Repository: mirror/firmware-mod-kit Branch: master Commit: 1ab09422186f Files: 5052 Total size: 26.2 MB Directory structure: gitextract_dkpulien/ ├── build-firmware.sh ├── check_for_upgrade.sh ├── cleanup.sh ├── creating_ipkg_packages.htm ├── ddwrt-gui-extract.sh ├── ddwrt-gui-rebuild.sh ├── extract-firmware.sh ├── firmware_mod_kit.htm ├── firmware_mod_kit_version.txt ├── ipk_template/ │ ├── conffiles │ ├── control │ ├── debian_binary │ └── make_ipk.sh ├── ipkg_install.sh ├── ipkg_install_all.sh ├── ipkg_remove.sh ├── ipkg_remove_all.sh ├── old-build.sh ├── old-extract.sh ├── shared-ng.inc ├── shared.inc ├── src/ │ ├── Makefile.in │ ├── addpattern.c │ ├── asustrx.c │ ├── bff/ │ │ ├── Makefile │ │ ├── bff_huffman_decompress.c │ │ └── bffxtractor.py │ ├── binwalk-0.4.1/ │ │ ├── docs/ │ │ │ └── README │ │ └── src/ │ │ ├── Makefile.in │ │ ├── binwalk.c │ │ ├── binwalk.h │ │ ├── common.c │ │ ├── common.h │ │ ├── configure │ │ ├── configure.ac │ │ ├── filter.c │ │ ├── filter.h │ │ ├── magic/ │ │ │ ├── magic.archives │ │ │ ├── magic.bootloaders │ │ │ ├── magic.compressed │ │ │ ├── magic.executables │ │ │ ├── magic.filesystems │ │ │ ├── magic.firmware │ │ │ └── magic.kernels │ │ ├── magic.binarch │ │ ├── magic.bincast │ │ ├── magic.binwalk │ │ ├── md5.c │ │ ├── md5.h │ │ ├── mparse.c │ │ ├── mparse.h │ │ ├── update.c │ │ └── update.h │ ├── binwalk-1.0/ │ │ ├── docs/ │ │ │ ├── API │ │ │ ├── COPYING │ │ │ └── README │ │ └── src/ │ │ ├── bin/ │ │ │ └── binwalk-script │ │ ├── binwalk/ │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── config/ │ │ │ │ └── extract.conf │ │ │ ├── config.py │ │ │ ├── extractor.py │ │ │ ├── filter.py │ │ │ ├── magic/ │ │ │ │ ├── binarch │ │ │ │ ├── bincast │ │ │ │ └── binwalk │ │ │ ├── parser.py │ │ │ ├── prettyprint.py │ │ │ ├── smartsig.py │ │ │ └── update.py │ │ ├── build/ │ │ │ ├── lib.linux-x86_64-2.7/ │ │ │ │ └── binwalk/ │ │ │ │ ├── __init__.py │ │ │ │ ├── common.py │ │ │ │ ├── config/ │ │ │ │ │ └── extract.conf │ │ │ │ ├── config.py │ │ │ │ ├── extractor.py │ │ │ │ ├── filter.py │ │ │ │ ├── magic/ │ │ │ │ │ ├── binarch │ │ │ │ │ ├── bincast │ │ │ │ │ └── binwalk │ │ │ │ ├── parser.py │ │ │ │ ├── prettyprint.py │ │ │ │ ├── smartsig.py │ │ │ │ └── update.py │ │ │ └── scripts-2.7/ │ │ │ └── binwalk │ │ ├── magic/ │ │ │ ├── archives │ │ │ ├── bootloaders │ │ │ ├── compressed │ │ │ ├── crypto │ │ │ ├── executables │ │ │ ├── filesystems │ │ │ ├── firmware │ │ │ ├── images │ │ │ ├── kernels │ │ │ ├── lzma │ │ │ └── sql │ │ ├── setup.py │ │ └── support/ │ │ └── lzma_gen.py │ ├── configure │ ├── configure.ac │ ├── cramfs-2.x/ │ │ ├── COPYING │ │ ├── GNUmakefile │ │ ├── NOTES │ │ ├── README │ │ ├── cramfsck.c │ │ ├── linux/ │ │ │ ├── cramfs_fs.h │ │ │ └── cramfs_fs_sb.h │ │ └── mkcramfs.c │ ├── cramfsswap/ │ │ ├── COPYING │ │ ├── Makefile │ │ ├── README │ │ ├── cramfsswap.1 │ │ ├── cramfsswap.c │ │ └── debian/ │ │ ├── changelog │ │ ├── compat │ │ ├── control │ │ ├── copyright │ │ ├── dirs │ │ ├── docs │ │ └── rules │ ├── crcalc/ │ │ ├── Makefile │ │ ├── README │ │ ├── crc.c │ │ ├── crc.h │ │ ├── crcalc.c │ │ ├── crcalc.h │ │ ├── md5.c │ │ ├── md5.h │ │ ├── patch.c │ │ └── patch.h │ ├── firmware-tools/ │ │ ├── Makefile │ │ ├── add_header.c │ │ ├── addpattern.c │ │ ├── airlink.c │ │ ├── bcm_tag.h │ │ ├── buffalo-enc.c │ │ ├── buffalo-lib.c │ │ ├── buffalo-lib.h │ │ ├── buffalo-tag.c │ │ ├── buffalo-tftp.c │ │ ├── csysimg.h │ │ ├── cyg_crc.h │ │ ├── cyg_crc16.c │ │ ├── cyg_crc32.c │ │ ├── dgfirmware.c │ │ ├── encode_crc.c │ │ ├── fix-u-media-header.c │ │ ├── fw.h │ │ ├── imagetag.c │ │ ├── imagetag.ggo │ │ ├── imagetag_cmdline.c │ │ ├── imagetag_cmdline.h │ │ ├── lzma2eva.c │ │ ├── makeamitbin.c │ │ ├── md5.c │ │ ├── md5.h │ │ ├── mkbrncmdline.c │ │ ├── mkbrnimg.c │ │ ├── mkcameofw.c │ │ ├── mkcasfw.c │ │ ├── mkchkimg.c │ │ ├── mkcsysimg.c │ │ ├── mkdapimg.c │ │ ├── mkdir615h1.c │ │ ├── mkdniimg.c │ │ ├── mkedimaximg.c │ │ ├── mkfwimage.c │ │ ├── mkfwimage2.c │ │ ├── mkmylofw.c │ │ ├── mkplanexfw.c │ │ ├── mktitanimg.c │ │ ├── mktitanimg.h │ │ ├── mktplinkfw.c │ │ ├── mkwrgimg.c │ │ ├── mkzcfw.c │ │ ├── mkzynfw.c │ │ ├── motorola-bin.c │ │ ├── myloader.h │ │ ├── nand_ecc.c │ │ ├── osbridge-crc.c │ │ ├── pc1crypt.c │ │ ├── ptgen.c │ │ ├── readme.txt │ │ ├── seama.c │ │ ├── seama.h │ │ ├── sha1.c │ │ ├── sha1.h │ │ ├── spw303v.c │ │ ├── srec2bin.c │ │ ├── trx.c │ │ ├── trx2edips.c │ │ ├── trx2usr.c │ │ ├── wndr3700.c │ │ ├── wrt400n.c │ │ ├── xorimage.c │ │ └── zynos.h │ ├── jffs2/ │ │ ├── mkfs.jffs2 │ │ └── unjffs2 │ ├── lzma/ │ │ ├── .built │ │ ├── .unpacked │ │ ├── 7zC.txt │ │ ├── 7zFormat.txt │ │ ├── C/ │ │ │ ├── 7zip/ │ │ │ │ ├── Archive/ │ │ │ │ │ └── 7z_C/ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ ├── 7zTypes.h │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ ├── makefile │ │ │ │ │ └── makefile.gcc │ │ │ │ ├── Common/ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ └── StreamUtils.h │ │ │ │ ├── Compress/ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ ├── BinTree/ │ │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ │ ├── BinTree4b.h │ │ │ │ │ │ │ └── BinTreeMain.h │ │ │ │ │ │ ├── HashChain/ │ │ │ │ │ │ │ ├── HC.h │ │ │ │ │ │ │ ├── HC2.h │ │ │ │ │ │ │ ├── HC3.h │ │ │ │ │ │ │ ├── HC4.h │ │ │ │ │ │ │ ├── HC4b.h │ │ │ │ │ │ │ └── HCMain.h │ │ │ │ │ │ ├── IMatchFinder.h │ │ │ │ │ │ ├── LZInWindow.cpp │ │ │ │ │ │ ├── LZInWindow.h │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ ├── Patricia/ │ │ │ │ │ │ │ ├── Pat.h │ │ │ │ │ │ │ ├── Pat2.h │ │ │ │ │ │ │ ├── Pat2H.h │ │ │ │ │ │ │ ├── Pat2R.h │ │ │ │ │ │ │ ├── Pat3H.h │ │ │ │ │ │ │ ├── Pat4H.h │ │ │ │ │ │ │ └── PatMain.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── LZMA_C/ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── LZMA_Lib/ │ │ │ │ │ │ ├── ZLib.cpp │ │ │ │ │ │ └── makefile │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ └── StdAfx.h │ │ │ │ ├── ICoder.h │ │ │ │ └── IStream.h │ │ │ ├── Common/ │ │ │ │ ├── Alloc.cpp │ │ │ │ ├── Alloc.h │ │ │ │ ├── CRC.cpp │ │ │ │ ├── CRC.h │ │ │ │ ├── C_FileIO.cpp │ │ │ │ ├── C_FileIO.h │ │ │ │ ├── ComTry.h │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ ├── CommandLineParser.h │ │ │ │ ├── Defs.h │ │ │ │ ├── MyCom.h │ │ │ │ ├── MyGuidDef.h │ │ │ │ ├── MyInitGuid.h │ │ │ │ ├── MyUnknown.h │ │ │ │ ├── MyWindows.h │ │ │ │ ├── NewHandler.cpp │ │ │ │ ├── NewHandler.h │ │ │ │ ├── StdAfx.h │ │ │ │ ├── String.cpp │ │ │ │ ├── String.h │ │ │ │ ├── StringConvert.cpp │ │ │ │ ├── StringConvert.h │ │ │ │ ├── StringToInt.cpp │ │ │ │ ├── StringToInt.h │ │ │ │ ├── Types.h │ │ │ │ ├── Vector.cpp │ │ │ │ └── Vector.h │ │ │ └── Windows/ │ │ │ ├── Defs.h │ │ │ ├── FileIO.cpp │ │ │ ├── FileIO.h │ │ │ └── StdAfx.h │ │ ├── CPL.html │ │ ├── CS/ │ │ │ └── 7zip/ │ │ │ ├── Common/ │ │ │ │ ├── CRC.cs │ │ │ │ ├── CommandLineParser.cs │ │ │ │ ├── InBuffer.cs │ │ │ │ └── OutBuffer.cs │ │ │ ├── Compress/ │ │ │ │ ├── LZ/ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ ├── LZMA/ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ └── Properties/ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ ├── Resources.cs │ │ │ │ │ └── Settings.cs │ │ │ │ └── RangeCoder/ │ │ │ │ ├── RangeCoder.cs │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ └── RangeCoderBitTree.cs │ │ │ └── ICoder.cs │ │ ├── Java/ │ │ │ └── SevenZip/ │ │ │ ├── CRC.java │ │ │ ├── Compression/ │ │ │ │ ├── ICodeProgress.java │ │ │ │ ├── LZ/ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ ├── InWindow.java │ │ │ │ │ └── OutWindow.java │ │ │ │ ├── LZMA/ │ │ │ │ │ ├── Base.java │ │ │ │ │ ├── Decoder.java │ │ │ │ │ └── Encoder.java │ │ │ │ └── RangeCoder/ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ ├── Decoder.java │ │ │ │ └── Encoder.java │ │ │ ├── LzmaAlone.java │ │ │ └── LzmaBench.java │ │ ├── LGPL.txt │ │ ├── Methods.txt │ │ ├── history.txt │ │ └── lzma.txt │ ├── motorola-bin.c │ ├── others/ │ │ ├── Makefile │ │ ├── squashfs-2.0-nb4/ │ │ │ ├── Makefile │ │ │ ├── nb4-mksquashfs/ │ │ │ │ ├── Makefile │ │ │ │ ├── getdelim.c │ │ │ │ ├── getdelim.h │ │ │ │ ├── getline.c │ │ │ │ ├── getline.h │ │ │ │ ├── lzma/ │ │ │ │ │ ├── compress/ │ │ │ │ │ │ ├── 7z.h │ │ │ │ │ │ ├── 7zapi.cpp │ │ │ │ │ │ ├── 7zapi.h │ │ │ │ │ │ ├── 7zlzma.cpp │ │ │ │ │ │ ├── AriBitCoder.cpp │ │ │ │ │ │ ├── AriBitCoder.h │ │ │ │ │ │ ├── AriConst.h │ │ │ │ │ │ ├── AriPrice.h │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ ├── BinTree2Main.h │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ ├── BinTree3Main.h │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ ├── BinTree3ZMain.h │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ ├── BinTree4Main.h │ │ │ │ │ │ ├── BinTree4b.h │ │ │ │ │ │ ├── BinTree4bMain.h │ │ │ │ │ │ ├── BinTreeMF.h │ │ │ │ │ │ ├── BinTreeMFMain.h │ │ │ │ │ │ ├── BinTreeMain.h │ │ │ │ │ │ ├── BitTreeCoder.h │ │ │ │ │ │ ├── CRC.h │ │ │ │ │ │ ├── Const.h │ │ │ │ │ │ ├── IInOutStreams.cpp │ │ │ │ │ │ ├── IInOutStreams.h │ │ │ │ │ │ ├── InByte.cpp │ │ │ │ │ │ ├── InByte.h │ │ │ │ │ │ ├── LZMA.cpp │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ ├── LenCoder.cpp │ │ │ │ │ │ ├── LenCoder.h │ │ │ │ │ │ ├── LiteralCoder.cpp │ │ │ │ │ │ ├── LiteralCoder.h │ │ │ │ │ │ ├── OutByte.cpp │ │ │ │ │ │ ├── OutByte.h │ │ │ │ │ │ ├── Portable.h │ │ │ │ │ │ ├── RCDefs.h │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── WindowIn.cpp │ │ │ │ │ │ ├── WindowIn.h │ │ │ │ │ │ ├── WindowOut.cpp │ │ │ │ │ │ ├── WindowOut.h │ │ │ │ │ │ └── lzDecomp.cpp │ │ │ │ │ └── decompress/ │ │ │ │ │ ├── 7z.h │ │ │ │ │ ├── 7zlzma.c │ │ │ │ │ ├── AriBitCoder.h │ │ │ │ │ ├── BitTreeCoder.h │ │ │ │ │ ├── IInOutStreams.c │ │ │ │ │ ├── IInOutStreams.h │ │ │ │ │ ├── LZMA.h │ │ │ │ │ ├── LZMADecoder.c │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ ├── LenCoder.h │ │ │ │ │ ├── LiteralCoder.h │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── Portable.h │ │ │ │ │ ├── RCDefs.h │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ ├── WindowOut.h │ │ │ │ │ └── vxTypesOld.h │ │ │ │ └── squashfs/ │ │ │ │ ├── Makefile │ │ │ │ ├── mksquashfs.c │ │ │ │ ├── mksquashfs.h │ │ │ │ ├── read_fs.c │ │ │ │ ├── read_fs.h │ │ │ │ ├── sort.c │ │ │ │ ├── squashfs_fs.h │ │ │ │ ├── squashfs_fs_i.h │ │ │ │ └── squashfs_fs_sb.h │ │ │ └── nb4-unsquashfs/ │ │ │ ├── Makefile │ │ │ ├── README │ │ │ ├── brcm-lzma/ │ │ │ │ ├── 7z.h │ │ │ │ ├── 7zlzma.c │ │ │ │ ├── AriBitCoder.h │ │ │ │ ├── BitTreeCoder.h │ │ │ │ ├── IInOutStreams.c │ │ │ │ ├── IInOutStreams.h │ │ │ │ ├── LZMA.h │ │ │ │ ├── LZMADecoder.c │ │ │ │ ├── LZMADecoder.h │ │ │ │ ├── LenCoder.h │ │ │ │ ├── LiteralCoder.h │ │ │ │ ├── Makefile │ │ │ │ ├── Portable.h │ │ │ │ ├── RCDefs.h │ │ │ │ ├── RangeCoder.h │ │ │ │ ├── WindowOut.h │ │ │ │ └── vxTypesOld.h │ │ │ ├── global.h │ │ │ ├── nb4-unsquash.c │ │ │ ├── read_fs.h │ │ │ └── squashfs_fs.h │ │ ├── squashfs-3.0-e2100/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── lzma/ │ │ │ │ ├── .built │ │ │ │ ├── .unpacked │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ └── 7z_C/ │ │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ │ │ ├── 7zTypes.h │ │ │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ └── StreamUtils.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ │ ├── BinTree/ │ │ │ │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ │ │ │ ├── BinTree4b.h │ │ │ │ │ │ │ │ │ └── BinTreeMain.h │ │ │ │ │ │ │ │ ├── HashChain/ │ │ │ │ │ │ │ │ │ ├── HC.h │ │ │ │ │ │ │ │ │ ├── HC2.h │ │ │ │ │ │ │ │ │ ├── HC3.h │ │ │ │ │ │ │ │ │ ├── HC4.h │ │ │ │ │ │ │ │ │ ├── HC4b.h │ │ │ │ │ │ │ │ │ └── HCMain.h │ │ │ │ │ │ │ │ ├── IMatchFinder.h │ │ │ │ │ │ │ │ ├── LZInWindow.cpp │ │ │ │ │ │ │ │ ├── LZInWindow.h │ │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ │ ├── Patricia/ │ │ │ │ │ │ │ │ │ ├── Pat.h │ │ │ │ │ │ │ │ │ ├── Pat2.h │ │ │ │ │ │ │ │ │ ├── Pat2H.h │ │ │ │ │ │ │ │ │ ├── Pat2R.h │ │ │ │ │ │ │ │ │ ├── Pat3H.h │ │ │ │ │ │ │ │ │ ├── Pat4H.h │ │ │ │ │ │ │ │ │ └── PatMain.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LZMA_C/ │ │ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LZMA_Lib/ │ │ │ │ │ │ │ │ ├── ZLib.cpp │ │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ └── IStream.h │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── Alloc.cpp │ │ │ │ │ │ ├── Alloc.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── CRC.h │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── String.cpp │ │ │ │ │ │ ├── String.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── Vector.cpp │ │ │ │ │ │ └── Vector.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ └── StdAfx.h │ │ │ │ ├── CPL.html │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── LGPL.txt │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.2-r2/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.2-r2-hg612-lzma/ │ │ │ ├── Makefile │ │ │ ├── lzma443/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ └── 7z_C/ │ │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ │ │ ├── 7zTypes.h │ │ │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ └── StreamUtils.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ │ │ ├── BranchTypes.h │ │ │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ │ ├── BinTree/ │ │ │ │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ │ │ │ └── BinTreeMain.h │ │ │ │ │ │ │ │ ├── HashChain/ │ │ │ │ │ │ │ │ │ ├── HC2.h │ │ │ │ │ │ │ │ │ ├── HC3.h │ │ │ │ │ │ │ │ │ ├── HC4.h │ │ │ │ │ │ │ │ │ └── HCMain.h │ │ │ │ │ │ │ │ ├── IMatchFinder.h │ │ │ │ │ │ │ │ ├── LZInWindow.cpp │ │ │ │ │ │ │ │ ├── LZInWindow.h │ │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── comp.cc │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ │ └── sqlzma.mk │ │ │ │ │ │ │ ├── LZMA_C/ │ │ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ │ │ ├── LzmaTypes.h │ │ │ │ │ │ │ │ ├── kmod/ │ │ │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ │ │ └── module.c │ │ │ │ │ │ │ │ ├── kmod.mk │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ │ ├── sqlzma.mk │ │ │ │ │ │ │ │ ├── testflags.c │ │ │ │ │ │ │ │ └── uncomp.c │ │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ └── IStream.h │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── Alloc.cpp │ │ │ │ │ │ ├── Alloc.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── CRC.h │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── String.cpp │ │ │ │ │ │ ├── String.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── Vector.cpp │ │ │ │ │ │ └── Vector.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ └── StdAfx.h │ │ │ │ ├── CPL.html │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── LGPL.txt │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ ├── lzma.txt │ │ │ │ └── sqlzma1-443.patch │ │ │ ├── sqlzma.h │ │ │ ├── sqmagic.h │ │ │ └── squashfs3.2-r2/ │ │ │ ├── ACKNOWLEDGEMENTS │ │ │ ├── CHANGES │ │ │ ├── COPYING │ │ │ ├── INSTALL │ │ │ ├── PERFORMANCE.README │ │ │ ├── README │ │ │ ├── README-3.2 │ │ │ ├── sqlzma2u-3.2-r2.patch │ │ │ └── squashfs-tools/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.2-r2-lzma/ │ │ │ ├── C/ │ │ │ │ ├── 7zCrc.c │ │ │ │ ├── 7zCrc.h │ │ │ │ ├── 7zCrcT8.c │ │ │ │ ├── Alloc.c │ │ │ │ ├── Alloc.h │ │ │ │ ├── Archive/ │ │ │ │ │ └── 7z/ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ ├── makefile │ │ │ │ │ └── makefile.gcc │ │ │ │ ├── Compress/ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ ├── BranchTypes.h │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ ├── BranchX86_2.c │ │ │ │ │ │ └── BranchX86_2.h │ │ │ │ │ ├── Huffman/ │ │ │ │ │ │ ├── HuffmanEncode.c │ │ │ │ │ │ └── HuffmanEncode.h │ │ │ │ │ ├── Lz/ │ │ │ │ │ │ ├── LzHash.h │ │ │ │ │ │ ├── MatchFinder.c │ │ │ │ │ │ ├── MatchFinder.h │ │ │ │ │ │ ├── MatchFinderMt.c │ │ │ │ │ │ └── MatchFinderMt.h │ │ │ │ │ └── Lzma/ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ ├── LzmaTypes.h │ │ │ │ │ ├── kmod/ │ │ │ │ │ │ └── uncomp.c │ │ │ │ │ ├── kmod.mk │ │ │ │ │ ├── sqlzma.mk │ │ │ │ │ ├── testflags.c │ │ │ │ │ └── uncomp.c │ │ │ │ ├── CpuArch.h │ │ │ │ ├── IStream.h │ │ │ │ ├── Sort.c │ │ │ │ ├── Sort.h │ │ │ │ ├── Threads.c │ │ │ │ ├── Threads.h │ │ │ │ └── Types.h │ │ │ ├── CPP/ │ │ │ │ ├── 7zip/ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ └── ParseProperties.h │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ └── IArchive.h │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ ├── BCJ2Register.cpp │ │ │ │ │ │ │ ├── BCJRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ ├── ByteSwap/ │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ ├── Copy/ │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ ├── LZMARegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── comp.cc │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ └── sqlzma.mk │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── ICoder.h │ │ │ │ │ ├── IDecl.h │ │ │ │ │ ├── IPassword.h │ │ │ │ │ ├── IProgress.h │ │ │ │ │ ├── IStream.h │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ ├── PropID.h │ │ │ │ │ └── UI/ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ └── Console/ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ ├── List.cpp │ │ │ │ │ ├── List.h │ │ │ │ │ ├── Main.cpp │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ └── afxres.h │ │ │ │ ├── Build.mak │ │ │ │ ├── Common/ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ ├── Buffer.h │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ ├── ComTry.h │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ ├── IntToString.h │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ ├── MyCom.h │ │ │ │ │ ├── MyException.h │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ ├── MyString.h │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ ├── MyVector.h │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ ├── Types.h │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ └── Wildcard.h │ │ │ │ └── Windows/ │ │ │ │ ├── DLL.cpp │ │ │ │ ├── DLL.h │ │ │ │ ├── Defs.h │ │ │ │ ├── Error.cpp │ │ │ │ ├── Error.h │ │ │ │ ├── FileDir.cpp │ │ │ │ ├── FileDir.h │ │ │ │ ├── FileFind.cpp │ │ │ │ ├── FileFind.h │ │ │ │ ├── FileIO.cpp │ │ │ │ ├── FileIO.h │ │ │ │ ├── FileMapping.cpp │ │ │ │ ├── FileMapping.h │ │ │ │ ├── FileName.cpp │ │ │ │ ├── FileName.h │ │ │ │ ├── Handle.h │ │ │ │ ├── MemoryLock.cpp │ │ │ │ ├── MemoryLock.h │ │ │ │ ├── PropVariant.cpp │ │ │ │ ├── PropVariant.h │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ ├── PropVariantConversions.h │ │ │ │ ├── StdAfx.h │ │ │ │ ├── Synchronization.cpp │ │ │ │ ├── Synchronization.h │ │ │ │ ├── System.cpp │ │ │ │ ├── System.h │ │ │ │ ├── Thread.h │ │ │ │ └── Time.h │ │ │ ├── Makefile │ │ │ ├── sqlzma.h │ │ │ ├── sqmagic.h │ │ │ └── squashfs3.2-r2/ │ │ │ ├── ACKNOWLEDGEMENTS │ │ │ ├── CHANGES │ │ │ ├── COPYING │ │ │ ├── INSTALL │ │ │ ├── OLD-READMEs/ │ │ │ │ ├── README-2.0 │ │ │ │ ├── README-2.1 │ │ │ │ ├── README-3.0 │ │ │ │ ├── README-3.1 │ │ │ │ └── README-AMD64 │ │ │ ├── PERFORMANCE.README │ │ │ ├── README │ │ │ ├── README-3.2 │ │ │ ├── sqlzma2u-3.2-r2.patch │ │ │ └── squashfs-tools/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.2-r2-rtn12/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── lzma_src/ │ │ │ │ └── C/ │ │ │ │ ├── Alloc.h │ │ │ │ ├── LzFind.c │ │ │ │ ├── LzFind.h │ │ │ │ ├── LzHash.h │ │ │ │ ├── LzmaDec.c │ │ │ │ ├── LzmaDec.h │ │ │ │ ├── LzmaEnc.c │ │ │ │ ├── LzmaEnc.h │ │ │ │ └── Types.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── sqlzma.c │ │ │ ├── sqlzma.h │ │ │ ├── sqmagic.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.2-r2-wnr1000/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── lzma_src/ │ │ │ │ └── C/ │ │ │ │ ├── Alloc.h │ │ │ │ ├── LzFind.c │ │ │ │ ├── LzFind.h │ │ │ │ ├── LzHash.h │ │ │ │ ├── LzmaDec.c │ │ │ │ ├── LzmaDec.h │ │ │ │ ├── LzmaEnc.c │ │ │ │ ├── LzmaEnc.h │ │ │ │ └── Types.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── sqlzma.c │ │ │ ├── sqlzma.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.3/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── sqmagic.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.3-grml-lzma/ │ │ │ ├── .tmpdeps │ │ │ ├── .topdeps │ │ │ ├── .topmsg │ │ │ ├── Makefile │ │ │ ├── debian/ │ │ │ │ ├── changelog │ │ │ │ ├── compat │ │ │ │ ├── control │ │ │ │ ├── control.modules.in │ │ │ │ ├── copyright │ │ │ │ ├── doc/ │ │ │ │ │ ├── en/ │ │ │ │ │ │ ├── mksquashfs.dbk │ │ │ │ │ │ └── unsquashfs.dbk │ │ │ │ │ └── po/ │ │ │ │ │ ├── mksquashfs.fr.add │ │ │ │ │ ├── mksquashfs.fr.po │ │ │ │ │ ├── mksquashfs.pot │ │ │ │ │ └── po4a.cfg │ │ │ │ ├── rules │ │ │ │ ├── rules.modules │ │ │ │ ├── squashfs-lzma-source.NEWS │ │ │ │ ├── squashfs-lzma-source.README.Debian │ │ │ │ ├── squashfs-lzma-source.docs │ │ │ │ ├── squashfs-lzma-source.links │ │ │ │ ├── squashfs-lzma-tools.README.Debian │ │ │ │ ├── squashfs-lzma-tools.dirs │ │ │ │ ├── squashfs-lzma-tools.install │ │ │ │ ├── squashfs-lzma-tools.manpages │ │ │ │ └── watch │ │ │ ├── ksquashfs/ │ │ │ │ ├── fs/ │ │ │ │ │ └── squashfs/ │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── inode.c │ │ │ │ │ ├── squashfs.h │ │ │ │ │ └── squashfs2_0.c │ │ │ │ └── include/ │ │ │ │ └── linux/ │ │ │ │ ├── squashfs_fs.h │ │ │ │ ├── squashfs_fs_i.h │ │ │ │ └── squashfs_fs_sb.h │ │ │ ├── lzma/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zCrcT8.c │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ │ ├── BranchTypes.h │ │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ │ ├── BranchX86_2.c │ │ │ │ │ │ │ └── BranchX86_2.h │ │ │ │ │ │ ├── Huffman/ │ │ │ │ │ │ │ ├── HuffmanEncode.c │ │ │ │ │ │ │ └── HuffmanEncode.h │ │ │ │ │ │ ├── Lz/ │ │ │ │ │ │ │ ├── LzHash.h │ │ │ │ │ │ │ ├── MatchFinder.c │ │ │ │ │ │ │ ├── MatchFinder.h │ │ │ │ │ │ │ ├── MatchFinderMt.c │ │ │ │ │ │ │ └── MatchFinderMt.h │ │ │ │ │ │ └── Lzma/ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ ├── LzmaTypes.h │ │ │ │ │ │ ├── kmod/ │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ └── module.c │ │ │ │ │ │ ├── kmod.mk │ │ │ │ │ │ ├── sqlzma.mk │ │ │ │ │ │ ├── testflags.c │ │ │ │ │ │ └── uncomp.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── IStream.h │ │ │ │ │ ├── Sort.c │ │ │ │ │ ├── Sort.h │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ └── Types.h │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ └── ParseProperties.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ └── IArchive.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ │ ├── BCJ2Register.cpp │ │ │ │ │ │ │ │ ├── BCJRegister.cpp │ │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ │ ├── ByteSwap/ │ │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── Copy/ │ │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ │ ├── LZMARegister.cpp │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── comp.cc │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ │ └── sqlzma.mk │ │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── afxres.h │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── LGPL.txt │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── sqlzma.h │ │ │ ├── sqlzma.txt │ │ │ ├── sqlzma1-449.patch │ │ │ ├── sqlzma2k-3.3.patch │ │ │ ├── sqlzma2u-3.3.patch │ │ │ ├── sqmagic.h │ │ │ └── squashfs3.3/ │ │ │ ├── ACKNOWLEDGEMENTS │ │ │ ├── CHANGES │ │ │ ├── COPYING │ │ │ ├── INSTALL │ │ │ ├── OLD-READMEs/ │ │ │ │ ├── README-2.0 │ │ │ │ ├── README-2.1 │ │ │ │ ├── README-3.0 │ │ │ │ ├── README-3.1 │ │ │ │ ├── README-3.2 │ │ │ │ └── README-AMD64 │ │ │ ├── PERFORMANCE.README │ │ │ ├── README │ │ │ ├── README-3.3 │ │ │ ├── kernel-patches/ │ │ │ │ ├── linux-2.6.10/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.12/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.14/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.16/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.18/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.20/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.22/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.23/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.24/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ ├── linux-2.6.6/ │ │ │ │ │ └── squashfs3.3-patch │ │ │ │ └── linux-2.6.8.1/ │ │ │ │ └── squashfs3.3-patch │ │ │ └── squashfs-tools/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.3-lzma/ │ │ │ ├── C/ │ │ │ │ ├── 7zCrc.c │ │ │ │ ├── 7zCrc.h │ │ │ │ ├── 7zCrcT8.c │ │ │ │ ├── Alloc.c │ │ │ │ ├── Alloc.h │ │ │ │ ├── Archive/ │ │ │ │ │ └── 7z/ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ ├── makefile │ │ │ │ │ └── makefile.gcc │ │ │ │ ├── Compress/ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ ├── BranchTypes.h │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ ├── BranchX86_2.c │ │ │ │ │ │ └── BranchX86_2.h │ │ │ │ │ ├── Huffman/ │ │ │ │ │ │ ├── HuffmanEncode.c │ │ │ │ │ │ └── HuffmanEncode.h │ │ │ │ │ ├── Lz/ │ │ │ │ │ │ ├── LzHash.h │ │ │ │ │ │ ├── MatchFinder.c │ │ │ │ │ │ ├── MatchFinder.h │ │ │ │ │ │ ├── MatchFinderMt.c │ │ │ │ │ │ └── MatchFinderMt.h │ │ │ │ │ └── Lzma/ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ ├── LzmaTypes.h │ │ │ │ │ ├── kmod/ │ │ │ │ │ │ └── uncomp.c │ │ │ │ │ ├── kmod.mk │ │ │ │ │ ├── sqlzma.mk │ │ │ │ │ ├── testflags.c │ │ │ │ │ └── uncomp.c │ │ │ │ ├── CpuArch.h │ │ │ │ ├── IStream.h │ │ │ │ ├── Sort.c │ │ │ │ ├── Sort.h │ │ │ │ ├── Threads.c │ │ │ │ ├── Threads.h │ │ │ │ └── Types.h │ │ │ ├── CPP/ │ │ │ │ ├── 7zip/ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ └── ParseProperties.h │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ └── IArchive.h │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ ├── BCJ2Register.cpp │ │ │ │ │ │ │ ├── BCJRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ ├── ByteSwap/ │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ ├── Copy/ │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ ├── LZMARegister.cpp │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── comp.cc │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ └── sqlzma.mk │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── ICoder.h │ │ │ │ │ ├── IDecl.h │ │ │ │ │ ├── IPassword.h │ │ │ │ │ ├── IProgress.h │ │ │ │ │ ├── IStream.h │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ ├── PropID.h │ │ │ │ │ └── UI/ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ └── Console/ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ ├── List.cpp │ │ │ │ │ ├── List.h │ │ │ │ │ ├── Main.cpp │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ └── afxres.h │ │ │ │ ├── Build.mak │ │ │ │ ├── Common/ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ ├── Buffer.h │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ ├── ComTry.h │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ ├── IntToString.h │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ ├── MyCom.h │ │ │ │ │ ├── MyException.h │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ ├── MyString.h │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ ├── MyVector.h │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ ├── Types.h │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ └── Wildcard.h │ │ │ │ └── Windows/ │ │ │ │ ├── DLL.cpp │ │ │ │ ├── DLL.h │ │ │ │ ├── Defs.h │ │ │ │ ├── Error.cpp │ │ │ │ ├── Error.h │ │ │ │ ├── FileDir.cpp │ │ │ │ ├── FileDir.h │ │ │ │ ├── FileFind.cpp │ │ │ │ ├── FileFind.h │ │ │ │ ├── FileIO.cpp │ │ │ │ ├── FileIO.h │ │ │ │ ├── FileMapping.cpp │ │ │ │ ├── FileMapping.h │ │ │ │ ├── FileName.cpp │ │ │ │ ├── FileName.h │ │ │ │ ├── Handle.h │ │ │ │ ├── MemoryLock.cpp │ │ │ │ ├── MemoryLock.h │ │ │ │ ├── PropVariant.cpp │ │ │ │ ├── PropVariant.h │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ ├── PropVariantConversions.h │ │ │ │ ├── StdAfx.h │ │ │ │ ├── Synchronization.cpp │ │ │ │ ├── Synchronization.h │ │ │ │ ├── System.cpp │ │ │ │ ├── System.h │ │ │ │ ├── Thread.h │ │ │ │ └── Time.h │ │ │ ├── Makefile │ │ │ ├── sqlzma.h │ │ │ ├── sqmagic.h │ │ │ ├── squashfs3.3/ │ │ │ │ └── squashfs-tools/ │ │ │ │ ├── Makefile │ │ │ │ ├── global.h │ │ │ │ ├── mksquashfs.c │ │ │ │ ├── mksquashfs.h │ │ │ │ ├── read_fs.c │ │ │ │ ├── read_fs.h │ │ │ │ ├── sort.c │ │ │ │ ├── sort.h │ │ │ │ ├── squashfs_fs.h │ │ │ │ └── unsquashfs.c │ │ │ └── unuse/ │ │ │ ├── CS/ │ │ │ │ └── 7zip/ │ │ │ │ ├── Common/ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ └── OutBuffer.cs │ │ │ │ ├── Compress/ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ └── ICoder.cs │ │ │ └── Java/ │ │ │ └── SevenZip/ │ │ │ ├── CRC.java │ │ │ ├── Compression/ │ │ │ │ ├── LZ/ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ ├── InWindow.java │ │ │ │ │ └── OutWindow.java │ │ │ │ ├── LZMA/ │ │ │ │ │ ├── Base.java │ │ │ │ │ ├── Decoder.java │ │ │ │ │ └── Encoder.java │ │ │ │ └── RangeCoder/ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ ├── Decoder.java │ │ │ │ └── Encoder.java │ │ │ ├── ICodeProgress.java │ │ │ ├── LzmaAlone.java │ │ │ └── LzmaBench.java │ │ ├── squashfs-3.4-cisco/ │ │ │ ├── Makefile │ │ │ ├── lzma/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zBuf.c │ │ │ │ │ ├── 7zBuf.h │ │ │ │ │ ├── 7zBuf2.c │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zFile.c │ │ │ │ │ ├── 7zFile.h │ │ │ │ │ ├── 7zStream.c │ │ │ │ │ ├── 7zVersion.h │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7z.dsp │ │ │ │ │ │ ├── 7z.dsw │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Bcj2.c │ │ │ │ │ ├── Bcj2.h │ │ │ │ │ ├── Bra.c │ │ │ │ │ ├── Bra.h │ │ │ │ │ ├── Bra86.c │ │ │ │ │ ├── BraIA64.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── LzFind.c │ │ │ │ │ ├── LzFind.h │ │ │ │ │ ├── LzFindMt.c │ │ │ │ │ ├── LzFindMt.h │ │ │ │ │ ├── LzHash.h │ │ │ │ │ ├── LzmaDec.c │ │ │ │ │ ├── LzmaDec.h │ │ │ │ │ ├── LzmaEnc.c │ │ │ │ │ ├── LzmaEnc.h │ │ │ │ │ ├── LzmaLib/ │ │ │ │ │ │ ├── LzmaLib.def │ │ │ │ │ │ ├── LzmaLib.dsp │ │ │ │ │ │ ├── LzmaLib.dsw │ │ │ │ │ │ ├── LzmaLibExports.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── LzmaLib.c │ │ │ │ │ ├── LzmaLib.h │ │ │ │ │ ├── LzmaUtil/ │ │ │ │ │ │ ├── Lzma86Dec.c │ │ │ │ │ │ ├── Lzma86Dec.h │ │ │ │ │ │ ├── Lzma86Enc.c │ │ │ │ │ │ ├── Lzma86Enc.h │ │ │ │ │ │ ├── LzmaUtil.c │ │ │ │ │ │ ├── LzmaUtil.dsp │ │ │ │ │ │ ├── LzmaUtil.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ └── Types.h │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ ├── ParseProperties.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ ├── IArchive.h │ │ │ │ │ │ │ ├── Lzma/ │ │ │ │ │ │ │ │ ├── LzmaArcRegister.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.h │ │ │ │ │ │ │ │ ├── LzmaHandler.cpp │ │ │ │ │ │ │ │ ├── LzmaHandler.h │ │ │ │ │ │ │ │ ├── LzmaIn.cpp │ │ │ │ │ │ │ │ ├── LzmaIn.h │ │ │ │ │ │ │ │ ├── LzmaItem.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Split/ │ │ │ │ │ │ │ │ ├── SplitHandler.cpp │ │ │ │ │ │ │ │ ├── SplitHandler.h │ │ │ │ │ │ │ │ ├── SplitHandlerOut.cpp │ │ │ │ │ │ │ │ ├── SplitRegister.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Bcj2Coder.cpp │ │ │ │ │ │ │ ├── Bcj2Coder.h │ │ │ │ │ │ │ ├── Bcj2Register.cpp │ │ │ │ │ │ │ ├── BcjCoder.cpp │ │ │ │ │ │ │ ├── BcjCoder.h │ │ │ │ │ │ │ ├── BcjRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchMisc.cpp │ │ │ │ │ │ │ ├── BranchMisc.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LzmaDecoder.cpp │ │ │ │ │ │ │ ├── LzmaDecoder.h │ │ │ │ │ │ │ ├── LzmaEncoder.cpp │ │ │ │ │ │ │ ├── LzmaEncoder.h │ │ │ │ │ │ │ ├── LzmaRegister.cpp │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ ├── Time.cpp │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ ├── lzma.txt │ │ │ │ ├── lzma465.tar.bz2 │ │ │ │ └── patches/ │ │ │ │ └── lzma465-squashfs.patch │ │ │ └── squashfs-tools/ │ │ │ ├── Makefile │ │ │ ├── global.h │ │ │ ├── lzmainterface.c │ │ │ ├── lzmainterface.h │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_fs.h │ │ │ └── unsquashfs.c │ │ ├── squashfs-3.4-nb4/ │ │ │ ├── Makefile │ │ │ ├── README.txt │ │ │ ├── lzma465/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zBuf.c │ │ │ │ │ ├── 7zBuf.h │ │ │ │ │ ├── 7zBuf2.c │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zFile.c │ │ │ │ │ ├── 7zFile.h │ │ │ │ │ ├── 7zStream.c │ │ │ │ │ ├── 7zVersion.h │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7z.dsp │ │ │ │ │ │ ├── 7z.dsw │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Bcj2.c │ │ │ │ │ ├── Bcj2.h │ │ │ │ │ ├── Bra.c │ │ │ │ │ ├── Bra.h │ │ │ │ │ ├── Bra86.c │ │ │ │ │ ├── BraIA64.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── LzFind.c │ │ │ │ │ ├── LzFind.h │ │ │ │ │ ├── LzFindMt.c │ │ │ │ │ ├── LzFindMt.h │ │ │ │ │ ├── LzHash.h │ │ │ │ │ ├── LzmaDec.c │ │ │ │ │ ├── LzmaDec.h │ │ │ │ │ ├── LzmaEnc.c │ │ │ │ │ ├── LzmaEnc.h │ │ │ │ │ ├── LzmaLib/ │ │ │ │ │ │ ├── LzmaLib.def │ │ │ │ │ │ ├── LzmaLib.dsp │ │ │ │ │ │ ├── LzmaLib.dsw │ │ │ │ │ │ ├── LzmaLibExports.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── LzmaLib.c │ │ │ │ │ ├── LzmaLib.h │ │ │ │ │ ├── LzmaUtil/ │ │ │ │ │ │ ├── Lzma86Dec.c │ │ │ │ │ │ ├── Lzma86Dec.h │ │ │ │ │ │ ├── Lzma86Enc.c │ │ │ │ │ │ ├── Lzma86Enc.h │ │ │ │ │ │ ├── LzmaUtil.c │ │ │ │ │ │ ├── LzmaUtil.dsp │ │ │ │ │ │ ├── LzmaUtil.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ ├── Types.h │ │ │ │ │ ├── sqlzma.mk │ │ │ │ │ └── uncomp.c │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ ├── ParseProperties.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ ├── IArchive.h │ │ │ │ │ │ │ ├── Lzma/ │ │ │ │ │ │ │ │ ├── LzmaArcRegister.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.h │ │ │ │ │ │ │ │ ├── LzmaHandler.cpp │ │ │ │ │ │ │ │ ├── LzmaHandler.h │ │ │ │ │ │ │ │ ├── LzmaIn.cpp │ │ │ │ │ │ │ │ ├── LzmaIn.h │ │ │ │ │ │ │ │ ├── LzmaItem.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Split/ │ │ │ │ │ │ │ │ ├── SplitHandler.cpp │ │ │ │ │ │ │ │ ├── SplitHandler.h │ │ │ │ │ │ │ │ ├── SplitHandlerOut.cpp │ │ │ │ │ │ │ │ ├── SplitRegister.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Bcj2Coder.cpp │ │ │ │ │ │ │ ├── Bcj2Coder.h │ │ │ │ │ │ │ ├── Bcj2Register.cpp │ │ │ │ │ │ │ ├── BcjCoder.cpp │ │ │ │ │ │ │ ├── BcjCoder.h │ │ │ │ │ │ │ ├── BcjRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchMisc.cpp │ │ │ │ │ │ │ ├── BranchMisc.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── comp.cc │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ ├── makefile.gcc │ │ │ │ │ │ │ │ └── sqlzma.mk │ │ │ │ │ │ │ ├── LzmaDecoder.cpp │ │ │ │ │ │ │ ├── LzmaDecoder.h │ │ │ │ │ │ │ ├── LzmaEncoder.cpp │ │ │ │ │ │ │ ├── LzmaEncoder.h │ │ │ │ │ │ │ ├── LzmaRegister.cpp │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ ├── Time.cpp │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── mksquashfs │ │ │ ├── sqlzma.h │ │ │ ├── sqmagic.h │ │ │ ├── squashfs3.4/ │ │ │ │ ├── ACKNOWLEDGEMENTS │ │ │ │ ├── CHANGES │ │ │ │ ├── COPYING │ │ │ │ ├── INSTALL │ │ │ │ ├── OLD-READMEs/ │ │ │ │ │ ├── README-2.0 │ │ │ │ │ ├── README-2.1 │ │ │ │ │ ├── README-3.0 │ │ │ │ │ ├── README-3.1 │ │ │ │ │ ├── README-3.2 │ │ │ │ │ ├── README-3.3 │ │ │ │ │ └── README-AMD64 │ │ │ │ ├── PERFORMANCE.README │ │ │ │ ├── README │ │ │ │ ├── kernel-patches/ │ │ │ │ │ ├── README │ │ │ │ │ ├── linux-2.6.12/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.14/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.16/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.18/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.20/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.22/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.23/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.24/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.25/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.26/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ ├── linux-2.6.27-rc4/ │ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ │ └── linux-2.6.27-rc4-next/ │ │ │ │ │ └── squashfs3.4-patch │ │ │ │ └── squashfs-tools/ │ │ │ │ ├── Makefile │ │ │ │ ├── global.h │ │ │ │ ├── mksquashfs.c │ │ │ │ ├── mksquashfs.h │ │ │ │ ├── read_fs.c │ │ │ │ ├── read_fs.h │ │ │ │ ├── sort.c │ │ │ │ ├── sort.h │ │ │ │ ├── squashfs_fs.h │ │ │ │ └── unsquashfs.c │ │ │ └── unsquashfs-lzma │ │ ├── squashfs-4.0-lzma/ │ │ │ ├── Makefile │ │ │ ├── README-4.0 │ │ │ ├── global.h │ │ │ ├── lzma/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zBuf.c │ │ │ │ │ ├── 7zBuf.h │ │ │ │ │ ├── 7zBuf2.c │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zFile.c │ │ │ │ │ ├── 7zFile.h │ │ │ │ │ ├── 7zStream.c │ │ │ │ │ ├── 7zVersion.h │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7z.dsp │ │ │ │ │ │ ├── 7z.dsw │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Bcj2.c │ │ │ │ │ ├── Bcj2.h │ │ │ │ │ ├── Bra.c │ │ │ │ │ ├── Bra.h │ │ │ │ │ ├── Bra86.c │ │ │ │ │ ├── BraIA64.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── LzFind.c │ │ │ │ │ ├── LzFind.h │ │ │ │ │ ├── LzFindMt.c │ │ │ │ │ ├── LzFindMt.h │ │ │ │ │ ├── LzHash.h │ │ │ │ │ ├── LzmaDec.c │ │ │ │ │ ├── LzmaDec.h │ │ │ │ │ ├── LzmaEnc.c │ │ │ │ │ ├── LzmaEnc.h │ │ │ │ │ ├── LzmaLib/ │ │ │ │ │ │ ├── LzmaLib.def │ │ │ │ │ │ ├── LzmaLib.dsp │ │ │ │ │ │ ├── LzmaLib.dsw │ │ │ │ │ │ ├── LzmaLibExports.c │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── LzmaLib.c │ │ │ │ │ ├── LzmaLib.h │ │ │ │ │ ├── LzmaUtil/ │ │ │ │ │ │ ├── Lzma86Dec.c │ │ │ │ │ │ ├── Lzma86Dec.h │ │ │ │ │ │ ├── Lzma86Enc.c │ │ │ │ │ │ ├── Lzma86Enc.h │ │ │ │ │ │ ├── LzmaUtil.c │ │ │ │ │ │ ├── LzmaUtil.dsp │ │ │ │ │ │ ├── LzmaUtil.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ └── Types.h │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ ├── ParseProperties.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ ├── IArchive.h │ │ │ │ │ │ │ ├── Lzma/ │ │ │ │ │ │ │ │ ├── LzmaArcRegister.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.h │ │ │ │ │ │ │ │ ├── LzmaHandler.cpp │ │ │ │ │ │ │ │ ├── LzmaHandler.h │ │ │ │ │ │ │ │ ├── LzmaIn.cpp │ │ │ │ │ │ │ │ ├── LzmaIn.h │ │ │ │ │ │ │ │ ├── LzmaItem.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Split/ │ │ │ │ │ │ │ │ ├── SplitHandler.cpp │ │ │ │ │ │ │ │ ├── SplitHandler.h │ │ │ │ │ │ │ │ ├── SplitHandlerOut.cpp │ │ │ │ │ │ │ │ ├── SplitRegister.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Bcj2Coder.cpp │ │ │ │ │ │ │ ├── Bcj2Coder.h │ │ │ │ │ │ │ ├── Bcj2Register.cpp │ │ │ │ │ │ │ ├── BcjCoder.cpp │ │ │ │ │ │ │ ├── BcjCoder.h │ │ │ │ │ │ │ ├── BcjRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchMisc.cpp │ │ │ │ │ │ │ ├── BranchMisc.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LzmaDecoder.cpp │ │ │ │ │ │ │ ├── LzmaDecoder.h │ │ │ │ │ │ │ ├── LzmaEncoder.cpp │ │ │ │ │ │ │ ├── LzmaEncoder.h │ │ │ │ │ │ │ ├── LzmaRegister.cpp │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ ├── Time.cpp │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.c.orig │ │ │ ├── mksquashfs.h │ │ │ ├── pseudo.c │ │ │ ├── pseudo.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_compat.h │ │ │ ├── squashfs_fs.h │ │ │ ├── squashfs_swap.h │ │ │ ├── swap.c │ │ │ ├── uncompress.c │ │ │ ├── uncompress.h │ │ │ ├── unsquash-1.c │ │ │ ├── unsquash-2.c │ │ │ ├── unsquash-3.c │ │ │ ├── unsquash-4.c │ │ │ ├── unsquashfs.c │ │ │ └── unsquashfs.h │ │ ├── squashfs-4.0-realtek/ │ │ │ ├── Makefile │ │ │ ├── compressor.c │ │ │ ├── compressor.h │ │ │ ├── global.h │ │ │ ├── gzip_wrapper.c │ │ │ ├── lzma/ │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zBuf.c │ │ │ │ │ ├── 7zBuf.h │ │ │ │ │ ├── 7zBuf2.c │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zFile.c │ │ │ │ │ ├── 7zFile.h │ │ │ │ │ ├── 7zStream.c │ │ │ │ │ ├── 7zVersion.h │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7z.dsp │ │ │ │ │ │ ├── 7z.dsw │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Bcj2.c │ │ │ │ │ ├── Bcj2.h │ │ │ │ │ ├── Bra.c │ │ │ │ │ ├── Bra.h │ │ │ │ │ ├── Bra86.c │ │ │ │ │ ├── BraIA64.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── LzFind.c │ │ │ │ │ ├── LzFind.h │ │ │ │ │ ├── LzFindMt.c │ │ │ │ │ ├── LzFindMt.h │ │ │ │ │ ├── LzHash.h │ │ │ │ │ ├── LzmaDec.c │ │ │ │ │ ├── LzmaDec.h │ │ │ │ │ ├── LzmaEnc.c │ │ │ │ │ ├── LzmaEnc.h │ │ │ │ │ ├── LzmaLib/ │ │ │ │ │ │ ├── LzmaLib.def │ │ │ │ │ │ ├── LzmaLib.dsp │ │ │ │ │ │ ├── LzmaLib.dsw │ │ │ │ │ │ ├── LzmaLibExports.c │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── LzmaLib.c │ │ │ │ │ ├── LzmaLib.h │ │ │ │ │ ├── LzmaUtil/ │ │ │ │ │ │ ├── Lzma86Dec.c │ │ │ │ │ │ ├── Lzma86Dec.h │ │ │ │ │ │ ├── Lzma86Enc.c │ │ │ │ │ │ ├── Lzma86Enc.h │ │ │ │ │ │ ├── LzmaUtil.c │ │ │ │ │ │ ├── LzmaUtil.dsp │ │ │ │ │ │ ├── LzmaUtil.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ └── Types.h │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ ├── ParseProperties.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ ├── IArchive.h │ │ │ │ │ │ │ ├── Lzma/ │ │ │ │ │ │ │ │ ├── LzmaArcRegister.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.h │ │ │ │ │ │ │ │ ├── LzmaHandler.cpp │ │ │ │ │ │ │ │ ├── LzmaHandler.h │ │ │ │ │ │ │ │ ├── LzmaIn.cpp │ │ │ │ │ │ │ │ ├── LzmaIn.h │ │ │ │ │ │ │ │ ├── LzmaItem.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Split/ │ │ │ │ │ │ │ │ ├── SplitHandler.cpp │ │ │ │ │ │ │ │ ├── SplitHandler.h │ │ │ │ │ │ │ │ ├── SplitHandlerOut.cpp │ │ │ │ │ │ │ │ ├── SplitRegister.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Bcj2Coder.cpp │ │ │ │ │ │ │ ├── Bcj2Coder.h │ │ │ │ │ │ │ ├── Bcj2Register.cpp │ │ │ │ │ │ │ ├── BcjCoder.cpp │ │ │ │ │ │ │ ├── BcjCoder.h │ │ │ │ │ │ │ ├── BcjRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchMisc.cpp │ │ │ │ │ │ │ ├── BranchMisc.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LzmaDecoder.cpp │ │ │ │ │ │ │ ├── LzmaDecoder.h │ │ │ │ │ │ │ ├── LzmaEncoder.cpp │ │ │ │ │ │ │ ├── LzmaEncoder.h │ │ │ │ │ │ │ ├── LzmaRegister.cpp │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ ├── Time.cpp │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── lzma_wrapper.c │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── pseudo.c │ │ │ ├── pseudo.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_compat.h │ │ │ ├── squashfs_fs.h │ │ │ ├── squashfs_swap.h │ │ │ ├── swap.c │ │ │ ├── unsquash-1.c │ │ │ ├── unsquash-2.c │ │ │ ├── unsquash-3.c │ │ │ ├── unsquash-4.c │ │ │ ├── unsquashfs.c │ │ │ └── unsquashfs.h │ │ ├── squashfs-4.2/ │ │ │ ├── ACKNOWLEDGEMENTS │ │ │ ├── CHANGES │ │ │ ├── COPYING │ │ │ ├── DONATIONS │ │ │ ├── INSTALL │ │ │ ├── Makefile │ │ │ ├── OLD-READMEs/ │ │ │ │ ├── README-2.0 │ │ │ │ ├── README-2.1 │ │ │ │ ├── README-3.0 │ │ │ │ ├── README-3.1 │ │ │ │ ├── README-3.2 │ │ │ │ ├── README-3.3 │ │ │ │ ├── README-4.0 │ │ │ │ ├── README-4.1 │ │ │ │ └── README-AMD64 │ │ │ ├── PERFORMANCE.README │ │ │ ├── README │ │ │ ├── README-4.2 │ │ │ ├── lzma-4.65/ │ │ │ │ ├── .built │ │ │ │ ├── .built_check │ │ │ │ ├── .configured │ │ │ │ ├── .prepared1a23cc84ca172080ca2c2f332cb31052 │ │ │ │ ├── .prepared1a23cc84ca172080ca2c2f332cb31052_check │ │ │ │ ├── 7zC.txt │ │ │ │ ├── 7zFormat.txt │ │ │ │ ├── C/ │ │ │ │ │ ├── 7zBuf.c │ │ │ │ │ ├── 7zBuf.h │ │ │ │ │ ├── 7zBuf2.c │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ ├── 7zFile.c │ │ │ │ │ ├── 7zFile.h │ │ │ │ │ ├── 7zStream.c │ │ │ │ │ ├── 7zVersion.h │ │ │ │ │ ├── Alloc.c │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z/ │ │ │ │ │ │ ├── 7z.dsp │ │ │ │ │ │ ├── 7z.dsw │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Bcj2.c │ │ │ │ │ ├── Bcj2.h │ │ │ │ │ ├── Bra.c │ │ │ │ │ ├── Bra.h │ │ │ │ │ ├── Bra86.c │ │ │ │ │ ├── BraIA64.c │ │ │ │ │ ├── CpuArch.h │ │ │ │ │ ├── LzFind.c │ │ │ │ │ ├── LzFind.h │ │ │ │ │ ├── LzFindMt.c │ │ │ │ │ ├── LzFindMt.h │ │ │ │ │ ├── LzHash.h │ │ │ │ │ ├── LzmaDec.c │ │ │ │ │ ├── LzmaDec.h │ │ │ │ │ ├── LzmaEnc.c │ │ │ │ │ ├── LzmaEnc.h │ │ │ │ │ ├── LzmaLib/ │ │ │ │ │ │ ├── LzmaLib.def │ │ │ │ │ │ ├── LzmaLib.dsp │ │ │ │ │ │ ├── LzmaLib.dsw │ │ │ │ │ │ ├── LzmaLibExports.c │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── resource.rc │ │ │ │ │ ├── LzmaLib.c │ │ │ │ │ ├── LzmaLib.h │ │ │ │ │ ├── LzmaUtil/ │ │ │ │ │ │ ├── Lzma86Dec.c │ │ │ │ │ │ ├── Lzma86Dec.h │ │ │ │ │ │ ├── Lzma86Enc.c │ │ │ │ │ │ ├── Lzma86Enc.h │ │ │ │ │ │ ├── LzmaUtil.c │ │ │ │ │ │ ├── LzmaUtil.dsp │ │ │ │ │ │ ├── LzmaUtil.dsw │ │ │ │ │ │ ├── lzma │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Threads.c │ │ │ │ │ ├── Threads.h │ │ │ │ │ └── Types.h │ │ │ │ ├── CPP/ │ │ │ │ │ ├── 7zip/ │ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ │ ├── 7z/ │ │ │ │ │ │ │ │ ├── 7zCompressionMode.cpp │ │ │ │ │ │ │ │ ├── 7zCompressionMode.h │ │ │ │ │ │ │ │ ├── 7zDecode.cpp │ │ │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ │ │ ├── 7zEncode.cpp │ │ │ │ │ │ │ │ ├── 7zEncode.h │ │ │ │ │ │ │ │ ├── 7zExtract.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderInStream.h │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.cpp │ │ │ │ │ │ │ │ ├── 7zFolderOutStream.h │ │ │ │ │ │ │ │ ├── 7zHandler.cpp │ │ │ │ │ │ │ │ ├── 7zHandler.h │ │ │ │ │ │ │ │ ├── 7zHandlerOut.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.cpp │ │ │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ │ │ ├── 7zIn.cpp │ │ │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ │ │ ├── 7zOut.cpp │ │ │ │ │ │ │ │ ├── 7zOut.h │ │ │ │ │ │ │ │ ├── 7zProperties.cpp │ │ │ │ │ │ │ │ ├── 7zProperties.h │ │ │ │ │ │ │ │ ├── 7zRegister.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.cpp │ │ │ │ │ │ │ │ ├── 7zSpecStream.h │ │ │ │ │ │ │ │ ├── 7zUpdate.cpp │ │ │ │ │ │ │ │ ├── 7zUpdate.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Archive.def │ │ │ │ │ │ │ ├── Archive2.def │ │ │ │ │ │ │ ├── ArchiveExports.cpp │ │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ │ ├── CoderMixer2.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2.h │ │ │ │ │ │ │ │ ├── CoderMixer2MT.cpp │ │ │ │ │ │ │ │ ├── CoderMixer2MT.h │ │ │ │ │ │ │ │ ├── CrossThreadProgress.cpp │ │ │ │ │ │ │ │ ├── CrossThreadProgress.h │ │ │ │ │ │ │ │ ├── DummyOutStream.cpp │ │ │ │ │ │ │ │ ├── DummyOutStream.h │ │ │ │ │ │ │ │ ├── HandlerOut.cpp │ │ │ │ │ │ │ │ ├── HandlerOut.h │ │ │ │ │ │ │ │ ├── InStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── InStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ItemNameUtils.cpp │ │ │ │ │ │ │ │ ├── ItemNameUtils.h │ │ │ │ │ │ │ │ ├── MultiStream.cpp │ │ │ │ │ │ │ │ ├── MultiStream.h │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.cpp │ │ │ │ │ │ │ │ ├── OutStreamWithCRC.h │ │ │ │ │ │ │ │ ├── ParseProperties.cpp │ │ │ │ │ │ │ │ ├── ParseProperties.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── DllExports2.cpp │ │ │ │ │ │ │ ├── IArchive.h │ │ │ │ │ │ │ ├── Lzma/ │ │ │ │ │ │ │ │ ├── LzmaArcRegister.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.cpp │ │ │ │ │ │ │ │ ├── LzmaFiltersDecode.h │ │ │ │ │ │ │ │ ├── LzmaHandler.cpp │ │ │ │ │ │ │ │ ├── LzmaHandler.h │ │ │ │ │ │ │ │ ├── LzmaIn.cpp │ │ │ │ │ │ │ │ ├── LzmaIn.h │ │ │ │ │ │ │ │ ├── LzmaItem.h │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ ├── Split/ │ │ │ │ │ │ │ │ ├── SplitHandler.cpp │ │ │ │ │ │ │ │ ├── SplitHandler.h │ │ │ │ │ │ │ │ ├── SplitHandlerOut.cpp │ │ │ │ │ │ │ │ ├── SplitRegister.cpp │ │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── Bundles/ │ │ │ │ │ │ │ ├── Alone7z/ │ │ │ │ │ │ │ │ ├── Alone.dsp │ │ │ │ │ │ │ │ ├── Alone.dsw │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ ├── Format7zExtractR/ │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ │ └── Format7zR/ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── resource.rc │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── CreateCoder.cpp │ │ │ │ │ │ │ ├── CreateCoder.h │ │ │ │ │ │ │ ├── FilePathAutoRename.cpp │ │ │ │ │ │ │ ├── FilePathAutoRename.h │ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ │ ├── FilterCoder.cpp │ │ │ │ │ │ │ ├── FilterCoder.h │ │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ │ ├── InOutTempBuffer.cpp │ │ │ │ │ │ │ ├── InOutTempBuffer.h │ │ │ │ │ │ │ ├── LimitedStreams.cpp │ │ │ │ │ │ │ ├── LimitedStreams.h │ │ │ │ │ │ │ ├── LockedStream.cpp │ │ │ │ │ │ │ ├── LockedStream.h │ │ │ │ │ │ │ ├── MethodId.cpp │ │ │ │ │ │ │ ├── MethodId.h │ │ │ │ │ │ │ ├── MethodProps.cpp │ │ │ │ │ │ │ ├── MethodProps.h │ │ │ │ │ │ │ ├── OffsetStream.cpp │ │ │ │ │ │ │ ├── OffsetStream.h │ │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ │ ├── ProgressUtils.cpp │ │ │ │ │ │ │ ├── ProgressUtils.h │ │ │ │ │ │ │ ├── RegisterArc.h │ │ │ │ │ │ │ ├── RegisterCodec.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── StreamBinder.cpp │ │ │ │ │ │ │ ├── StreamBinder.h │ │ │ │ │ │ │ ├── StreamObjects.cpp │ │ │ │ │ │ │ ├── StreamObjects.h │ │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ │ ├── StreamUtils.h │ │ │ │ │ │ │ ├── VirtThread.cpp │ │ │ │ │ │ │ └── VirtThread.h │ │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ │ ├── Bcj2Coder.cpp │ │ │ │ │ │ │ ├── Bcj2Coder.h │ │ │ │ │ │ │ ├── Bcj2Register.cpp │ │ │ │ │ │ │ ├── BcjCoder.cpp │ │ │ │ │ │ │ ├── BcjCoder.h │ │ │ │ │ │ │ ├── BcjRegister.cpp │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchMisc.cpp │ │ │ │ │ │ │ ├── BranchMisc.h │ │ │ │ │ │ │ ├── BranchRegister.cpp │ │ │ │ │ │ │ ├── ByteSwap.cpp │ │ │ │ │ │ │ ├── ByteSwap.h │ │ │ │ │ │ │ ├── ByteSwapRegister.cpp │ │ │ │ │ │ │ ├── CodecExports.cpp │ │ │ │ │ │ │ ├── CopyCoder.cpp │ │ │ │ │ │ │ ├── CopyCoder.h │ │ │ │ │ │ │ ├── CopyRegister.cpp │ │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ │ ├── Exception.h │ │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ │ ├── LzmaBenchCon.cpp │ │ │ │ │ │ │ │ ├── LzmaBenchCon.h │ │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ │ ├── lzma │ │ │ │ │ │ │ │ ├── lzma_alone │ │ │ │ │ │ │ │ ├── lzma_version.h │ │ │ │ │ │ │ │ ├── lzmp.cpp │ │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ │ ├── LzmaDecoder.cpp │ │ │ │ │ │ │ ├── LzmaDecoder.h │ │ │ │ │ │ │ ├── LzmaEncoder.cpp │ │ │ │ │ │ │ ├── LzmaEncoder.h │ │ │ │ │ │ │ ├── LzmaRegister.cpp │ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── ICoder.h │ │ │ │ │ │ ├── IDecl.h │ │ │ │ │ │ ├── IPassword.h │ │ │ │ │ │ ├── IProgress.h │ │ │ │ │ │ ├── IStream.h │ │ │ │ │ │ ├── MyVersion.h │ │ │ │ │ │ ├── MyVersionInfo.rc │ │ │ │ │ │ ├── PropID.h │ │ │ │ │ │ └── UI/ │ │ │ │ │ │ ├── Client7z/ │ │ │ │ │ │ │ ├── Client7z.cpp │ │ │ │ │ │ │ ├── Client7z.dsp │ │ │ │ │ │ │ ├── Client7z.dsw │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ │ ├── ArchiveCommandLine.cpp │ │ │ │ │ │ │ ├── ArchiveCommandLine.h │ │ │ │ │ │ │ ├── ArchiveExtractCallback.cpp │ │ │ │ │ │ │ ├── ArchiveExtractCallback.h │ │ │ │ │ │ │ ├── ArchiveName.cpp │ │ │ │ │ │ │ ├── ArchiveName.h │ │ │ │ │ │ │ ├── ArchiveOpenCallback.cpp │ │ │ │ │ │ │ ├── ArchiveOpenCallback.h │ │ │ │ │ │ │ ├── DefaultName.cpp │ │ │ │ │ │ │ ├── DefaultName.h │ │ │ │ │ │ │ ├── DirItem.h │ │ │ │ │ │ │ ├── EnumDirItems.cpp │ │ │ │ │ │ │ ├── EnumDirItems.h │ │ │ │ │ │ │ ├── ExitCode.h │ │ │ │ │ │ │ ├── Extract.cpp │ │ │ │ │ │ │ ├── Extract.h │ │ │ │ │ │ │ ├── ExtractMode.h │ │ │ │ │ │ │ ├── ExtractingFilePath.cpp │ │ │ │ │ │ │ ├── ExtractingFilePath.h │ │ │ │ │ │ │ ├── IFileExtractCallback.h │ │ │ │ │ │ │ ├── LoadCodecs.cpp │ │ │ │ │ │ │ ├── LoadCodecs.h │ │ │ │ │ │ │ ├── OpenArchive.cpp │ │ │ │ │ │ │ ├── OpenArchive.h │ │ │ │ │ │ │ ├── PropIDUtils.cpp │ │ │ │ │ │ │ ├── PropIDUtils.h │ │ │ │ │ │ │ ├── Property.h │ │ │ │ │ │ │ ├── SetProperties.cpp │ │ │ │ │ │ │ ├── SetProperties.h │ │ │ │ │ │ │ ├── SortUtils.cpp │ │ │ │ │ │ │ ├── SortUtils.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── TempFiles.cpp │ │ │ │ │ │ │ ├── TempFiles.h │ │ │ │ │ │ │ ├── Update.cpp │ │ │ │ │ │ │ ├── Update.h │ │ │ │ │ │ │ ├── UpdateAction.cpp │ │ │ │ │ │ │ ├── UpdateAction.h │ │ │ │ │ │ │ ├── UpdateCallback.cpp │ │ │ │ │ │ │ ├── UpdateCallback.h │ │ │ │ │ │ │ ├── UpdatePair.cpp │ │ │ │ │ │ │ ├── UpdatePair.h │ │ │ │ │ │ │ ├── UpdateProduce.cpp │ │ │ │ │ │ │ ├── UpdateProduce.h │ │ │ │ │ │ │ ├── WorkDir.cpp │ │ │ │ │ │ │ ├── WorkDir.h │ │ │ │ │ │ │ └── ZipRegistry.h │ │ │ │ │ │ └── Console/ │ │ │ │ │ │ ├── ConsoleClose.cpp │ │ │ │ │ │ ├── ConsoleClose.h │ │ │ │ │ │ ├── ExtractCallbackConsole.cpp │ │ │ │ │ │ ├── ExtractCallbackConsole.h │ │ │ │ │ │ ├── List.cpp │ │ │ │ │ │ ├── List.h │ │ │ │ │ │ ├── Main.cpp │ │ │ │ │ │ ├── MainAr.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.cpp │ │ │ │ │ │ ├── OpenCallbackConsole.h │ │ │ │ │ │ ├── PercentPrinter.cpp │ │ │ │ │ │ ├── PercentPrinter.h │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── UpdateCallbackConsole.cpp │ │ │ │ │ │ ├── UpdateCallbackConsole.h │ │ │ │ │ │ ├── UserInputUtils.cpp │ │ │ │ │ │ ├── UserInputUtils.h │ │ │ │ │ │ └── makefile │ │ │ │ │ ├── Build.mak │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── AutoPtr.h │ │ │ │ │ │ ├── Buffer.h │ │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ │ ├── ComTry.h │ │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ │ ├── Defs.h │ │ │ │ │ │ ├── DynamicBuffer.h │ │ │ │ │ │ ├── IntToString.cpp │ │ │ │ │ │ ├── IntToString.h │ │ │ │ │ │ ├── ListFileUtils.cpp │ │ │ │ │ │ ├── ListFileUtils.h │ │ │ │ │ │ ├── MyCom.h │ │ │ │ │ │ ├── MyException.h │ │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ │ ├── MyString.cpp │ │ │ │ │ │ ├── MyString.h │ │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ │ ├── MyVector.cpp │ │ │ │ │ │ ├── MyVector.h │ │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StdInStream.cpp │ │ │ │ │ │ ├── StdInStream.h │ │ │ │ │ │ ├── StdOutStream.cpp │ │ │ │ │ │ ├── StdOutStream.h │ │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ │ ├── Types.h │ │ │ │ │ │ ├── UTFConvert.cpp │ │ │ │ │ │ ├── UTFConvert.h │ │ │ │ │ │ ├── Wildcard.cpp │ │ │ │ │ │ └── Wildcard.h │ │ │ │ │ └── Windows/ │ │ │ │ │ ├── DLL.cpp │ │ │ │ │ ├── DLL.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Error.cpp │ │ │ │ │ ├── Error.h │ │ │ │ │ ├── FileDir.cpp │ │ │ │ │ ├── FileDir.h │ │ │ │ │ ├── FileFind.cpp │ │ │ │ │ ├── FileFind.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ ├── FileMapping.cpp │ │ │ │ │ ├── FileMapping.h │ │ │ │ │ ├── FileName.cpp │ │ │ │ │ ├── FileName.h │ │ │ │ │ ├── Handle.h │ │ │ │ │ ├── MemoryLock.cpp │ │ │ │ │ ├── MemoryLock.h │ │ │ │ │ ├── PropVariant.cpp │ │ │ │ │ ├── PropVariant.h │ │ │ │ │ ├── PropVariantConversions.cpp │ │ │ │ │ ├── PropVariantConversions.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── Synchronization.cpp │ │ │ │ │ ├── Synchronization.h │ │ │ │ │ ├── System.cpp │ │ │ │ │ ├── System.h │ │ │ │ │ ├── Thread.h │ │ │ │ │ ├── Time.cpp │ │ │ │ │ └── Time.h │ │ │ │ ├── CS/ │ │ │ │ │ └── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ │ └── OutBuffer.cs │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ │ └── ICoder.cs │ │ │ │ ├── Java/ │ │ │ │ │ └── SevenZip/ │ │ │ │ │ ├── CRC.java │ │ │ │ │ ├── Compression/ │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LzmaAlone.java │ │ │ │ │ └── LzmaBench.java │ │ │ │ ├── Methods.txt │ │ │ │ ├── history.txt │ │ │ │ └── lzma.txt │ │ │ ├── pseudo-file.example │ │ │ └── squashfs-tools/ │ │ │ ├── Makefile │ │ │ ├── compressor.c │ │ │ ├── compressor.h │ │ │ ├── gzip_wrapper.c │ │ │ ├── lzma_wrapper.c │ │ │ ├── lzma_xz_options.c │ │ │ ├── lzma_xz_options.h │ │ │ ├── lzma_xz_wrapper.c │ │ │ ├── lzo_wrapper.c │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── pseudo.c │ │ │ ├── pseudo.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── read_xattrs.c │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_compat.h │ │ │ ├── squashfs_fs.h │ │ │ ├── squashfs_swap.h │ │ │ ├── swap.c │ │ │ ├── unsquash-1.c │ │ │ ├── unsquash-2.c │ │ │ ├── unsquash-3.c │ │ │ ├── unsquash-4.c │ │ │ ├── unsquashfs.c │ │ │ ├── unsquashfs.h │ │ │ ├── unsquashfs_xattr.c │ │ │ ├── xattr.c │ │ │ ├── xattr.h │ │ │ ├── xz_wrapper.c │ │ │ └── xz_wrapper.h │ │ ├── squashfs-4.2-official/ │ │ │ ├── Makefile │ │ │ ├── compressor.c │ │ │ ├── compressor.h │ │ │ ├── gzip_wrapper.c │ │ │ ├── lzma_wrapper.c │ │ │ ├── lzma_xz_wrapper.c │ │ │ ├── lzo_wrapper.c │ │ │ ├── mksquashfs.c │ │ │ ├── mksquashfs.h │ │ │ ├── pseudo.c │ │ │ ├── pseudo.h │ │ │ ├── read_fs.c │ │ │ ├── read_fs.h │ │ │ ├── read_xattrs.c │ │ │ ├── sort.c │ │ │ ├── sort.h │ │ │ ├── squashfs_compat.h │ │ │ ├── squashfs_fs.h │ │ │ ├── squashfs_swap.h │ │ │ ├── swap.c │ │ │ ├── unsquash-1.c │ │ │ ├── unsquash-2.c │ │ │ ├── unsquash-3.c │ │ │ ├── unsquash-4.c │ │ │ ├── unsquashfs.c │ │ │ ├── unsquashfs.h │ │ │ ├── unsquashfs_xattr.c │ │ │ ├── xattr.c │ │ │ ├── xattr.h │ │ │ ├── xz_wrapper.c │ │ │ └── xz_wrapper.h │ │ └── squashfs-hg55x-bin/ │ │ ├── README │ │ └── unsquashfs │ ├── splitter3.cc │ ├── squashfs-2.1-r2/ │ │ ├── Makefile │ │ ├── mksquashfs.c │ │ ├── mksquashfs.h │ │ ├── read_fs.c │ │ ├── read_fs.h │ │ ├── sort.c │ │ ├── squashfs_fs.h │ │ └── unsquashfs.c │ ├── squashfs-3.0/ │ │ ├── Makefile │ │ ├── global.h │ │ ├── mksquashfs.c │ │ ├── mksquashfs.h │ │ ├── read_fs.c │ │ ├── read_fs.h │ │ ├── sort.c │ │ ├── sort.h │ │ ├── squashfs_fs.h │ │ └── unsquashfs.c │ ├── squashfs-3.0-lzma-damn-small-variant/ │ │ ├── Makefile │ │ ├── global.h │ │ ├── lzma/ │ │ │ ├── .built │ │ │ ├── .unpacked │ │ │ ├── 7zC.txt │ │ │ ├── 7zFormat.txt │ │ │ ├── C/ │ │ │ │ ├── 7zip/ │ │ │ │ │ ├── Archive/ │ │ │ │ │ │ └── 7z_C/ │ │ │ │ │ │ ├── 7zAlloc.c │ │ │ │ │ │ ├── 7zAlloc.h │ │ │ │ │ │ ├── 7zBuffer.c │ │ │ │ │ │ ├── 7zBuffer.h │ │ │ │ │ │ ├── 7zCrc.c │ │ │ │ │ │ ├── 7zCrc.h │ │ │ │ │ │ ├── 7zDecode.c │ │ │ │ │ │ ├── 7zDecode.h │ │ │ │ │ │ ├── 7zExtract.c │ │ │ │ │ │ ├── 7zExtract.h │ │ │ │ │ │ ├── 7zHeader.c │ │ │ │ │ │ ├── 7zHeader.h │ │ │ │ │ │ ├── 7zIn.c │ │ │ │ │ │ ├── 7zIn.h │ │ │ │ │ │ ├── 7zItem.c │ │ │ │ │ │ ├── 7zItem.h │ │ │ │ │ │ ├── 7zMain.c │ │ │ │ │ │ ├── 7zMethodID.c │ │ │ │ │ │ ├── 7zMethodID.h │ │ │ │ │ │ ├── 7zTypes.h │ │ │ │ │ │ ├── 7z_C.dsp │ │ │ │ │ │ ├── 7z_C.dsw │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ ├── StreamUtils.cpp │ │ │ │ │ │ └── StreamUtils.h │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ │ ├── BranchSPARC.c │ │ │ │ │ │ │ ├── BranchSPARC.h │ │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ ├── SPARC.cpp │ │ │ │ │ │ │ ├── SPARC.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree/ │ │ │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ │ │ ├── BinTree4b.h │ │ │ │ │ │ │ │ └── BinTreeMain.h │ │ │ │ │ │ │ ├── HashChain/ │ │ │ │ │ │ │ │ ├── HC.h │ │ │ │ │ │ │ │ ├── HC2.h │ │ │ │ │ │ │ │ ├── HC3.h │ │ │ │ │ │ │ │ ├── HC4.h │ │ │ │ │ │ │ │ ├── HC4b.h │ │ │ │ │ │ │ │ └── HCMain.h │ │ │ │ │ │ │ ├── IMatchFinder.h │ │ │ │ │ │ │ ├── LZInWindow.cpp │ │ │ │ │ │ │ ├── LZInWindow.h │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ ├── Patricia/ │ │ │ │ │ │ │ │ ├── Pat.h │ │ │ │ │ │ │ │ ├── Pat2.h │ │ │ │ │ │ │ │ ├── Pat2H.h │ │ │ │ │ │ │ │ ├── Pat2R.h │ │ │ │ │ │ │ │ ├── Pat3H.h │ │ │ │ │ │ │ │ ├── Pat4H.h │ │ │ │ │ │ │ │ └── PatMain.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ ├── LzmaRam.cpp │ │ │ │ │ │ │ ├── LzmaRam.h │ │ │ │ │ │ │ ├── LzmaRamDecode.c │ │ │ │ │ │ │ ├── LzmaRamDecode.h │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ ├── LZMA_C/ │ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ │ ├── LzmaDecodeSize.c │ │ │ │ │ │ │ ├── LzmaStateDecode.c │ │ │ │ │ │ │ ├── LzmaStateDecode.h │ │ │ │ │ │ │ ├── LzmaStateTest.c │ │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ │ ├── makefile │ │ │ │ │ │ │ └── makefile.gcc │ │ │ │ │ │ ├── LZMA_Lib/ │ │ │ │ │ │ │ ├── ZLib.cpp │ │ │ │ │ │ │ ├── lzmaext.h │ │ │ │ │ │ │ └── makefile │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── ICoder.h │ │ │ │ │ └── IStream.h │ │ │ │ ├── Common/ │ │ │ │ │ ├── Alloc.cpp │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ ├── CRC.h │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ ├── ComTry.h │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── MyCom.h │ │ │ │ │ ├── MyGuidDef.h │ │ │ │ │ ├── MyInitGuid.h │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── String.cpp │ │ │ │ │ ├── String.h │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ ├── Types.h │ │ │ │ │ ├── Vector.cpp │ │ │ │ │ └── Vector.h │ │ │ │ └── Windows/ │ │ │ │ ├── Defs.h │ │ │ │ ├── FileIO.cpp │ │ │ │ ├── FileIO.h │ │ │ │ └── StdAfx.h │ │ │ ├── CPL.html │ │ │ ├── CS/ │ │ │ │ └── 7zip/ │ │ │ │ ├── Common/ │ │ │ │ │ ├── CRC.cs │ │ │ │ │ ├── CommandLineParser.cs │ │ │ │ │ ├── InBuffer.cs │ │ │ │ │ └── OutBuffer.cs │ │ │ │ ├── Compress/ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ ├── IMatchFinder.cs │ │ │ │ │ │ ├── LzBinTree.cs │ │ │ │ │ │ ├── LzInWindow.cs │ │ │ │ │ │ └── LzOutWindow.cs │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ ├── LzmaBase.cs │ │ │ │ │ │ ├── LzmaDecoder.cs │ │ │ │ │ │ └── LzmaEncoder.cs │ │ │ │ │ ├── LzmaAlone/ │ │ │ │ │ │ ├── LzmaAlone.cs │ │ │ │ │ │ ├── LzmaAlone.csproj │ │ │ │ │ │ ├── LzmaAlone.sln │ │ │ │ │ │ ├── LzmaBench.cs │ │ │ │ │ │ └── Properties/ │ │ │ │ │ │ ├── AssemblyInfo.cs │ │ │ │ │ │ ├── Resources.cs │ │ │ │ │ │ └── Settings.cs │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ ├── RangeCoder.cs │ │ │ │ │ ├── RangeCoderBit.cs │ │ │ │ │ └── RangeCoderBitTree.cs │ │ │ │ └── ICoder.cs │ │ │ ├── Java/ │ │ │ │ └── SevenZip/ │ │ │ │ ├── CRC.java │ │ │ │ ├── Compression/ │ │ │ │ │ ├── ICodeProgress.java │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ ├── BinTree.java │ │ │ │ │ │ ├── InWindow.java │ │ │ │ │ │ └── OutWindow.java │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ ├── Base.java │ │ │ │ │ │ ├── Decoder.java │ │ │ │ │ │ └── Encoder.java │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ ├── BitTreeDecoder.java │ │ │ │ │ ├── BitTreeEncoder.java │ │ │ │ │ ├── Decoder.java │ │ │ │ │ └── Encoder.java │ │ │ │ ├── LzmaAlone.java │ │ │ │ └── LzmaBench.java │ │ │ ├── LGPL.txt │ │ │ ├── Methods.txt │ │ │ ├── history.txt │ │ │ └── lzma.txt │ │ ├── mksquashfs.c │ │ ├── mksquashfs.h │ │ ├── read_fs.c │ │ ├── read_fs.h │ │ ├── sort.c │ │ ├── sort.h │ │ ├── squashfs_fs.h │ │ └── unsquashfs.c │ ├── tpl-tool/ │ │ ├── doc/ │ │ │ ├── Image_layout │ │ │ └── Readme │ │ └── src/ │ │ ├── Makefile │ │ ├── md5.c │ │ ├── md5.h │ │ ├── tpl-factory-to-sysupgrade.sh │ │ └── tpl-tool.c │ ├── uncramfs/ │ │ ├── Makefile │ │ ├── README │ │ ├── USE_CRAMFSCK_TO_EXTRACT_INSTEAD_SEE_CRAMFS-2.X_FOLDER │ │ ├── VERSION │ │ ├── cramfs.h │ │ ├── uncramfs-w.pl │ │ └── uncramfs.c │ ├── uncramfs-lzma/ │ │ ├── Makefile │ │ ├── README │ │ ├── VERSION │ │ ├── cramfs.h │ │ ├── cramfs_fs.h │ │ ├── lzma-rg/ │ │ │ ├── CPL.html │ │ │ ├── LGPL.txt │ │ │ ├── Makefile │ │ │ ├── SRC/ │ │ │ │ ├── .cvsignore │ │ │ │ ├── 7zip/ │ │ │ │ │ ├── Common/ │ │ │ │ │ │ ├── FileStreams.cpp │ │ │ │ │ │ ├── FileStreams.h │ │ │ │ │ │ ├── InBuffer.cpp │ │ │ │ │ │ ├── InBuffer.h │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ ├── OutBuffer.cpp │ │ │ │ │ │ ├── OutBuffer.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── Compress/ │ │ │ │ │ │ ├── Branch/ │ │ │ │ │ │ │ ├── ARM.cpp │ │ │ │ │ │ │ ├── ARM.h │ │ │ │ │ │ │ ├── ARMThumb.cpp │ │ │ │ │ │ │ ├── ARMThumb.h │ │ │ │ │ │ │ ├── BranchARM.c │ │ │ │ │ │ │ ├── BranchARM.h │ │ │ │ │ │ │ ├── BranchARMThumb.c │ │ │ │ │ │ │ ├── BranchARMThumb.h │ │ │ │ │ │ │ ├── BranchCoder.cpp │ │ │ │ │ │ │ ├── BranchCoder.h │ │ │ │ │ │ │ ├── BranchIA64.c │ │ │ │ │ │ │ ├── BranchIA64.h │ │ │ │ │ │ │ ├── BranchPPC.c │ │ │ │ │ │ │ ├── BranchPPC.h │ │ │ │ │ │ │ ├── BranchX86.c │ │ │ │ │ │ │ ├── BranchX86.h │ │ │ │ │ │ │ ├── IA64.cpp │ │ │ │ │ │ │ ├── IA64.h │ │ │ │ │ │ │ ├── PPC.cpp │ │ │ │ │ │ │ ├── PPC.h │ │ │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ │ │ ├── x86.cpp │ │ │ │ │ │ │ ├── x86.h │ │ │ │ │ │ │ ├── x86_2.cpp │ │ │ │ │ │ │ └── x86_2.h │ │ │ │ │ │ ├── LZ/ │ │ │ │ │ │ │ ├── BinTree/ │ │ │ │ │ │ │ │ ├── BinTree.h │ │ │ │ │ │ │ │ ├── BinTree2.h │ │ │ │ │ │ │ │ ├── BinTree3.h │ │ │ │ │ │ │ │ ├── BinTree3Z.h │ │ │ │ │ │ │ │ ├── BinTree3ZMain.h │ │ │ │ │ │ │ │ ├── BinTree4.h │ │ │ │ │ │ │ │ ├── BinTree4b.h │ │ │ │ │ │ │ │ ├── BinTreeMF.h │ │ │ │ │ │ │ │ ├── BinTreeMFMain.h │ │ │ │ │ │ │ │ └── BinTreeMain.h │ │ │ │ │ │ │ ├── HashChain/ │ │ │ │ │ │ │ │ ├── HC.h │ │ │ │ │ │ │ │ ├── HC2.h │ │ │ │ │ │ │ │ ├── HC3.h │ │ │ │ │ │ │ │ ├── HC4.h │ │ │ │ │ │ │ │ ├── HC4b.h │ │ │ │ │ │ │ │ ├── HCMF.h │ │ │ │ │ │ │ │ ├── HCMFMain.h │ │ │ │ │ │ │ │ └── HCMain.h │ │ │ │ │ │ │ ├── IMatchFinder.h │ │ │ │ │ │ │ ├── LZInWindow.cpp │ │ │ │ │ │ │ ├── LZInWindow.h │ │ │ │ │ │ │ ├── LZOutWindow.cpp │ │ │ │ │ │ │ ├── LZOutWindow.h │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ ├── Patricia/ │ │ │ │ │ │ │ │ ├── Pat.h │ │ │ │ │ │ │ │ ├── Pat2.h │ │ │ │ │ │ │ │ ├── Pat2H.h │ │ │ │ │ │ │ │ ├── Pat2R.h │ │ │ │ │ │ │ │ ├── Pat3H.h │ │ │ │ │ │ │ │ ├── Pat4H.h │ │ │ │ │ │ │ │ └── PatMain.h │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA/ │ │ │ │ │ │ │ ├── LZMA.h │ │ │ │ │ │ │ ├── LZMADecoder.cpp │ │ │ │ │ │ │ ├── LZMADecoder.h │ │ │ │ │ │ │ ├── LZMAEncoder.cpp │ │ │ │ │ │ │ ├── LZMAEncoder.h │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA_Alone/ │ │ │ │ │ │ │ ├── AloneLZMA.dsp │ │ │ │ │ │ │ ├── AloneLZMA.dsw │ │ │ │ │ │ │ ├── LzmaAlone.cpp │ │ │ │ │ │ │ ├── LzmaBench.cpp │ │ │ │ │ │ │ ├── LzmaBench.h │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ ├── Makefile.rg │ │ │ │ │ │ │ ├── StdAfx.cpp │ │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ │ ├── LZMA_C/ │ │ │ │ │ │ │ ├── LzmaDecode.c │ │ │ │ │ │ │ ├── LzmaDecode.h │ │ │ │ │ │ │ ├── LzmaTest.c │ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ │ ├── Makefile.rg │ │ │ │ │ │ │ ├── decode.c │ │ │ │ │ │ │ ├── decode.c.orig │ │ │ │ │ │ │ └── decode.h │ │ │ │ │ │ └── RangeCoder/ │ │ │ │ │ │ ├── Makefile │ │ │ │ │ │ ├── RangeCoder.h │ │ │ │ │ │ ├── RangeCoderBit.cpp │ │ │ │ │ │ ├── RangeCoderBit.h │ │ │ │ │ │ ├── RangeCoderBitTree.h │ │ │ │ │ │ ├── RangeCoderOpt.h │ │ │ │ │ │ └── StdAfx.h │ │ │ │ │ ├── ICoder.h │ │ │ │ │ ├── IStream.h │ │ │ │ │ ├── Makefile │ │ │ │ │ └── lzma_encode.cpp │ │ │ │ ├── Common/ │ │ │ │ │ ├── Alloc.cpp │ │ │ │ │ ├── Alloc.h │ │ │ │ │ ├── CRC.cpp │ │ │ │ │ ├── CRC.h │ │ │ │ │ ├── C_FileIO.cpp │ │ │ │ │ ├── C_FileIO.h │ │ │ │ │ ├── ComTry.h │ │ │ │ │ ├── CommandLineParser.cpp │ │ │ │ │ ├── CommandLineParser.h │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── MyCom.h │ │ │ │ │ ├── MyUnknown.h │ │ │ │ │ ├── MyWindows.h │ │ │ │ │ ├── NewHandler.cpp │ │ │ │ │ ├── NewHandler.h │ │ │ │ │ ├── StdAfx.h │ │ │ │ │ ├── String.cpp │ │ │ │ │ ├── String.h │ │ │ │ │ ├── StringConvert.cpp │ │ │ │ │ ├── StringConvert.h │ │ │ │ │ ├── StringToInt.cpp │ │ │ │ │ ├── StringToInt.h │ │ │ │ │ ├── Types.h │ │ │ │ │ ├── Vector.cpp │ │ │ │ │ └── Vector.h │ │ │ │ ├── Makefile │ │ │ │ ├── Windows/ │ │ │ │ │ ├── Defs.h │ │ │ │ │ ├── FileIO.cpp │ │ │ │ │ ├── FileIO.h │ │ │ │ │ └── StdAfx.h │ │ │ │ ├── lzma.mak │ │ │ │ └── lzma_encode.h │ │ │ ├── history.txt │ │ │ └── lzma.txt │ │ └── lzma-uncramfs.c │ ├── untrx.cc │ ├── untrx.h │ ├── webcomp-tools/ │ │ ├── Makefile │ │ ├── README │ │ ├── common.c │ │ ├── common.h │ │ ├── webdecomp.c │ │ └── webdecomp.h │ └── wrt_vx_imgtool/ │ ├── Makefile │ ├── imghdr.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── wrt54gv5_img.cpp ├── trunk/ │ ├── NOTE_no_need_to_sync_ver_file.txt │ ├── README │ └── firmware_mod_kit_version.txt ├── uncpio.sh ├── uncramfs_all.sh └── unsquashfs_all.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: build-firmware.sh ================================================ #!/bin/bash DIR="$1" NEXT_PARAM="" if [ "$1" == "-h" ] then echo "Usage: $0 [FMK directory] [-nopad | -min]" exit 1 fi if [ "$DIR" == "" ] || [ "$DIR" == "-nopad" ] || [ "$DIR" == "-min" ] then DIR="fmk" NEXT_PARAM="$1" else NEXT_PARAM="$2" fi # Need to extract file systems as ROOT if [ "$UID" != "0" ] then SUDO="sudo" else SUDO="" fi DIR=$(readlink -f $DIR) # Make sure we're operating out of the FMK directory cd $(dirname $(readlink -f $0)) # Order matters here! eval $(cat shared-ng.inc) eval $(cat $CONFLOG) FSOUT="$DIR/new-filesystem.$FS_TYPE" printf "Firmware Mod Kit (build-ng) ${VERSION}, (c)2011-2013 Craig Heffner, Jeremy Collake\n\n" if [ ! -d "$DIR" ] then echo -e "Usage: $0 [build directory] [-nopad]\n" exit 1 fi # Check if FMK has been built, and if not, build it if [ ! -e "./src/crcalc/crcalc" ] then echo "Firmware-Mod-Kit has not been built yet. Building..." cd src && ./configure && make if [ $? -eq 0 ] then cd - else echo "Build failed! Quitting..." exit 1 fi fi echo "Building new $FS_TYPE file system..." # Clean up any previously created files rm -rf "$FWOUT" "$FSOUT" # Build the appropriate file system case $FS_TYPE in "squashfs") # Check for squashfs 4.0 realtek, which requires the -comp option to build lzma images. if [ "$(echo $MKFS | grep 'squashfs-4.0-realtek')" != "" ] && [ "$FS_COMPRESSION" == "lzma" ] then COMP="-comp lzma" else COMP="" fi # Mksquashfs 4.0 tools don't support the -le option; little endian is built by default if [ "$(echo $MKFS | grep 'squashfs-4.')" != "" ] && [ "$ENDIANESS" == "-le" ] then ENDIANESS="" fi # Increasing the block size minimizes the resulting image size (larger dictionary). Max block size of 1MB. if [ "$NEXT_PARAM" == "-min" ] then echo "Blocksize override (-min). Original used $((FS_BLOCKSIZE/1024))KB blocks. New firmware uses 1MB blocks." FS_BLOCKSIZE="$((1024*1024))" fi # if blocksize var exists, then add '-b' parameter if [ "$FS_BLOCKSIZE" != "" ] then BS="-b $FS_BLOCKSIZE" fi $SUDO $MKFS "$ROOTFS" "$FSOUT" $ENDIANESS $BS $COMP -all-root ;; "cramfs") $SUDO $MKFS "$ROOTFS" "$FSOUT" if [ "$ENDIANESS" == "-be" ] then mv "$FSOUT" "$FSOUT.le" ./src/cramfsswap/cramfsswap "$FSOUT.le" "$FSOUT" rm -f "$FSOUT.le" fi ;; *) echo "Unsupported file system '$FS_TYPE'!" ;; esac if [ ! -e $FSOUT ] then echo "Failed to create new file system! Quitting..." exit 1 fi # Append the new file system to the first part of the original firmware file cp $HEADER_IMAGE $FWOUT $SUDO cat $FSOUT >> $FWOUT # Calculate and create any filler bytes required between the end of the file system and the footer / EOF. CUR_SIZE=$(ls -l $FWOUT | awk '{print $5}') ((FILLER_SIZE=$FW_SIZE-$CUR_SIZE-$FOOTER_SIZE)) if [ "$FILLER_SIZE" -lt 0 ] then echo "ERROR: New firmware image will be larger than original image!" echo " Building firmware images larger than the original can brick your device!" echo " Try re-running with the -min option, or remove any unnecessary files from the file system." echo " Refusing to create new firmware image." echo "" echo " Original file size: $FW_SIZE" echo " Current file size: $CUR_SIZE" echo "" echo " Quitting..." rm -f "$FWOUT" "$FSOUT" exit 1 else if [ "$NEXT_PARAM" != "-nopad" ]; then echo "Remaining free bytes in firmware image: $FILLER_SIZE" perl -e "print \"\xFF\"x$FILLER_SIZE" >> "$FWOUT" else echo "Padding of firmware image disabled via -nopad" fi fi # Append the footer to the new firmware image, if there is any footer if [ "$FOOTER_SIZE" -gt "0" ] then cat $FOOTER_IMAGE >> "$FWOUT" fi # Calculate new checksum values for the firmware header # trx, dlob, uimage ./src/crcalc/crcalc "$FWOUT" "$BINLOG" if [ $? -eq 0 ] then echo -n "Finished! " else echo -n "Firmware header not supported; firmware checksums may be incorrect. " fi # if a Buffalo image, then run encrypter - base on image name if [ "$(echo $FWOUT | grep -i 'buffalo')" != "" ] then # product name, version, key, encryption type can be specified here $KEY="" # specify full param, e.g. -k mykey $MAGIC="" $PRODUCT="" $LONGSTATE="" ./src/firmware-tools/buffalo-enc -i $FWOUT -o $FWOUT.buffalo.enc $KEY $MAGIC $PRODUCT $LONGSTATE #if [ $? -eq 0 ] #then # echo "Encrypted Buffalo image created." #else # echo "ERROR creating an encrypted Buffalo image" #fi fi echo "New firmware image has been saved to: $FWOUT" ================================================ FILE: check_for_upgrade.sh ================================================ #!/bin/sh ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 20110224-1507-MCT - Needed quotes around a string compare. ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # echo " Checking for updates ..." mkdir update_check cd update_check SYSNAME=`uname` if [ `expr "$SYSNAME" : "Darwin"` = 6 ]; then curl -O -s --connect-timeout 4 --retry 1 http://firmware-mod-kit.googlecode.com/svn/trunk/firmware_mod_kit_version.txt else wget --quiet --timeout=4 --tries=1 http://firmware-mod-kit.googlecode.com/svn/trunk/firmware_mod_kit_version.txt fi cd .. if [ ! -f "update_check/firmware_mod_kit_version.txt" ]; then echo " ! WARNING: Could not check for update. No connectivity or server down?" rm -rf update_check exit 1 fi NEW_VERSION=`cat update_check/firmware_mod_kit_version.txt` CUR_VERSION=`cat firmware_mod_kit_version.txt` if [ "$NEW_VERSION" != "$CUR_VERSION" ]; then echo " !!! There is a newer version available: $NEW_VERSION" echo " You are currently using $CUR_VERSION" else echo " You have the latest version of this kit." fi rm -rf update_check exit 0 ================================================ FILE: cleanup.sh ================================================ #!/bin/sh . ./shared.inc Cleanup ================================================ FILE: creating_ipkg_packages.htm ================================================ Creating IPKs

IPK Creation Kit
(c)2006 Jeremy Collake <jeremy.collake@gmail.com>

!!! ALPHA STAGE OF DEVELOPMENT. MAY NOT WORK AND HAVE MANY PROBLEMS !!!

This document attempts to outline the process of creation of IPKG format packages with the IPK Creation Kit, giving specific emphasis on usage for embedded linux platforms such as OpenWrt and DD-WRT. It is a quick draft intended to encourage people to develop IPKs specific to certain firmwares for use with the Firmware Modification Kit, a kit that allows easy modification of firmware images without recompiling the sources.

The structure of an IPK

IPK files are archives containing the following:

 

Using the IPK template

The IPK template directory contained in the Firmware Modification Kit makes it particularly easy to create IPK files without having to manually create them each time.

Creating your own IPK

Step 1

Copy or extract the IPK template directory to a new directory named after the package you are creating an IPK for. If you are copying, use "cp -r" to copy the entire directory and all its contents.

Step 2

In the new directory edit the "control" and "conffiles" text files appropriately. The fields in "control" are probably self-explanatory:

control:


Package: somepackage
Priority: optional
Depends: libpcap libncurses
Section: net
Description: A minimal and secure package of great sorts.
Maintainer: Junior Jim-Bob <juniorjim.bob.com>
Source: N/A
Version: 2.61-1
Architecture: mipsel
 

If you want to get fancy, the Source field can indicate a URL to download the data.tar.gz portion of the package. If instead the package files are included inside the PKG, leave "N/A" in this field.

"conffiles" contains a listing of files in the package that are used for configuration storage. This is helpful to preserve the configuration of the package if it is updated, or if the configuration otherwise needs preserving. It might look something like this after editing:

conffiles:


/etc/package_config/package.conf
/etc/package_config/moreconfig.conf
 

Step 3

Copy the package files into the folder in the same relative directories to which they will be installed to the file system. Symbolic links are allowed. For example:


./usr/sbin/mypackage
./tmp/etc/package_config/
./etc/package_config/ ---(symbolic link)---> ../tmp/etc/package_config/
./tmp/etc/package_config/moreconfig.conf
 

The above makes the /etc/package_config/ directory a symbolic link to /tmp/package_config/. This would be useful for firmwares that have a read-only /etc file system. On these systems, the configuration files could reside on a ram disk and be emitted at boot-time based on input from some other store of configuration variables, like NVRAM.

Step 4:

Build the IPK. You're done, now simply build the IPK file with the script provided. It's parameters are:

MAKE_IPK.SH OUTPUT_PACKAGE_IPK IPK_BASE_DIRECTORY

OUTPUT_PACKAGE_IPK : The IPK file to output. If it already exists it will be over-written.
IPK_BASE_DIRECTORY : The directory you created in step 1 and have been working with up until now.

Example:


make_ipk.sh package.ipk ../package_ipk_dir
 

 

To support this project:

 

This document (c)2006 Jeremy Collake.
All Rights reserved. This document may be freely republished in its unaltered and whole form only. Alterations or partial publishing requires approval of Jeremy Collake <jeremy@bitsum.com>.

================================================ FILE: ddwrt-gui-extract.sh ================================================ #!/bin/bash OUT="$1" DIR="$2" if [ "$DIR" == "" ] then DIR="fmk/rootfs" fi if [ "$OUT" == "" ] then OUT="www" fi if [ $UID -ne 0 ] then SUDO="sudo" fi eval $(cat shared-ng.inc) HTTPD="$DIR/usr/sbin/httpd" WWW="$DIR/etc/www" KEYFILE="$DIR/webcomp.key" echo -e "Firmware Mod Kit (ddwrt-gui-extract) $VERSION, (c)2013 Craig Heffner, Jeremy Collake\nhttp://www.bitsum.com\n" if [ ! -d "$DIR" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ] then echo -e "Usage: $0 [output directory] [rootfs directory]\n" exit 1 fi if [ ! -e "$HTTPD" ] || [ ! -e "$WWW" ] then echo "Unable to locate httpd / www files in directory $DIR. Quitting..." exit 1 fi # Extract! # key file is written to rootfs, and since may have root ownership, sudo TMPFILE=`mktemp /tmp/$0.XXXXXX` ./src/webcomp-tools/webdecomp --httpd="$HTTPD" --www="$WWW" --dir="$OUT" --key="$TMPFILE" --extract $SUDO cp "$TMPFILE" "$KEYFILE" ================================================ FILE: ddwrt-gui-rebuild.sh ================================================ #!/bin/bash WEBDIR="$1" DIR="$2" if [ "$DIR" == "" ] then DIR="fmk/rootfs" fi if [ "$WEBDIR" == "" ] then WEBDIR="www" fi # Web files were likely extracted as root, so we'll need root permissions to modify them if [ $UID -ne 0 ] then SUDO="sudo" fi eval $(cat shared-ng.inc) HTTPD="$DIR/usr/sbin/httpd" WWW="$DIR/etc/www" KEYFILE="$DIR/webcomp.key" echo -e "Firmware Mod Kit (ddwrt-gui-rebuild) $VERSION, (c)2011 Craig Heffner, Jeremy Collake\nhttp://www.bitsum.com\n" if [ ! -d "$DIR" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ] then echo -e "Usage: $0 [input directory] [rootfs directory]\n" exit 1 fi if [ ! -e "$HTTPD" ] || [ ! -e "$WWW" ] then echo "Unable to locate httpd / www files in directory $DIR. Quitting..." exit 1 fi # Restore! TMPFILE=`mktemp /tmp/$0.XXXXXX` # we actually pass a temporary copy of the keyfile to the webdecomp tool so that # the actual keyfile won't be included in the compiled web file system $SUDO mv "$KEYFILE" "$TMPFILE" $SUDO ./src/webcomp-tools/webdecomp --httpd="$HTTPD" --www="$WWW" --dir="$WEBDIR" --key="$TMPFILE" --restore $SUDO mv "$TMPFILE" "$KEYFILE" ================================================ FILE: extract-firmware.sh ================================================ #!/bin/bash IMG="${1}" DIR="${2}" if [ "${DIR}" = "" ] then DIR="fmk" fi # Need to extract file systems as ROOT if [ "$(id -ru)" != "0" ] then SUDO="sudo" else SUDO="" fi IMG=$(readlink -f $IMG) DIR=$(readlink -f $DIR) # Make sure we're operating out of the FMK directory cd $(dirname $(readlink -f $0)) # Source in/Import shared settings. ${DIR} MUST be defined prior to this! . ./shared-ng.inc printf "Firmware Mod Kit (build-ng) ${VERSION}, (c)2011-2013 Craig Heffner, Jeremy Collake\n\n" # Check usage if [ "${IMG}" = "" ] || [ "${IMG}" = "-h" ] then printf "Usage: ${0} \n\n" exit 1 fi if [ ! -f "${IMG}" ]; then echo "File does not exist!" exit 1 fi if [ -e "${DIR}" ] then echo "Directory ${DIR} already exists! Quitting..." exit 1 fi # Check if FMK has been built, and if not, build it if [ ! -e "./src/crcalc/crcalc" ] then echo "Firmware-Mod-Kit has not been built yet. Building..." cd src && ./configure && make if [ ${?} -eq 0 ] then cd - else echo "Build failed! Quitting..." exit 1 fi fi # Get the size, in bytes, of the target firmware image FW_SIZE=$(ls -l "${IMG}" | cut -d' ' -f5) # Create output directories mkdir -p "${DIR}/logs" mkdir -p "${DIR}/image_parts" echo "Scanning firmware..." # Log binwalk results to the ${BINLOG} file, disable default filters, exclude invalid results, # and search only for trx, uimage, dlob, squashfs, and cramfs results. #${BINWALK} -f "${BINLOG}" -d -x invalid -y trx -y uimage -y dlob -y squashfs -y cramfs "${IMG}" ${BINWALK} -f "${BINLOG}" "${IMG}" # Set Internal Field Separator (IFS) via two lines to newline only (bashism would be $'\n') IFS=' ' # Header image offset is ALWAYS 0. Header checksums are simply updated by build-ng.sh. HEADER_IMAGE_OFFSET=0 # Loop through binwalk log file for LINE in IFS=' '$(sort -n ${BINLOG} | grep -v -e '^DECIMAL' -e '^---') do # Get decimal file offset and the first word of the description OFFSET=$(echo ${LINE} | awk '{print $1}') DESCRIPTION=$(echo ${LINE} | awk '{print tolower($3)}') # Offset 0 is firmware header if [ "${OFFSET}" = "0" ] then HEADER_OFFSET=${OFFSET} HEADER_TYPE=${DESCRIPTION} HEADER_SIZE=$(echo ${LINE} | sed -e 's/.*header size: //' | cut -d' ' -f1) HEADER_IMAGE_SIZE=$(echo ${LINE} | sed -e 's/.*image size: //' | cut -d' ' -f1) # Check to see if this line is a file system entry elif [ "$(echo ${LINE} | grep -i filesystem)" != "" ] then FS_OFFSET=${OFFSET} FS_TYPE=${DESCRIPTION} # Need to know endianess for re-assembly if [ "$(echo ${LINE} | grep -i 'big endian')" != "" ] then ENDIANESS="-be" else ENDIANESS="-le" fi # Check for LZMA compression in the file system. If not present, assume gzip. # This is only used for squashfs 4.0 images. if [ "$(echo ${LINE} | grep -i 'lzma')" != "" ] then FS_COMPRESSION="lzma" else FS_COMPRESSION="gzip" fi # Check for a block size (used only by mksquashfs) if [ "$(echo ${LINE} | grep -i 'blocksize')" != "" ] then set -f IFS=, for fsparam in ${LINE} do if [[ $fsparam = *blocksize* ]]; then fsparam="${fsparam##*blocksize: }" FS_BLOCKSIZE="${fsparam%* bytes}" break fi done fi set +f; unset IFS fi done # Header image size is everything from the header image offset (0) up to the file system HEADER_IMAGE_SIZE=$((${FS_OFFSET}-${HEADER_IMAGE_OFFSET})) # Extract the header + image up to the file system echo "Extracting ${HEADER_IMAGE_SIZE} bytes of ${HEADER_TYPE} header image at offset ${HEADER_IMAGE_OFFSET}" dd if="${IMG}" bs=${HEADER_IMAGE_SIZE} skip=${HEADER_IMAGE_OFFSET} count=1 of="${HEADER_IMAGE}" 2>/dev/null if [ "${FS_OFFSET}" != "" ] then echo "Extracting ${FS_TYPE} file system at offset ${FS_OFFSET}" dd if="${IMG}" bs=${FS_OFFSET} skip=1 of="${FSIMG}" 2>/dev/null else echo "ERROR: No supported file system found! Aborting..." rm -rf "${DIR}" exit 1 fi FOOTER_SIZE=0 FOOTER_OFFSET=0 # Try to determine if there is a footer at the end of the firmware image. # Grab the last 10 lines of a hexdump of the firmware image, excluding the # last line in the hexdump. Reverse the line order and replace any lines # that start with '*' with the word 'FILLER'. for LINE in $(hexdump -C ${IMG} | tail -11 | head -10 | sed -n '1!G;h;$p' | sed -e 's/^*/FILLER/') do if [ "${LINE}" = "FILLER" ] then break else FOOTER_SIZE=$((${FOOTER_SIZE}+16)) fi done # If a footer was found, dump it out if [ "${FOOTER_SIZE}" != "0" ] then FOOTER_OFFSET=$((${FW_SIZE}-${FOOTER_SIZE})) echo "Extracting ${FOOTER_SIZE} byte footer from offset ${FOOTER_OFFSET}" dd if="${IMG}" bs=1 skip=${FOOTER_OFFSET} count=${FOOTER_SIZE} of="${FOOTER_IMAGE}" 2>/dev/null else FOOTER_OFFSET=${FW_SIZE} fi # Log the parsed values to the CONFLOG for use when re-building the firmware echo "FW_SIZE='${FW_SIZE}'" > ${CONFLOG} echo "HEADER_TYPE='${HEADER_TYPE}'" >> ${CONFLOG} echo "HEADER_SIZE='${HEADER_SIZE}'" >> ${CONFLOG} echo "HEADER_IMAGE_SIZE='${HEADER_IMAGE_SIZE}'" >> ${CONFLOG} echo "HEADER_IMAGE_OFFSET='${HEADER_IMAGE_OFFSET}'" >> ${CONFLOG} echo "FOOTER_SIZE='${FOOTER_SIZE}'" >> ${CONFLOG} echo "FOOTER_OFFSET='${FOOTER_OFFSET}'" >> ${CONFLOG} echo "FS_TYPE='${FS_TYPE}'" >> ${CONFLOG} echo "FS_OFFSET='${FS_OFFSET}'" >> ${CONFLOG} echo "FS_COMPRESSION='${FS_COMPRESSION}'" >> ${CONFLOG} echo "FS_BLOCKSIZE='${FS_BLOCKSIZE}'" >> ${CONFLOG} echo "ENDIANESS='${ENDIANESS}'" >> ${CONFLOG} # Extract the file system and save the MKFS variable to the CONFLOG case ${FS_TYPE} in "squashfs") echo "Extracting squashfs files..." ${SUDO} ./unsquashfs_all.sh "${FSIMG}" "${ROOTFS}" 2>/dev/null | grep MKFS >> "${CONFLOG}" ;; "cramfs") echo "Extracting CramFS file system..." ${SUDO} ./uncramfs_all.sh "${FSIMG}" "${ROOTFS}" ${ENDIANESS} 2>/dev/null | grep MKFS >> "${CONFLOG}" ;; *) echo "Unsupported file system '${FS_TYPE}'! Quitting..." rm -rf "${DIR}" exit 1 ;; esac # Check if file system extraction was successful if [ ${?} -eq 0 ] then echo "Firmware extraction successful!" echo "Firmware parts can be found in '${DIR}/*'" else echo "Firmware extraction failed!" rm -rf "${DIR}" exit 1 fi exit 0 ================================================ FILE: firmware_mod_kit.htm ================================================ Firmware Modification Kit

Firmware Modification Kit
Giving YOU the power to customize your firmware
documentation version 0.78 beta
all scripts, untrx, wrt_vx_imgtool, crcalc, binwalk and docs (c) 2006-2011
Craig Heffner <heffnercj@gmail.com>, Jeremy Collake <jeremy.collake@gmail.com>, and other contributors (see project page)
other portions (c) their respective holders

THERE ARE NEW DOCS: This documentation may be superseded or extended by documentation at the Google Code project site. An essentially new, and much improved, rendition is now available. Firmware-Mod-Kit-Ng ;)

Contents

I. Description
II. Why is this useful?
III. Where to get the kit
IV. Requirements
V. Compatibility
VI. Instructions
    A. extracting firmware
    B. modifying firmware
        1. installing packages
        2. removing packages
    C. re-building firmware
VII. Caveats
    A. binary compatibility issues
    B. maximum firmware size
    C. solutions to file system incompatibilities
VIII. Acknowledgements and more
IX. Links
X. Revision history

 

I. Description

This kit gives the user the ability to make changes to a firmware image without recompiling the firmware sources. It works by extracting the firmware into its component parts, then extracting the file system image (assuming its in one the supported formats). The user can then make modifications to the extracted file system, and rebuild the firmware image.

Although this kit completely automates the process, it is also useful for those who need a handy collection of utilities to manipulate firmware images. The following utilities are included in this kit, along with scripts to automate their use:

ASUSTRX An extended version of ASUSTRX that can build both 'normal' TRX files and, optionally, those with an ASUS addver style header appended. It can also, uniquely, force segment offsets in the TRX (with -b switch) for compatibility with Marvell ASUS devices like the WL-530g. This tool replaces both 'normal' trx tool and addver. Current versions included are: 0.90 beta.
ADDPATTERN Utility to pre-pend Linksys style HDR0 header to a TRX.
ADDVER ASUS utility to append a header to a TRX image that contains version information. ASUSTRX includes this capability. Current version: unversioned.
BINWALK Firmware analysis tool, used for searching firmware images for known file types. Used by the extract-ng.sh script to identify valid file systems inside firmware images. Current version included is 0.3.9. Tool home page: http://binwalk.googlecode.com.
CRAMFSCK CRAMFS file system image checker and extractor. Current versions included are:  2.4x.
CRCALC Re-calculates and patches header checksums for TRX and uImage firmware headers.
MKSQUASHFS Builds a squashfs file system image. Current versions included are: 2.1-r2, 3.0.
MKCRAMFS Builds a cramfs file system image. Coming in next version. Current versions included are: 2.4x.
MOTOROLA_BIN A utility that prepends 8 byte headers to TRX images for Motorola devices WR850G, WA840G, WE800G. Current version: unversioned.
UNCRAMFS Alternate tool to extracts a cramfs file system image. Use cramfsck instead whenever possible as it seems to be more reliable. Current versions included are: 0.7 (for cramfs v2.x).
UNCRAMFS-LZMA Extracts an lzma cramfs file system image, specifically those included in OpenRG based firmware. Current version included is 0.7rg.
UNSQUASHFS Extracts a zlib squashfs file system image. Current versions included are 1.0 for 3.0 images and 1.0 for 2.x images (my own blend).
UNSQUASHFS-LZMA Extracts an lzma squashfs file system image. Current versions included are 1.0 for 3.0 images and 1.0 for 2.x images (my own blend). Note: Not all squashfs-lzma patches are compatible with one another. I'm working on adding support for all common squashfs-lzma variations.
UNTRX Splits TRX style firmwares into their component parts. Also supports pre-pended addpattern HDR0 style headers. This was developed exclusively for this kit. Current versions included are: 0.45.
WRT_VX_IMGTOOL Utility to generate VxWorks compatible firmware images for the WRT54G(S) v5 series.

 

Tools/changes unique to this kit

This kit doesn't just collect existing tools, it also offers new ones and modifications to existing ones. Custom code currently is:

ASUSTRX - Modified to allow '-b' switch to force segment offsets (needed for some devices, like the WL-530g).
CRCALC - A new tool to re-calculate and patch the checksum fields for common firmware headers. Currently TRX and uImage headers are supported.
UNTRX - A new tool to extract the contents of a TRX image into its component parts.
UNSQUASHFS - Custom blend that supports extraction of 2.x squashfs images. This tool wasn't officially made available until squashfs 3.0, so up until now it wasn't available for 2.x images.
WRT-VX-IMGTOOL - A new tool to view, extract, build, and fix VxWorks compatible firmware images for the WRT54G(S) v5 series.
SPLITTER3 - Custom file splitter for certain types of linux firmware images.

II. Why is this useful?

A list of some of the many reasons this might be desired are:


 

III. Where to get the kit

The best way to download and use this kit is to check out the sources from the repository. The automated scripts all automatically build the executables, and the sources. It is easy as downloading something and using it that way. Also, if you are unable to use a simple SVN checkout, then it is likely that this kit is a danger to you because it is for advanced users.

To anonymously check out the firmware-mod-kit:

 mkdir firmware_mod_kit
 cd firmware_mod_kit
 svn checkout http://firmware-mod-kit.googlecode.com/svn/trunk/ firmware-mod-kit-read-only


Kit downloads and links:

Project hosting and repository (new): http://code.google.com/p/firmware-mod-kit/
Guest SVN Checkout: svn checkout http://firmware-mod-kit.googlecode.com/svn/trunk/ firmware-mod-kit-read-only
User forums can be found here.

Packages:

All of the many OpenWrt packages should work with OpenWrt images and many other firmware images.

An old (2009) specific collection of DD-WRT packages for use with the kit: http://www.bitsum.com/files/ddwrt_packages.tar.gz .
 

 

IV. Requirements

I've worked to make sure the requirements are low enough for anyone to use this kit. However, to reduce distribution costs and better represent the multi-platform capabilities of this kit, the binary tools in the kit do automatically build themselves the first time you run one of the scripts. Any machine set up to build anything C or C++ on the machine will probably be ready. The few requirements are all basic items that everyone has easy access to:

OS/X is not supported at this time. The kit is probably not far from compatibility, but easier to just install a linux VM.

V. Compatibility

Any TRX style firmware image format should that uses squashfs-lzma as a root file system work fine. Firmwares that use regular zlib squashfs or unsupported file systems will work if the steps that extract the file system and rebuild the file system are tweaked.

The kit can build firmware images for the following devices, amongst many others:

The kit is known (or thought) to be compatible with the following firmwares:

DD-WRT v23 tested - versions v23 SP1 and later are compatible (soon older versions too). WARNING: Builds of DD-WRT later than 08/04/2006 (v23 SP2) have some protections against changing the web UI.
DD-WRT v24 tested
OpenWrt White Russian tested
OpenWrt Kamikaze untested (should work) - not really necessary, based on OpenWrt has its Image Builder.
FreeWrt untested - should work ok
HyperWrt untested
Ewrt untested
Sveasoft Alchemy untested
Sveasoft Talisman untested
Linksys / other vendor not supported by scripts yet - haven't added cramfs handling
ASUS WL-330G untested - should work ok
ASUS WL-520G untested - should work ok
ASUS WL-530G supported
ASUS WL-550G untested  - should work ok
Trendnet TEW-632BRP tested
DLink DIR-615 untested
many others* untested

* Even if the kit doesn't automatically support the firmware or device you want, you can manually use the tools inside to manipulate many firmware images, or request support be added.

 

VI. Instructions

I've scripts that simply and abstract the firmware modification process. Basically, it's a one-step process to extract the firmware, and a one-step process to rebuild the firmware. There are also scripts to install or remove individual packages or entire directories of packages.

The procedure of calls is:

  1. extract_firmware.sh ....
  2. (optional) ipkg_install[_all]).sh ...
  3. (optional) ipkg_remove[_all].sh   ...
  4. build_firmware.sh

 

A. Extracting the firmware (extract_firmware.sh, extract-ng.sh)

Simply run extract_firmware.sh with the following parameters. You must run this tool from inside the directory it exists in.


$ ./extract_firmware.sh firmware.bin working_directory/
 


- firmware.bin is the firmware image you want to extract, i.e. DD-WRT.v23_MICRO_GENERIC.BIN.
- working_directory is the working directory you want to use. This is where the intermediate files and the extracted file system will be stored. Note that files in the working directory may be deleted!

It doesn't matter which firmware image you supply, i.e. for a WRT54G or an ASUS WL-500G. These images are usually all the same and differ only in the header format. The rebuilding process will create images for the various models.

An extraction log is created as extract.log.

If extract_firmware.sh fails, the newer extract-ng.sh can be used. Although newer and less thoroughly tested than extract_firmware.sh, it is more flexible and can often extract file systems that extract_firmware.sh cannot:


$ ./extract-ng.sh firmware.bin working_directory/
 

 

B. Making changes to the firmware's file system

Modifying the firmware is simple. The file system is stored in the working directory you supplied to extract_firmware.sh. Here are the subfolders of this directory:

    rootfs/
       
This is where the file system is. Make modifications here.
    image_parts/
       
This is where intermediate files are stored. If you need to replace the kernel (not at all recommended), you can do so by replacing the appropriate file here (usually segment2).
    installed_packages/
       
If you use the ipkg_install.sh tool, this is where packages you've installed after firmware extraction will reside.

One can manually change the files in rootfs and/or use the automated package scripts.

 

Installing packages (.IPK)

In compliment to manually making changes, one can use pre-built IPKG format package files with the ipkg_install/remove scripts. Although not all will work and a repository for packages verified to work has not yet been produced, many packages work just fine.

Packages are pre-built collections of files pertaining to a set of software. OpenWrt and DD-WRT both use packages, and most are cross-compatible. These packages are stored in a tar/gzip archive of a pre-defined structure that includes some control files. You can extract and copy the files manually, or use the ipkg_install.sh script included with this kit. For a list of some of the available packages (not all may work), see http://downloads.openwrt.org/whiterussian/packages/ and http://ftp.selfnet.de/pub/openwrt/backports/rc5/ . We are currently in the process of compiling a set of packages known to be good for DD-WRT ... to help in this matter please visit here.

For information on how to create IPKs, see the IPK Creation Kit.

Example use:


$ ./ipkg_install.sh some_package-1.2.5.ipk working_directory/
 

some_package-1.2.5.ipkg would be the filename of the package.
working_directory is the same working directory you supplied to the extract_firmware.sh script.

Notes:

A script, ipkg_install_all.sh is also available to install an entire folder of packages.

The collection of installed packages will be stored in working_directory/installed_packages .

 

Removing packages (.IPK)

To remove packages there is the ipkg_remove.sh script.

Example use:


$ ./ipkg_remove.sh some_package-1.2.5.ipk working_directory/
 

some_package-1.2.5.ipkg would be the filename of the package.
working_directory is the same working directory you supplied to the extract_firmware.sh script.

Notes:

A script, ipkg_remove_all.sh is also available to install an entire folder of packages.

The collection of installed packages stored working_directory/installed_packages will be updated to reflect the change if successful.

 

C. Re-building the firmware (build_firmware.sh, build-ng.sh)

Rebuilding the firmware is as easy as extracting it. Use the build_firmware.sh script to automate the process.  You must run this tool from inside the directory it exists in.

Example use:


$ ./build_firmware.sh output_directory/ working_directory/
 

- output_directory is the path to which the created firmware images should be stored. If images already exist here, they will be over-written. Firmware images for various models will be emitted (these images are all the same but have different header patterns so they are accepted by the target models).
- working_directory is the working directory supplied to extract_firmware.sh.

A building log is created as build.log.

If extract-ng.sh was used to extract the firmware image, build-ng.sh must be used to rebuild it:


$ ./build-ng.sh working_directory/
 

 

VIII. Caveats

There are a few things to watch out for when modifying firmware images. If you make reasonable changes these problems will probably never affect you. Be warned, this section may be technical in parts.

A. Binary compatibility issues

B. Maximum firmware size

Currently, the maximum firmware image size supported by this kit is 5,898,240 (0x5A0000) bytes, but can be adjusted through the "-m [size]" parameter of the asustrx tool.


C. Solutions to file system incompatibilities

! This section is very much a work in progress !

The squashfs file system is case sensitive (i.e. teSt.bin ! = test.bin) and adheres to EXT2 naming rules. To support proper extraction of the file system, the working directory should be on a case sensitive file system and support symbolic links. The scripts will warn you if you attempt to use as working directory on a case INsensitive file system. You'll see a number of errors if you extract to a file system that doesn't support symbolic links.

Note: Case insensitivity doesn't always cause problems, especially if the file system preserves case ok. It depends on the firmware and version. Most of the time for DD-WRT as long as a case preserving file system is used as a working directory, all should work fine.

These solutions apply to those using CYGWIN, or some other environment that may not have a case sensitive file system by default. Linux users typically do not have this problem since EXT2 and EXT3 file systems are case sensitive.


WARNING: THESE ARE IN EARLY STAGES OF TESTING AND MAY NOT WORK.

  Applies to Description
SOLUTION 1 CYGWIN, OTHER It's reported this does not work under CYGWIN due to the CYGWIN utilities all being case INsensitive (thanks pagedude).

Use a network share to a case sensitive file system. This is, by far, the easiest solution. Simply use an appropriate network share for the working directory.
 
SOLUTION 2 CYGWIN
For NT partitions it's reported you can enable case sensitivity through the following registry key, but I do not know if this works or not.

 \HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\obcaseinsensitive [REG_DWORD] = 0
 

SOLUTION 3 OS X (not usually needed, at least for DD-WRT)
One can either Turn on HSFX for the boot disk, or (more easily) create a temporary HSFX case sensitive file system to use as a working directory.

Example of how to create a temporary HSFX case sensitive file system:

to create:
$ hdiutil create -size 20m -fs HFSX -volname db90h -nouuid test-image
to mount:
$ hdiutil attach test-image.dmg
to un-mount:
$ hdiutil detach /Volumes/db90h

(thanks solarflare for this information)
 

SOLUTION 4 CYGWIN
 

Mount an ext2 files system. Eko, of DD-WRT forums, contributes this tip. Make a partition on a hard drive or USB thumb drive, then install "Ext2 Installable File System For Windows". 10MB should generally be plenty of working directory space, but 20MB is suggested for more optimal file system performance.
 

    

IV. Acknowledgments and more

The authors and maintainers of this kit are Jeremy Collake (db90h) and Craig Heffner.  Special thanks to Solarflare, TexHex <floh@fbesser.de>, and others.

If YOU would like to contribute to this kit, send me an email at jeremy.collake@gmail.com or visit the current project hosting at http://code.google.com/p/firmware-mod-kit/ . Developers are welcome.

 

X. Links

 

X. Revision history

0.73

0.72

0.64-0.71

0.63

0.60

0.58

0.56

0.54

0.51

0.50

0.49

0.48

0.471

0.47

0.46:

0.45:

0.43:

0.42:

0.40 beta  (md5: 786472cfa03fb1cd70e1b025d091168b)

0.33 beta

0.31 beta

0.30 beta

0.29 beta

0.28 beta

0.27 beta

0.26 beta

0.25 beta

0.23 beta

0.22 beta

0.20 beta

v0.15 beta

v0.13 alpha: Documentation updates, re-included pre-built executables
v0.10 alpha: First decent public release.

 

 

This document (c)2006-2011 Jeremy Collake and Craig Heffner.
All Rights reserved. This document may be freely republished in its unaltered and whole form only. Alterations or partial publishing requires approval of creator(s).

 This kit is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

================================================ FILE: firmware_mod_kit_version.txt ================================================ 0.82 ================================================ FILE: ipk_template/conffiles ================================================ test ================================================ FILE: ipk_template/control ================================================ Package: package_name Priority: optional Section: net Depends: libncurses Description: Some package description. Maintainer: Some guy Source: N/A Version: 1.01-1 Architecture: mipsel ================================================ FILE: ipk_template/debian_binary ================================================ 2.0 ================================================ FILE: ipk_template/make_ipk.sh ================================================ #!/bin/sh VERSION="0.01 alpha" # # Title: make_ipk.sh # Author: Jeremy Collake # # Creates a IPK from the given directory # # echo "$0 (c)2006 Jeremy Collake make_ipkg.log OLD_DIR=`pwd` if [ -f "$2" ]; then echo " Erasing existing $2 ..." rm $2 #>> make_ipkg.log 2>&1 fi ############################################## # change to package ipk folder # cd "$2" ############################################## # do some cleanup from any previous runs # rm "packagetemp.tar" ############################################## # create control.tar # echo " Creating control.tar ..." tar -cf "control.tar" "./control" "./conffiles" if [ $? != 0 ] || [ ! -f "control.tar" ]; then echo " ERROR: creation of $2/control.tar failed!" exit 2 fi ############################################## # create control.tar.gz # echo " Creating control.tar.gz ..." gzip < "control.tar" > "control.tar.gz" if [ $? != 0 ] || [ ! -f "control.tar.gz" ]; then echo " ERROR: creation of $2/control.tar.gz failed!" exit 2 fi ############################################## # create data.tar # # exclude control, conffiles, this script (if it exists), # and anything else prudent to ignore # echo " Creating data.tar ..." OUR_BASENAME=`basename $0` IPK_BASENAME=`basename $1` # just get top-level directories actually ALL_FILES=`find "./" -maxdepth 1 | sed 1d` rm data.tar INPUT_FILES=" " for i in $ALL_FILES; do echo " Processing $i " if [ -d $i ]; then INPUT_FILES=`echo $INPUT_FILES "$i"` fi done echo " dbg.infiles: $INPUT_FILES" tar "--exclude=./control.tar" "--exclude=./control" "--exclude=./conffile*" "--exclude=./$OUR_BASENAME" "--exclude=./$IPK_BASENAME" "--exclude=./make_ipk*.log" -cvf data.tar $INPUT_FILES echo " -------- current data.tar ----------" tar -tvf data.tar if [ $? != 0 ] || [ ! -f "data.tar" ]; then echo " ERROR: creation of $2/data.tar failed!" exit 2 fi ############################################## # create data.tar.gz # # exclude control, conffiles, and this script if it's there.. # echo " Creating data.tar.gz ..." OUR_BASENAME=`basename $0` gzip < "data.tar" > "data.tar.gz" if [ $? != 0 ] || [ ! -f "data.tar.gz" ]; then echo " ERROR: creation of $2/data.tar.gz failed!" exit 2 fi ############################################## # create PACKAGE.tar # tar -cf "packagetemp.tar" "./control.tar.gz" "./data.tar.gz" "./debian_binary" if [ $? != 0 ] || [ ! -f "packagetemp.tar" ]; then echo " ERROR: creation of packagetemp.tar failed!" exit 2 fi ############################################## # finally gzip the result to PACKAGE.ipk # gzip < "packagetemp.tar" > "$1" if [ $? != 0 ] || [ ! -f $1 ]; then echo " ERROR: creation of $1 failed!" exit 2 fi echo " Done. Created: $1" cd $OLD_DIR ================================================ FILE: ipkg_install.sh ================================================ #!/bin/sh # # $Id: ipkg_install.sh 336 2012-08-04 00:12:14Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" # # Title: ipkg_install.sh # Author: Jeremy Collake # Site: http://code.google.com/p/firmware-mod-kit/ # # Do a really dumb package install. No dependencies, # removal, or anything. Just extract the data files # to the file system. # # See documentation at: # http://www.bitsum.com/firmware_mod_kit.htm # # USAGE: ipkg_install.sh PACKAGE_SOURCE WORKING_DIRECTORY/ # # PACKAGE_SOURCE is the path to the .PKG file. # # WORKING_DIRECTORY is the working directory supplied to # extract_firmware.sh. # # Example: # # ./ipkg_install.sh nano_1.3.8-1_mipsel.ipk ../working_dir/ # # todo: need to get full path of log file because directory # change causes log files in both. # # todo: this does NOT work with sources that aren't local # yet.. # # # echo "$0 v$VERSION, (c)2006-2012 Jeremy Collake" echo " !!WARNING!!! This script is in early alpha stage of development" ############################################333 # CleanupTmp [base_dir] [package basename] # # basename=name w/o IPK (contrasts below labels) CleanupTmp() { echo " Cleanup" >> /dev/null 2>&1 rm -rf "$1/tmp" >> /dev/null 2>&1 rm -f "$1/$2" >> /dev/null 2>&1 } ################################################## if [ ! $# = "2" ]; then echo " Invalid usage" echo " USAGE: $0 PACKAGE_PATH WORKING_DIRECTORY" exit 1 fi BASE_NAME=`basename $1` echo " Installing $BASE_NAME" #################################################### if [ ! -e "$1" ]; then echo " ERROR: $1 does not exist." exit 1 fi OLD_DIR=`pwd` ################################################## # notes: # OS X's tar utility doesn't like GZIP'd TARs .. (re: not TAR'd GZIPs ..), # else we could just use tar (which under linux accepts GZIPs as well). # mkdir -p "$2/installed_packages/" >> ipkg_install.log 2>&1 cp $1 "$2/installed_packages/" cd "$2/installed_packages" INSIDE_NAME=`echo "$BASE_NAME" | sed "s/.ipk/ /"` gunzip < "$BASE_NAME" > "$INSIDE_NAME" echo " Assuming contents bore $INSIDE_NAME" rm -rf tmp mkdir tmp tar -xf "$INSIDE_NAME" -C "tmp/" if [ $? != 0 ]; then echo " ERROR: Extraction failed or incompatible format." CleanupTmp "." "$INSIDE_NAME" exit 1 fi ################################################## echo " --------------------------------------------" echo " Examining control files $2/rootfs ..." echo " Pay attention to the dependencies as you" echo " may need to install some of them ..." echo tar -xzvf "tmp/control.tar.gz" -C "tmp/" if [ $? != "0" ] || [ ! -e "tmp/control" ]; then echo " ERROR: Extraction failed of control files (missing from IPK?)" CleanupTmp "." "$INSIDE_NAME" cd "$OLD_DIR" exit 1 else # todo: add proper dependency checking and more # OLD_IFS="$IFS" IFS="NEWLINE" cat "tmp/control" for i in $( cat "tmp/control" | sed "s/N\/A/ /" ); do #echo " | $i" if [ `expr "$i" : "Source"` = 7 ]; then SOURCE_PATH=`echo $i | sed s/Source:/ /` #echo " dbg: handling SOURCE of $SOURCE_PATH" if [ `expr "$SOURCE_PATH" : "http://"` = 7 ] || [ `expr "$SOURCE_PATH" : "ftp://"` = 7 ]; then echo " Found remote source .. downloading" echo " !! THIS PART IS UNTESTED. WHO KNOWS IF IT WORKS ATM ;p" wget "$SOURCE_PATH" fi fi done fi IFS="$OLD_IFS" echo " --------------------------------------------" ################################################## echo " Extracting data files to $2/rootfs ..." tar --overwrite -xzvf "tmp/data.tar.gz" -C "../rootfs" # no longer do this, we'll let the user evaluate the tar output.. #if [ "$?" != "0" ]; then # echo " ERROR: Extraction failed of data.tar.gz - missing from IPK?" # CleanupTmp "." "$INSIDE_NAME" # cd "$OLD_DIR" # exit 1 #else echo " Package installed !" #fi ################################################## CleanupTmp "." "$INSIDE_NAME" cd "$OLD_DIR" exit 0 ================================================ FILE: ipkg_install_all.sh ================================================ #!/bin/sh # # $Id: ipkg_install_all.sh 336 2012-08-04 00:12:14Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" # # Title: ipkg_install_all.sh # Author: Jeremy Collake # Site: hhttp://code.google.com/p/firmware-mod-kit/ # # Invoke ipkg_install for every package in the given # folder. # # See documentation at: # http://www.bitsum.com/firmware_mod_kit.htm # # USAGE: ipkg_install_all.sh PACKAGES_FOLDER WORKING_DIRECTORY/ # # PACKAGE_SOURCE is the path to the .PKG file(s). # # WORKING_DIRECTORY is the working directory supplied to # extract_firmware.sh. # # Example: # # ./ipkg_install_all.sh ../packages ../working_dir/ # echo "$0 v$VERSION, (c)2006-2012 Jeremy Collake" ################################################## if [ ! $# = "2" ]; then echo " Invalid usage" echo " USAGE: $0 PACKAGE_PATH WORKING_DIRECTORY" exit 1 fi BASE_NAME=`basename $1` echo " Installing $BASE_NAME" ################################################## if [ ! -e "$1" ]; then echo " ERROR: $1 does not exist." exit 1 fi ################################################## for i in $( ls "$1" ); do ./ipkg_install.sh $1/$i $2 done ================================================ FILE: ipkg_remove.sh ================================================ #!/bin/sh # # $Id: ipkg_remove.sh 336 2012-08-04 00:12:14Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" ################################################## # # Title: ipkg_remove.sh # Author: Jeremy Collake # Site: hhttp://code.google.com/p/firmware-mod-kit/ # # # USAGE: ipkg_remove.sh nano_1.3.8-1_mipsel.ipk WORKING_DIRECTORY/ # # # Example: # # ./ipkg_remove.sh dd-wrt.v23_generic.bin std_generic # # echo "$0 v$VERSION, (c)2006-2012 Jeremy Collake" echo " !!WARNING!!! This script is in early alpha stage of development" ################################################## # CleanupTmp [base_dir] [package basename] # CleanupTmp() { rm -rf "$1/tmp" >> /dev/null 2>&1 rm "$/control.tar.gz" >> /dev/null 2>&1 rm "$/data.tar.gz" >> /dev/null 2>&1 rm "$1/$2" >> /dev/null 2>&1 } ########################################################### # DeleteWithFolderTemplate ( target_dir , template_dir ) # # deletes files and folders from a target folder # based on their presence in a template folder # (all files/dirs in template folder deleted from # target folder). # # This function calls itself recursively. # # One would think there'd be an easier way to accomplish # this, and maybe there is... I am not a bash guru. # DeleteWithFolderTemplate() { local TARGET_DIR=$1 local TEMPLATE_DIR=$2 #echo " Processing folder $TEMPLATE_DIR .." ################################################## for i in `ls $TEMPLATE_DIR`; do #echo " dbg: $TEMPLATE_DIR/$i" if [ -d $TEMPLATE_DIR/$i ]; then if [ -L $TEMPLATE_DIR/$i ]; then echo " Removing symbolic link $TARGET_DIR/$i" rm $TARGET_DIR/$i >> /dev/null 2>&1 else DeleteWithFolderTemplate $TARGET_DIR/$i $TEMPLATE_DIR/$i # now remove folder if empty rmdir $TARGET_DIR/$i >> /dev/null 2>&1 fi elif [ -f $TEMPLATE_DIR/$i ]; then echo " Removing file at $TARGET_DIR/$i" rm $TARGET_DIR/$i >> /dev/null 2>&1 else echo " WARNING: Unknown file type at $TEMPLATE_DIR/$i" fi done } ################################################## if [ ! $# = "2" ]; then echo " Invalid usage" echo " USAGE: $0 PACKAGE_PATH WORKING_DIRECTORY" exit 1 fi BASE_NAME=`basename $1` echo " Removing $BASE_NAME" #################################################### if [ ! -e "$1" ]; then echo " ERROR: $1 does not exist." exit 1 fi OLD_DIR=`pwd` ################################################## # notes: # OS X's tar utility doesn't like GZIP'd TARs .. (re: not TAR'd GZIPs ..), # else we could just use tar (wh##################################################ich under linux accepts GZIPs as well). # mkdir -p "$2/installed_packages/" >> ipkg_remove.log 2>&1 cp $1 "$2/installed_packages/" cd "$2/installed_packages" INSIDE_NAME=`echo "$BASE_NAME" | sed "s/.ipk/ /"` gunzip < "$BASE_NAME" > "$INSIDE_NAME" echo " Assuming contents bore $INSIDE_NAME" rm -rf tmp mkdir tmp tar -xf "$INSIDE_NAME" -C "tmp/" >> /dev/null 2>&1 if [ $? != 0 ]; then echo " ERROR: Extraction failed or incompatible format." #CleanupTmp "." "$INSIDE_NAME" exit 1 fi ################################################## echo " Removing files from $2/rootfs ..." rm -rf "tmp/data" >> /dev/null 2>&1 mkdir -p "tmp/data" >> /dev/null 2>&1 tar -xzvf "tmp/data.tar.gz" -C "tmp/data" >> /dev/null 2>&1 if [ $? != 0 ]; then echo " ERROR: Extraction failed of data.tar.gz (missing from IPK?)" CleanupTmp "." "$INSIDE_NAME" cd "$OLD_DIR" exit 1 else echo " Package removed successfully!" fi # # using . as a template, delete from working rootfs # cd "$OLD_DIR" DeleteWithFolderTemplate $2/rootfs "$2/installed_packages/tmp/data" cd "$2/installed_packages" ################################################## echo " --------------------------------------------" echo " Examining control files $2/rootfs ..." echo " Pay attention to the dependencies as you" echo " may want to remove some of them if not" echo " used by any other installed package." echo tar -xzf "tmp/control.tar.gz" -C "tmp/" if [ $? != 0 ] || [ ! -e "tmp/control" ]; then echo " ERROR: Extraction failed of control files (missing from IPK?)" CleanupTmp "." "$INSIDE_NAME" cd "$OLD_DIR" exit 1 else # todo: add proper dependency checking and more cat "tmp/control" # if successeful, remove the package from the installed_packages # folder CleanupTmp "." "$INSIDE_NAME" echo " Removing package IPK from installed_packages ..." cd "$OLD_DIR" fi echo " --------------------------------------------" ################################################## exit 0 ================================================ FILE: ipkg_remove_all.sh ================================================ #!/bin/sh # # $Id: ipkg_remove_all.sh 336 2012-08-04 00:12:14Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" # # Title: ipkg_install_all.sh # Author: Jeremy Collake # Site: http://code.google.com/p/firmware-mod-kit/ # # Invoke ipkg_install for every package in the given # folder. # # See documentation at: # http://www.bitsum.com/firmware_mod_kit.htm # # USAGE: ipkg_remove_all.sh PACKAGES_FOLDER WORKING_DIRECTORY/ # # PACKAGE_SOURCE is the path to the .PKG file(s). # # WORKING_DIRECTORY is the working directory supplied to # extract_firmware.sh. # # Example: # # ./ipkg_remove_all.sh ../packages ../working_dir/ # echo "$0 v$VERSION, (c)2006-2012 Jeremy Collake" ################################################## if [ ! $# = "2" ]; then echo " Invalid usage" echo " USAGE: $0 PACKAGE_PATH WORKING_DIRECTORY" exit 1 fi BASE_NAME=`basename $1` echo " Installing $BASE_NAME" ################################################## if [ ! -e "$1" ]; then echo " ERROR: $1 does not exist." exit 1 fi ################################################## for i in $( ls "$1" ); do "./ipkg_remove.sh" "$1/$i" "$2" done ================================================ FILE: old-build.sh ================================================ #!/bin/sh # # $Id: build_firmware.sh 333 2012-08-03 22:59:39Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" # # Title: build_firmware.sh # Author: Jeremy Collake # Site: http://code.google.com/p/firmware-mod-kit/ # # USAGE: old-build.sh OUTPUT_DIRECTORY/ WORKING_DIRECOTRY/ # # This scripts builds the firmware image from [WORKING_DIRECTORY], # with the following subdirectories: # # image_parts/ <- firmware seperated # rootfs/ <- filesystem # # Example: # # ./old-build.sh new_firmwares/ std_generic/ # ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 20110225-0746-MCT - Added rebuild number. # + Enhanced previous patch to include a rebuild # number that increments. # + Moved this log to below the authors space. # 20110224-1507-MCT - Two simple mods. # + Put the name of the build into an external file so that # it's easier to customize. # + Modified a var to correct the spelling. :) # Changed FIRMARE_BASE_NAME to FIRMWARE_BASE_NAME ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # EXIT_ON_FS_PROBLEM="0" echo echo " Firmware Mod Kit (extract) v$VERSION, (c)2010-2012 Jeremy Collake, - Newer NG edition by Craig Heffner" ################################################################# # function: BuildLinuxRawFirmwareType # puts together firmwares types like the TEW-632BRP ################################################################# BuildLinuxRawFirmwareType() { OUTPUT_PATH=$1 PARTS_PATH=$2 OUTPUT_FIRMWARE_FILENAME="output-firmware.bin" echo " Building firmware from directory $2 ..." if [ ! -e "$PARTS_PATH/rootfs/" ]; then echo " ERROR: rootfs must exist" exit 1 fi mkdir -p "$OUTPUT_PATH" rm -f "$PARTS_PATH/image_parts/squashfs-3-lzma.img" "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" "$PARTS_PATH/image_parts/rootfs.img" "$PARTS_PATH/image_parts/*.new" if [ -f "$PARTS_PATH/.squashfs3_lzma_fs" ]; then # make squashfs image if marker present echo " Building squashfs-lzma file system (big endian) ..." if [ -f "$2/.linux_raw_type3" ]; then echo " !!! WARNING: This raw embedded linux image type is UNTESTED - added Nov 6 2010" echo " !!! DO NOT FLASH UNLESS YOU ARE PREPARED TO RECOVER FROM A BRICKED ROUTER" echo " !!! YOU HAVE BEEN WARNED AND ASSUME LIABILITY FOR DAMAGES IF YOU DO FLASH IT" ./src/squashfs-3.0/mksquashfs-lzma "$PARTS_PATH/rootfs/" "$PARTS_PATH/image_parts/squashfs-3-lzma.img" -all-root -be -noappend -b 65536 2>/dev/null >> build.log else ./src/squashfs-3.0/mksquashfs-lzma "$PARTS_PATH/rootfs/" "$PARTS_PATH/image_parts/squashfs-3-lzma.img" -all-root -be -noappend 2>/dev/null >> build.log fi ln -s "squashfs-3-lzma.img" "$PARTS_PATH/image_parts/rootfs.img" filesize=$(du -b "$PARTS_PATH/image_parts/squashfs-3-lzma.img" | cut -f 1) else # make jffs2 image if marker not present echo " Building JFFS2 file system (big endian) ..." ./src/jffs2/mkfs.jffs2 -r "$PARTS_PATH/rootfs/" -o "$PARTS_PATH/image_parts/jffs2.img" --big-endian --squash # 2>/dev/null >> build.log ln -s "jffs2.img" "$PARTS_PATH/image_parts/rootfs.img" filesize=$(du -b "$PARTS_PATH/image_parts/jffs2.img" | cut -f 1) fi # build firmware image cp "$PARTS_PATH/image_parts/vmlinuz" "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" if [ -f "$2/.linux_raw_type3" ]; then echo " Building RAW IMAGE TYPE 3" cat "$PARTS_PATH/image_parts/rootfs.img" >> "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" else dd "if=$PARTS_PATH/image_parts/rootfs.img" "of=$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" bs=1K seek=1024 2>/dev/null >> build.log fi if [ -f "$PARTS_PATH/image_parts/hwid.txt" ]; then # user report: prepend four NULL bytes to the platform ID, causes image to be accepted on # either TEW-632BRP A1.0 or A1.1 by effectively nullifying the platform ID # "\000\000\000\000" >> "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" # now write platform ID cat "$PARTS_PATH/image_parts/hwid.txt" >> "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" else echo " ERROR: hwid.txt not found. This image needs a TARGET." exit 1 fi filesize=$(du -b "$OUTPUT_PATH/$OUTPUT_FIRMWARE_FILENAME" | cut -f 1) if [ $filesize -ge 3866649 ]; then echo " WARNING: firmware image may be too large for routers with 4MB ROM ..." fi } ################################################################# # InvokeTRX ( OutputDir, WorkingDir, filesystem image filename ) ################################################################# InvokeTRX () { echo " Building base firmware image (generic) ..." SEGMENT_1="$2/image_parts/segment1" if [ -f "$2/image_parts/segment2" ]; then SEGMENT_2="$2/image_parts/segment2" else SEGMENT_2="" fi # I switched to asustrx due to bug in trx with big endian OS X. # it works just like trx if you don't supply a version number (skips addver appendage) "src/asustrx" -o "$1/$FIRMWARE_BASE_NAME.trx" \ $SEGMENT_1 $SEGMENT_2 \ "$2/image_parts/$3" \ >> build.log 2>&1 echo " Building base firmware image (asus) ..." "src/asustrx" -p WL500gx -v 1.9.2.7 -o "$1/$FIRMWARE_BASE_NAME-asus.trx" \ $SEGMENT_1 $SEGMENT_2 \ "$2/image_parts/$3" \ >> build.log 2>&1 } ################################################################# # CreateTargetImages ( OutputDir, WorkingDir ) # # addpattern (HDR0) images. Maybe other model specific stuff # later. ################################################################# CreateTargetImages () { echo " Making $1/$FIRMWARE_BASE_NAME-wrtsl54gs.bin" if [ ! -f "$1/$FIRMWARE_BASE_NAME.trx" ]; then echo " ERROR: Sanity check failed." exit 1 fi "src/addpattern" -4 -p W54U -v v4.20.6 -i "$1/$FIRMWARE_BASE_NAME.trx" \ -o "$1/$FIRMWARE_BASE_NAME-wrtsl54gs.bin" -g >> build.log 2>&1 echo " Making $1/$FIRMWARE_BASE_NAME-wrt54g.bin" "src/addpattern" -4 -p W54G -v v4.20.6 -i "$1/$FIRMWARE_BASE_NAME.trx" \ -o "$1/$FIRMWARE_BASE_NAME-wrt54g.bin" -g >> build.log 2>&1 echo " Making $1/$FIRMWARE_BASE_NAME-wrt54gs.bin" "src/addpattern" -4 -p W54S -v v4.70.6 -i "$1/$FIRMWARE_BASE_NAME.trx" \ -o "$1/$FIRMWARE_BASE_NAME-wrt54gs.bin" -g >> build.log 2>&1 echo " Making $1/$FIRMWARE_BASE_NAME-wrt54gsv4.bin" "src/addpattern" -4 -p W54s -v v1.05.0 -i "$1/$FIRMWARE_BASE_NAME.trx" \ -o "$1/$FIRMWARE_BASE_NAME-wrt54gsv4.bin" -g >> build.log 2>&1 echo " Making $1/$FIRMWARE_BASE_NAME-generic.bin" ln -s "$FIRMWARE_BASE_NAME.trx" "$1/$FIRMWARE_BASE_NAME-generic.bin" >> build.log 2>&1 } ################################################################# # Build_WRT_Images( OutputDir, WorkingDir ) ################################################################# Build_WRT_Images () { echo " Building squashfs-lzma filesystem ..." if [ -e "$2/image_parts/squashfs-lzma-image-3_0" ]; then if [ -f "$2/image_parts/.sq_lzma_damn_small_variant_marker" ]; then echo " Utilizing lzma damn small variant ..." echo " WARNING: Support for these recently added, not fully tested... be careful." echo " Please report to jeremy.collake@gmail.com success or failure." echo " This may take a while ..." "src/squashfs-3.0-lzma-damn-small-variant/mksquashfs-lzma" "$2/rootfs/" "$2/image_parts/squashfs-lzma-image-new" \ -noappend -root-owned -le >> build.log else echo " Utilizing lzma standard variant ..." "src/squashfs-3.0/mksquashfs-lzma" "$2/rootfs/" "$2/image_parts/squashfs-lzma-image-new" \ -noappend -root-owned -le -magic "$2/image_parts/squashfs_magic" >> build.log fi # -magic to fix brainslayer changing squashfs signature in 08/10/06+ firmware images if [ $? != 0 ]; then echo " ERROR - mksquashfs failed." exit 1 fi elif [ -f "$2/image_parts/squashfs-lzma-image-2_x" ]; then echo " Utilizing squashfs lzma 2.1-r2 ..." "src/squashfs-2.1-r2/mksquashfs-lzma" "$2/rootfs/" "$2/image_parts/squashfs-lzma-image-new" \ -noappend -le >> build.log else echo " ERROR - Working directory contains no sqfs filesystem?" exit 1 fi ################################################################# InvokeTRX "$1" "$2" "squashfs-lzma-image-new" CreateTargetImages "$1" "$2" } ################################################################# # MakeCramfs (output file, root dir) # # invokes mkcramfs # ################################################################# MakeCramfs () { echo " Building cramfs file system ..." ./src/cramfs-2.x/mkcramfs "$2" "$1" >> build.log 2>&1 if [ $? != 0 ]; then echo " ERROR: creating cramfs file system failed.". exit "$?" else echo " Successfully created cramfs image." fi } ################################################################# # Build_WL530G_Image (OutputDir, WorkingDir, fs image filename [only] ) # # Builds an ASUS WL530/520/550G image. # ################################################################# Build_WL530G_Image () { echo " Building wl-530/520/550g style image (static TRX offsets)." ./src/asustrx -p WL530g -v 1.9.4.6 -o "$1/$FIRMWARE_BASE_NAME-wl530g.trx" -b 32 "$2/image_parts/segment1" -b 655360 "$2/image_parts/$3" >> build.log 2>&1 } ################################################################# ################################################################# ################################################################# if [ $# = 2 ]; then PlatformIdentify ################################################################# TestFileSystemExit "$1" "$2" ################################################################# TestIsRoot ################################################################# if [ ! -f "./old-build.sh" ]; then echo " ERROR - You must run this script from the same directory as it is in!" exit 1 fi ################################################################# if [ ! -f .firmware_rebuild_number ] ; then FIRMWARE_REBUILD_NUMBER=1 echo ${FIRMWARE_REBUILD_NUMBER} > .firmware_rebuild_number else FIRMWARE_REBUILD_NUMBER=$( cat .firmware_rebuild_number ) (( FIRMWARE_REBUILD_NUMBER+=1 )) echo ${FIRMWARE_REBUILD_NUMBER} > .firmware_rebuild_number fi if [ ! -f .firmware_base_name ] ; then FIRMWARE_BASE_NAME=custom_image echo $FIRMWARE_BASE_NAME > .firmware_base_name else FIRMWARE_BASE_NAME="$( cat .firmware_base_name )" fi FIRMWARE_BASE_NAME=$( printf "%s_%05d" ${FIRMWARE_BASE_NAME} ${FIRMWARE_REBUILD_NUMBER} ) echo "Rebuilt: ${FIRMWARE_BASE_NAME} With: Firmware Mod Kit (build) v$VERSION, (c)2010 Jeremy Collake" > "$2/rootfs/etc/rebuild_info" ################################################################# # remove deprecated stuff if [ -f "./src/mksquashfs.c" ] || [ -f "mksquashfs.c" ]; then DeprecateOldVersion fi ################################################################# # Invoke BuildTools, which tries to build everything and then # sets up appropriate symlinks. # BuildTools "build.log" ################################################################# echo " Preparing output directory $1 ..." mkdir -p $1 >> build.log 2>&1 rm "$1/$FIRMWARE_BASE_NAME*.*" "$1" >> build.log 2>&1 if [ -f "$2/.linux_raw_type" ]; then echo " Detected linux raw type firmware." BuildLinuxRawFirmwareType "$1" "$2" elif [ -f "$2/.linux_raw_type3" ]; then echo " Detected linux raw type firmware." BuildLinuxRawFirmwareType "$1" "$2" elif [ -f "$2/image_parts/.trx-sqfs" ]; then echo " Detected WRT squashfs-lzma style." Build_WRT_Images "$1" "$2" elif [ -f "$2/image_parts/cramfs-image-x_x" ]; then echo " Detected cramfs file system." TestIsRoot # remove old filename of new image.. rm -f "$2/image_parts/cramfs-image-1.1" MakeCramfs "$2/image_parts/cramfs-image-new" "$2/rootfs" # todo: rewrite this terrible test grep "530g" "$2/image_parts/cramfs-image-x_x" >> build.log 2>&1 if [ $? = "0" ]; then IS_530G_STYLE=1 fi grep "550g" "$2/image_parts/cramfs-image-x_x" >> build.log 2>&1 if [ $? = "0" ]; then IS_530G_STYLE=1 fi grep "520g" "$2/image_parts/cramfs-image-x_x" >> build.log 2>&1 if [ $? = "0" ]; then IS_530G_STYLE=1 fi if [ "$IS_530G_STYLE" = "1" ]; then Build_WL530G_Image "$1" "$2" "cramfs-image-new" else echo " No specific firmware type known, so am making standard images." InvokeTRX "$1" "$2" "cramfs-image-new" CreateTargetImages "$1" "$2" fi else echo " ERROR: Unknown or unsupported firmware image." exit 1 fi echo " Firmware images built." ls -l "$1" md5sum -b "$1"/${FIRMWARE_BASE_NAME}* > "$1"/${FIRMWARE_BASE_NAME}.md5sums echo " All done!" else ################################################################# echo " Incorrect usage." echo " USAGE: $0 OUTPUT_DIR WORKING_DIR" exit 1 fi exit 0 ================================================ FILE: old-extract.sh ================================================ #!/bin/sh # # $Id: extract_firmware.sh 336 2012-08-04 00:12:14Z jeremy.collake@gmail.com $ # . "./shared.inc" ### 20110225-MCT The VERSION is set in the shared.inc file from a single external source now. VERSION="${SHARED_VERSION}" # # Title: extract_firmware.sh # Author: Jeremy Collake # Site: http://code.google.com/p/firmware-mod-kit/ # # USAGE: old-extract.sh FIRMWARE_IMAGE.BIN WORKING_DIRECTORY/ # # This scripts extacts the firmware image to [WORKING_DIRECTORY], # with the following subdirectories: # # image_parts/ <- firmware seperated # rootfs/ <- extracted filesystem # # Example: # # ./old-extract.sh dd-wrt.v23_generic.bin std_generic # # EXIT_ON_FS_PROBLEM="0" echo echo " Firmware Mod Kit (extract) v$VERSION, (c)2010-2012 Jeremy Collake, - Newer NG edition by Craig Heffner" ################################################################# # # function: ExtractLinuxRawFirmwareType () # # Extracts essentially 'raw' firmware images with kernel, filesystem, and hardware id # Example is the TrendNET TEW-632BRP router. # ExtractLinuxRawFirmwareType () { # $1 = input firmware PARTS_PATH=$2 echo " Extracting $1 to $2 ..." mkdir -p "$PARTS_PATH/image_parts" if [ $? = 0 ]; then dd "if=$1" "of=$PARTS_PATH/image_parts/vmlinuz" bs=1K count=1024 2>/dev/null >> extract.log dd "if=$1" "of=$PARTS_PATH/image_parts/squashfs-3-lzma.img" bs=1K skip=1024 2>/dev/null >> extract.log SYSNAME=`uname` if [ `expr "$SYSNAME" : "Darwin"` = 6 ]; then filesize=$(ls -la $1 | awk '{print $5}') else filesize=$(du --apparent-size --block-size=1 $1 | cut -f 1) fi filesize=$((filesize - 24)) dd "if=$1" "of=$PARTS_PATH/image_parts/hwid.txt" bs=1 skip=$filesize 2>/dev/null >> extract.log "./src/squashfs-3.0/unsquashfs-lzma" -dest "$PARTS_PATH/rootfs" \ "$PARTS_PATH/image_parts/squashfs-3-lzma.img" 2>/dev/null >> extract.log if [ -e "$PARTS_PATH/rootfs/" ]; then # write a marker to indicate the firmware image type and filesystem type touch "$PARTS_PATH/.linux_raw_type" touch "$PARTS_PATH/.squashfs3_lzma_fs" fi else echo " ERROR: Creating output directory.." fi } ################################################################# # # Main script entry # ################################################################# if [ $# = 2 ]; then PlatformIdentify ################################################################# TestFileSystemExit $1 $2 ################################################################# TestIsRoot ################################################################# if [ -f "$1" ]; then if [ ! -f "./old-extract.sh" ]; then echo " ERROR - You must run this script from the same directory as it is in!" exit 1 fi ################################################################# # remove deprecated stuff if [ -f "./src/mksquashfs.c" ] || [ -f "mksquashfs.c" ]; then DeprecateOldVersion fi ################################################################# # Invoke BuildTools, which tries to build everything and then # sets up appropriate symlinks. # BuildTools "extract.log" ################################################################# echo " Preparing working directory ..." echo " Removing any previous files ..." rm -rf "$2/rootfs" >> extract.log 2>&1 rm -rf "$2/image_parts" >> extract.log 2>&1 rm -rf "$2/installed_packages" >> extract.log 2>&1 echo " Creating directories ..." mkdir -p "$2/image_parts" >> extract.log 2>&1 mkdir -p "$2/installed_packages" >> extract.log 2>&1 echo " Extracting firmware" "src/untrx" "$1" "$2/image_parts" >> extract.log 2>&1 if [ $? != 0 ]; then echo "! untrx failed, trying splitter3"; "src/splitter3" "$1" "$2/image_parts" >> extract.log 2>&1 if [ $? != 0 ]; then echo " Not recognized by splitter3"; # exit 1 else touch "$2/.linux_raw_type3" touch "$2/.squashfs3_lzma_fs" fi fi # if unknown version, then we'll just try to use the latest UnSquashFS we have if [ -f "$2/image_parts/squashfs-lzma-image-x_x" ]; then ln -s "squashfs-lzma-image-x_x" "$2/image_parts/squashfs-lzma-image-3_0" fi # if squashfs 3.1 or 3.2, symlink it to 3.0 image, since they are compatible if [ -f "$2/image_parts/squashfs-lzma-image-3_1" ]; then ln -s "squashfs-lzma-image-3_1" "$2/image_parts/squashfs-lzma-image-3_0" fi if [ -f "$2/image_parts/squashfs-lzma-image-3_2" ]; then ln -s "squashfs-lzma-image-3_2" "$2/image_parts/squashfs-lzma-image-3_0" fi if [ -f "$2/image_parts/squashfs-lzma-image-3_x" ]; then ln -s "squashfs-lzma-image-3_x" "$2/image_parts/squashfs-lzma-image-3_0" fi if [ -f "$2/image_parts/squashfs-lzma-image-2_0" ]; then ln -s "squashfs-lzma-image-2_0" "$2/image_parts/squashfs-lzma-image-2_x" fi if [ -f "$2/image_parts/squashfs-lzma-image-2_1" ]; then ln -s "squashfs-lzma-image-2_1" "$2/image_parts/squashfs-lzma-image-2_x" fi # now unsquashfs, if filesystem is squashfs if [ -f "$2/image_parts/squashfs-lzma-image-3_0" ]; then echo " Attempting squashfs 3.0 lzma ..." "src/squashfs-3.0/unsquashfs-lzma" \ -dest "$2/rootfs" "$2/image_parts/squashfs-lzma-image-3_0" 2>/dev/null >> extract.log if [ ! -e "$2/rootfs" ]; then echo " Trying 'damn small' variant - used by DD-WRT v24 ..." "src/squashfs-3.0-lzma-damn-small-variant/unsquashfs-lzma" \ -dest "$2/rootfs" "$2/image_parts/squashfs-lzma-image-3_0" 2>/dev/null >> extract.log if [ -e "$2/rootfs" ]; then # if it worked, then write a tag so we know which squashfs variant to build the fs with touch "$2/image_parts/.sq_lzma_damn_small_variant_marker" touch "$2/image_parts/.trx-sqfs" fi else touch "$2/image_parts/.trx-sqfs" fi elif [ -f "$2/image_parts/squashfs-lzma-image-2_x" ]; then "src/squashfs-2.1-r2/unsquashfs-lzma" \ -dest "$2/rootfs" "$2/image_parts/squashfs-lzma-image-2_x" 2>/dev/null >>extract.log if [ -e "$2/rootfs" ]; then touch "$2/image_parts/.trx-sqfs" else echo " ERROR: extracting filesystem." fi elif [ -f "$2/image_parts/cramfs-image-x_x" ]; then TestIsRoot "src/cramfs-2.x/cramfsck" \ -v -x "$2/rootfs" "$2/image_parts/cramfs-image-x_x" >> extract.log 2>&1 else echo " Attempting raw linux style firmware package (i.e. TEW-632BRP) ..." ExtractLinuxRawFirmwareType "$1" "$2" fi if [ -e "$2/rootfs" ]; then echo " Firmware appears extracted correctly!" echo " Now make changes and run build_firmware.sh." else echo " Error: filesystem not extracted properly." echo " firmware image format not compatible?" exit 1 fi else echo " $1 does not exist.. give me something to work with man!" fi else echo " Incorrect usage." echo " USAGE: $0 FIRMWARE_IMAGE.BIN WORKING_DIR" exit 1 fi exit 0 ================================================ FILE: shared-ng.inc ================================================ VERSION=$(cat firmware_mod_kit_version.txt) IMAGE_PARTS="$DIR/image_parts" LOGS="$DIR/logs" CONFLOG="$LOGS/config.log" BINLOG="$LOGS/binwalk.log" ROOTFS="$DIR/rootfs" FSIMG="$IMAGE_PARTS/rootfs.img" HEADER_IMAGE="$IMAGE_PARTS/header.img" FOOTER_IMAGE="$IMAGE_PARTS/footer.img" FWOUT="$DIR/new-firmware.bin" BINWALK="./src/binwalk-1.0/src/bin/binwalk-script -v -m ./src/binwalk-1.0/src/binwalk/magic/binwalk" ================================================ FILE: shared.inc ================================================ #!/bin/sh SHARED_VERSION="$( cat firmware_mod_kit_version.txt )" # # Title: shared.inc # Author: Jeremy Collake # # Shared functions # # # ################################################################# WarningPrompt () { read -p " [ Press any key to contrinue, or abort now with break signal (CTRL-C) ]" } ################################################################# PlatformIdentify () { SYSNAME=`uname` if [ "$SYSNAME" = "Linux" ]; then echo " LINUX system detected. Compatibility ok." elif [ `expr "$SYSNAME" : "Darwin"` = 6 ]; then echo " OS X system detected. **BETA TESTING**" echo " This platform is not well tested." WarningPrompt elif [ `expr "$SYSNAME" : "CYGWIN"` = 6 ]; then echo " CYGWIN system detected. **BETA TESTING** Built images may have problems." echo " This platform is not well tested." WarningPrompt else echo " Unknown system detected. Compatibility state is unknown." WarningPrompt fi } ################################################################# TestFileSystemExit () { INPUT_FILE=$1 WORKING_DIR=$2 echo " Testing file system of $WORKING_DIR ..." mkdir -p "$WORKING_DIR" >> /dev/null 2>&1 rm "$WORKING_DIR/test12345612.tmp" >> /dev/null 2>&1 echo test > "$WORKING_DIR/test12345612.tmp" if [ -e "$WORKING_DIR/teST12345612.tmp" ]; then echo " WARNING: File system $WORKING_DIR is not case sensitive." echo " For some firmwares this can cause troubles in the" echo " built images that result in runtime errata or" echo " even refuse to boot." if [ $EXIT_ON_FS_PROBLEM = "1" ]; then rm "$WORKING_DIR/test12345612.tmp" >> /dev/null 2>&1 exit 2 else WarningPrompt fi fi if [ ! -e "$WORKING_DIR/test12345612.tmp" ]; then echo " ERROR: File system $WORKING_DIR is not writable." rm "$WORKING_DIR/test12345612.tmp" >> /dev/null 2>&1 exit 3 fi rm "$WORKING_DIR/test12345612.tmp" >> /dev/null 2>&1 } ################################################################# # LinkToolsBinraries (srcfolder, destfolder) #LinkToolsBinaries () #{ ## deprecated v0.44 # ln -s -f $1/asustrx $2/asustrx # ln -s -f $1/untrx $2/untrx # ln -s -f $1/mksquashfs $2/mksquashfs # ln -s -f $1/mksquashfs-lzma $2/mksquashfs-lzma # ln -s -f $1/unsquashfs $2/unsquashfs # ln -s -f $1/unsquashfs-lzma $2/unsquashfs-lzma # ln -s -f $1/addpattern $2/addpattern #} ################################################################# CleanCWD () { make clean >> cleanup.log 2>&1 rm -f src/*.log >> cleanup.log 2>&1 rm -f *.log >> cleanup.log 2>&1 rm -f *.o >> cleanup.log 2>&1 rm -f asustrx >> cleanup.log 2>&1 rm -f trx >> cleanup.log 2>&1 rm -f untrx >> cleanup.log 2>&1 rm -f addpattern >> cleanup.log 2>&1 rm -f mksquashfs >> cleanup.log 2>&1 rm -f mksquashfs-lzma >> cleanup.log 2>&1 rm -f unsquashfs >> cleanup.log 2>&1 rm -f unsquashfs-lzma >> cleanup.log 2>&1 # cygwin rm -f asustrx.exe >> cleanup.log 2>&1 rm -f trx.exe >> cleanup.log 2>&1 rm -f untrx.edxe >> cleanup.log 2>&1 rm -f addpattern.exe >> cleanup.log 2>&1 rm -f mksquashfs.exe >> cleanup.log 2>&1 rm -f mksquashfs-lzma.exe >> cleanup.log 2>&1 rm -f unsquashfs.exe >> cleanup.log 2>&1 rm -f unsquashfs-lzma.exe >> cleanup.log 2>&1 # old name for untrx, deprecated rm -f extfirmware* >> cleanup.log 2>&1 # trx replaced with asustrx rm -f trx.c >> cleanup.log 2>&1 } Cleanup () { CleanCWD cd src CleanCWD cd .. } ################################################################# # BuildTools ( LOG_FILE ) # # BuildTools () { local LOG_FILE="$1" ################################################################# echo " Building tools ..." #make -C src > $LOG_FILE 2>&1 cd src ./configure && make > $LOG_FILE 2>&1 cd - if [ $? = 0 ]; then echo " Build seems successful." else echo " ERROR - Build did not succeed. Check log file, you are probably" echo " missing one or more necessary pre-requisites. See docs for" echo " a list of pre-requsites." if [ -e "src/untrx" ]; then echo " CONTINUING anyway, attempting to use pre-built binaries (x32 linux)" else exit 1 fi fi ################################################################# local UNAME2=`uname` if [ `expr "$UNAME2" : "CYGWIN"` = 6 ]; then ln -s -f "src/asustrx.exe" "src/asustrx" >> $LOG_FILE 2>&1 ln -s -f "src/untrx.exe" "src/untrx" >> $LOG_FILE 2>&1 ln -s -f "src/addpattern.exe" "src/addpattern" >> $LOG_FILE 2>&1 ln -s -f "src/squashfs-3.0/mksquashfs-lzma.exe" "src/squashfs-3.0/mksquashfs-lzma" >> $LOG_FILE 2>&1 ln -s -f "src/squashfs-3.0/unsquashfs-lzma.exe" "src/squashfs-3.0/unsquashfs-lzma" >> $LOG_FILE 2>&1 ln -s -f "src/squashfs-3.0/mksquashfs.exe" "src/squashfs-3.0/mksquashfs" >> $LOG_FILE 2>&1 ln -s -f "src/squashfs-3.0/unsquashfs.exe" "src/squashfs-3.0/unsquashfs" >> $LOG_FILE 2>&1 fi ################################################################# # cygwin: this can not be called before above block (no *. bins exist) #LinkToolsBinaries "src" "." } ################################################################# # DeprecateOldVersion () # # This is to automatically cleanup stuff that's been moved or removed # since older versions. Aren't I nice? # DeprecateOldVersion () { echo " Detected leftover stuff from an old version, cleaning" mkdir "src_backup" >> upgrade.log 2>&1 mv "*.c" "src_old_backup" >> upgrade.log 2>&1 mv "*.h" "src_old_backup" >> upgrade.log 2>&1 mv "lzma" "src_old_backup" >> upgrade.log 2>&1 mv "Makefile" "src_old_backup" >> upgrade.log 2>&1 mv src/cramfs-1.1 src_backup/ >> upgrade.log 2>&1 # remove symbolic links from v0.43 and below rm "mksquashfs" >> upgrade.log 2>&1 rm "unsquashfs" >> upgrade.log 2>&1 rm "mksquashfs-lzma" >> upgrade.log 2>&1 rm "unsquashfs-lzma" >> upgrade.log 2>&1 rm "untrx" >> upgrade.log 2>&1 rm "asustrx" >> upgrade.log 2>&1 rm "addpattern" >> upgrade.log 2>&1 # remove old sources mv src/untrx.c src_old_backup >> upgrade.log 2>&1 mv src/mksquashfs* src_old_backup >> upgrade.log 2>&1 mv src/unsquashfs* src_old_backup >> upgrade.log 2>&1 mv src/read_* src_old_backup >> upgrade.log 2>&1 mv src/sort* src_old_backup >> upgrade.log 2>&1 mv src/global.h src_old_backup >> upgrade.log 2>&1 Cleanup } TestIsRootAndExitIfNot() { if [ $(id -u) != "0" ]; then echo " ERROR: You must be 'root' when extracting and building some images." echo " This is because some images need to create devices in your fs." echo " For DD-WRT, do NOT extract or build as root, use standard user." exit 1 fi } TestIsRoot() { if [ $(id -u) != "0" ]; then echo " WARNING: You must be 'root' when extracting and building some images." echo " This is because some images need to create devices in your fs." echo " For DD-WRT, do NOT extract or build as root, use standard user." fi } ================================================ FILE: src/Makefile.in ================================================ CC := gcc CXX := g++ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 all: asustrx addpattern untrx motorola-bin splitter3 bffutils make -C ./uncramfs/ make -C ./uncramfs-lzma/ make -C ./cramfs-2.x/ make -C ./cramfsswap/ make -C ./squashfs-2.1-r2/ make -C ./squashfs-3.0/ make -C ./squashfs-3.0-lzma-damn-small-variant/ make -C ./wrt_vx_imgtool/ make -C ./others/ make -C ./crcalc/ make -C ./webcomp-tools/ make -C ./firmware-tools/ addpattern: addpattern.o $(CC) addpattern.o -o $@ untrx: untrx.o $(CXX) untrx.o -o $@ splitter3: splitter3.o $(CXX) splitter3.o -o $@ asustrx: asustrx.o $(CC) asustrx.o -o $@ motorola-bin: motorola-bin.o $(CC) motorola-bin.o -o $@ bffutils: make -C ./bff/ clean: rm -f *.o rm -f motorola-bin rm -f untrx rm -f asustrx rm -f addpattern rm -f splitter3 rm -f binwalk make -C ./squashfs-2.1-r2/ clean make -C ./squashfs-3.0 clean make -C ./squashfs-3.0-lzma-damn-small-variant clean make -C ./cramfs-2.x clean make -C ./uncramfs clean make -C ./uncramfs-lzma clean make -C ./cramfsswap clean make -C ./wrt_vx_imgtool clean make -C ./others clean make -C ./crcalc clean make -C ./webcomp-tools clean make -C ./binwalk*/src/ cleanall make -C ./firmware-tools/ clean make -C ./bff/ clean cleanall: clean rm -rf Makefile config.* *.cache ================================================ FILE: src/addpattern.c ================================================ /* * Copyright (C) 2004 Manuel Novoa III * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* July 29, 2004 * * This is a hacked replacement for the 'addpattern' utility used to * create wrt54g .bin firmware files. It isn't pretty, but it does * the job for me. * * Extensions: * -v allows setting the version string on the command line. * -{0|1} sets the (currently ignored) hw_ver flag in the header * to 0 or 1 respectively. */ /* January 12, 2005 * * Modified by rodent at rodent dot za dot net * Support added for the new WRT54G v2.2 and WRT54GS v1.1 "flags" * Without the flags set to 0x7, the above units will refuse to flash. * * Extensions: * -{0|1|2} sets {0|1} sets hw_ver flag to 0/1. {2} sets hw_ver to 1 * and adds the new hardware "flags" for the v2.2/v1.1 units */ #include #include #include #include #include #include /**********************************************************************/ #define CODE_ID "U2ND" /* from code_pattern.h */ #define CODE_PATTERN "W54S" /* from code_pattern.h */ #define CYBERTAN_VERSION "v3.37.2" /* from cyutils.h */ /* WRT54G v2.2 and WRT54GS v1.1 "flags" (from 3.37.32 firmware cyutils.h) */ #define SUPPORT_4712_CHIP 0x0001 #define SUPPORT_INTEL_FLASH 0x0002 #define SUPPORT_5325E_SWITCH 0x0004 struct code_header { /* from cyutils.h */ char magic[4]; char res1[4]; /* for extra magic */ char fwdate[3]; char fwvern[3]; char id[4]; /* U2ND */ char hw_ver; /* 0: for 4702, 1: for 4712 -- new in 2.04.3 */ unsigned short flags; /* SUPPORT_ flags new for 3.37.2 (WRT54G v2.2 and WRT54GS v1.1) */ unsigned char res2[10]; } ; /**********************************************************************/ void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Usage: addpattern [-i trxfile] [-o binfile] [-p pattern] [-g] [-v v#.#.#] [-{0|1|2|4}]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { char buf[1024]; /* keep this at 1k or adjust garbage calc below */ struct code_header *hdr; FILE *in = stdin; FILE *out = stdout; char *ifn = NULL; char *ofn = NULL; char *pattern = CODE_PATTERN; char *version = CYBERTAN_VERSION; int gflag = 0; int c; int v0, v1, v2; size_t off, n; time_t t; struct tm *ptm; fprintf(stderr, "mjn3's addpattern replacement - v0.81\n"); hdr = (struct code_header *) buf; memset(hdr, 0, sizeof(struct code_header)); while ((c = getopt(argc, argv, "i:o:p:gv:0124")) != -1) { switch (c) { case 'i': ifn = optarg; break; case 'o': ofn = optarg; break; case 'p': pattern = optarg; break; case 'g': gflag = 1; break; case 'v': /* extension to allow setting version */ version = optarg; break; case '0': hdr->hw_ver = 0; break; case '1': hdr->hw_ver = 1; break; case '2': /* new 54G v2.2 and 54GS v1.1 flags */ hdr->hw_ver = 1; hdr->flags |= SUPPORT_4712_CHIP; hdr->flags |= SUPPORT_INTEL_FLASH; hdr->flags |= SUPPORT_5325E_SWITCH; break; case '4': /* V4 firmware sets the flags to 0x1f */ hdr->hw_ver = 1; hdr->flags = 0x1f; break; default: usage(); } } if (optind != argc) { fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); usage(); } if (strlen(pattern) != 4) { fprintf(stderr, "illegal pattern \"%s\": length != 4\n", pattern); usage(); } if (ifn && !(in = fopen(ifn, "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", ifn); usage(); } if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } if (time(&t) == (time_t)(-1)) { fprintf(stderr, "time call failed\n"); return EXIT_FAILURE; } ptm = localtime(&t); if (3 != sscanf(version, "v%d.%d.%d", &v0, &v1, &v2)) { fprintf(stderr, "bad version string \"%s\"\n", version); return EXIT_FAILURE; } memcpy(&hdr->magic, pattern, 4); hdr->fwdate[0] = ptm->tm_year % 100; hdr->fwdate[1] = ptm->tm_mon + 1; hdr->fwdate[2] = ptm->tm_mday; hdr->fwvern[0] = v0; hdr->fwvern[1] = v1; hdr->fwvern[2] = v2; memcpy(&hdr->id, CODE_ID, strlen(CODE_ID)); off = sizeof(struct code_header); fprintf(stderr, "writing firmware v%d.%d.%d on %d/%d/%d (y/m/d)\n", v0, v1, v2, hdr->fwdate[0], hdr->fwdate[1], hdr->fwdate[2]); while ((n = fread(buf + off, 1, sizeof(buf)-off, in) + off) > 0) { off = 0; if (n < sizeof(buf)) { if (ferror(in)) { FREAD_ERROR: fprintf(stderr, "fread error\n"); return EXIT_FAILURE; } if (gflag) { gflag = sizeof(buf) - n; memset(buf + n, 0xff, gflag); fprintf(stderr, "adding %d bytes of garbage\n", gflag); n = sizeof(buf); } } if (!fwrite(buf, n, 1, out)) { FWRITE_ERROR: fprintf(stderr, "fwrite error\n"); return EXIT_FAILURE; } } if (ferror(in)) { goto FREAD_ERROR; } if (fflush(out)) { goto FWRITE_ERROR; } fclose(in); fclose(out); return EXIT_SUCCESS; } ================================================ FILE: src/asustrx.c ================================================ /* * Copyright (C) 2004 Manuel Novoa III * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* July 29, 2004 * * This is a hacked replacement for the 'trx' utility used to create * wrt54g .trx firmware files. It isn't pretty, but it does the job * for me. * * As an extension, you can specify a larger maximum length for the * .trx file using '-m'. It will be rounded up to be a multiple of 4K. * NOTE: This space will be malloc()'d. * * August 16, 2004 * * Sigh... Make it endian-neutral. * * TODO: Support '-b' option to specify offsets for each file. */ /* March 04, 2005 * * Copyright(c) 2005 Konstantin A. Klubnichkin and Oleg I. Vdovikin * * Added ASUS addver functionality, which is binary only * * addver is no longer needed, use utility like this * * asustrx -p WL500g -v 1.9.2.7 -o image.trx file [ file [ file ] ] */ /* September 22, 2006 * * Copyright(c) 2006 Jeremy Collake * * Added -b switch to force a segment start offset, padding up * to that point. This switch should immediately preceed filenames. * * Example of ASUS calls to their trx (addver called sperately): * * trx -o WL530g_$(KVER).$(FVER)_$(LANGUAGE).bin -b 32 zImage -b 655360 target.cramfs * * * Also several other misc. changes where I saw appropriate. * */ #include #include #include #include #include #include #include #include #include #include // always flip, regardless of endianness of machine u_int32_t flip_endian(u_int32_t nValue) { // my crappy endian switch u_int32_t nR; u_int32_t nByte1=(nValue&0xff000000)>>24; u_int32_t nByte2=(nValue&0x00ff0000)>>16; u_int32_t nByte3=(nValue&0x0000ff00)>>8; u_int32_t nByte4=nValue&0x0ff; nR=nByte4<<24; nR|=(nByte3<<16); nR|=(nByte2<<8); nR|=nByte1; return nR; } #if __BYTE_ORDER == __BIG_ENDIAN #define STORE32_LE(X) bswap_32(X) #define READ32_LE(X) bswap_32(X) #elif __BYTE_ORDER == __LITTLE_ENDIAN #define STORE32_LE(X) (X) #define READ32_LE(X) (X) #else #error unkown endianness! #endif /*jc end */ uint32_t crc32buf(char *buf, size_t len); /**********************************************************************/ /* from trxhdr.h */ #define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_VERSION 1 #define TRX_MAX_LEN 0x9A0000 /* jc: change from 0x3A0000 */ #define TRX_NO_HEADER 1 /* Do not write TRX header */ struct trx_header { uint32_t magic; /* "HDR0" */ uint32_t len; /* Length of file including header */ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[3]; /* Offsets of partitions from start of header */ }; /**********************************************************************/ void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Use: trx [-p prodid] [-v ver] [-o ofile] [-m maxlen] [-b offs] file [-b offs] [file [file]]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { FILE *out = stdout; FILE *in; char *ofn = NULL; char *buf; char *e; int c, i; size_t n; uint32_t cur_len; int boolSegmentSizesGiven=0; /* jc */ int nSegementCount=0; unsigned long maxlen = TRX_MAX_LEN; struct trx_header *p; struct trx_header trxtemp; memset(&trxtemp,0,sizeof(struct trx_header)); struct { uint8_t version[4]; /* Firmware version */ uint8_t prod_id[12]; /* Product Id */ uint8_t comp_hw[4][4]; /* Compatible hw list maj-min min/maj-min max */ uint8_t pad[32]; /* Padding */ } asus = { .prod_id = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* jc: initialize .prod_id */ .version = { 1, 9, 2, 7 }, /* version is set to 1.9.2.7 by default */ .comp_hw[0] = { 0, 2, 2, 99 } /* hardcoded hw compat list 0.02 - 2.99 */ }; fprintf(stderr, "mjn3's trx replacement - v0.90, modified to pack ASUS compatible trx\n"); while ((c = getopt(argc, argv, "b:o:m:p:v:")) != -1) { switch (c) { /* jc */ case 'b': boolSegmentSizesGiven=1; trxtemp.offsets[nSegementCount++]=STORE32_LE(strtoul(optarg, &e, 0)); if ((e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } break; /* jc end */ case 'o': ofn = optarg; break; case 'm': errno = 0; maxlen = strtoul(optarg, &e, 0); if (errno || (e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } #undef ROUND #define ROUND 0x1000 if (maxlen & (ROUND-1)) { maxlen += (ROUND - (maxlen & (ROUND-1))); } if (maxlen < ROUND) { fprintf(stderr, "maxlen too small (or wrapped)\n"); usage(); } break; case 'p': if ((n = strlen(optarg)) > sizeof(asus.prod_id)) { fprintf(stderr, "product id too long\n"); usage(); } memset(asus.prod_id, ' ', sizeof(asus.prod_id)); memcpy(asus.prod_id, optarg, n); break; case 'v': for (n = 0; n < sizeof(asus.version) / sizeof(asus.version[0]); n++) { if (n != 0 && optarg[0] == '.' && optarg[1]) optarg++; else if (n != 0) break; asus.version[n] = strtoul(optarg, &optarg, 10); } if (*optarg) { fprintf(stderr, "invalid version string\n"); usage(); } break; default: usage(); } } if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } if (optind == argc) { fprintf(stderr, "we require at least one arg\n"); usage(); } if (argc - optind > 3) { fprintf(stderr, "too many args: %d > 3\n", argc - optind); usage(); } if (maxlen > TRX_MAX_LEN) { fprintf(stderr, "WARNING: maxlen exceeds default maximum! Beware of overwriting nvram!\n"); } if (!(buf = malloc(maxlen))) { fprintf(stderr, "malloc failed\n"); return EXIT_FAILURE; } memset(buf,0,maxlen); /* jc */ p = (struct trx_header *) buf; memcpy(p,&trxtemp,sizeof(struct trx_header)); /* jc */ p->magic = STORE32_LE(TRX_MAGIC); cur_len = sizeof(struct trx_header); p->flag_version = STORE32_LE((TRX_VERSION << 16)); i = 0; while (optind < argc) { /* jc */ if(!READ32_LE(p->offsets[i])) { p->offsets[i] = STORE32_LE(cur_len); } else { if(cur_len>READ32_LE(p->offsets[i])) { fprintf(stderr, "offset too large\n"); return EXIT_FAILURE; } cur_len=READ32_LE(p->offsets[i]); } /* jc end */ if (!(in = fopen(argv[optind], "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", argv[optind]); usage(); } n = fread(buf + cur_len, 1, maxlen - cur_len, in); if (!feof(in)) { fprintf(stderr, "fread failure or file \"%s\" too large cur:%d max: %d\n", argv[optind], cur_len, maxlen); fclose(in); return EXIT_FAILURE; } fclose(in); ++optind; if (optind < argc) { #undef ROUND #define ROUND 4 if (n & (ROUND-1)) { memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1))); n += ROUND - (n & (ROUND-1)); } } cur_len += n; i++; } /* reserve space for asus footer */ if (asus.prod_id[0]) { cur_len += sizeof(asus); } #undef ROUND #define ROUND 0x1000 n = cur_len & (ROUND-1); if (n) { memset(buf + cur_len, 0, ROUND - n); cur_len += ROUND - n; } /* add asus footer */ if (asus.prod_id[0]) { memcpy(buf + cur_len - sizeof(asus), &asus, sizeof(asus)); } p->crc32 = crc32buf((char *) &p->flag_version, cur_len - offsetof(struct trx_header, flag_version)); p->crc32 = STORE32_LE(p->crc32); p->len = STORE32_LE(cur_len); if (!fwrite(buf, cur_len, 1, out) || fflush(out)) { fprintf(stderr, "fwrite failed\n"); return EXIT_FAILURE; } fclose(out); return EXIT_SUCCESS; } /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32buf(char *buf, size_t len) { uint32_t crc; crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc; } ================================================ FILE: src/bff/Makefile ================================================ all: gcc bff_huffman_decompress.c -o bff_huffman_decompress clean: rm -f bff_huffman_decompress distclean: clean ================================================ FILE: src/bff/bff_huffman_decompress.c ================================================ /*- * Copyright (c) 2009 Xin LI * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ // compile it using: gcc bff_huffman_decompress.c -o bff_huffman_decompress // use it as: ./bff_huffman_decompress sampleBff_file0 sampleBff_file0_parsed /* * pack(1) file format: * * The first byte is the header: * 00 - Level for the huffman tree (<=24) * * pack(1) will then store symbols (leaf) nodes count in each huffman * tree levels, each level would consume 1 byte (See [1]). * * After the symbol count table, there is the symbol table, storing * symbols represented by corresponding leaf node. EOB is not being * explicitly transmitted (not necessary anyway) in the symbol table. * * Compressed data goes after the symbol table. * * NOTES * * [1] If we count EOB into the symbols, that would mean that we will * have at most 256 symbols in the huffman tree. pack(1) rejects empty * file and files that just repeats one character, which means that we * will have at least 2 symbols. Therefore, pack(1) would reduce the * last level symbol count by 2 which makes it a number in * range [0..254], so all levels' symbol count would fit into 1 byte. */ #include #include #include #define PACK_HEADER_LENGTH 1 #define HTREE_MAXLEVEL 24 /* * unpack descriptor * * Represent the huffman tree in a similar way that pack(1) would * store in a packed file. We store all symbols in a linear table, * and store pointers to each level's first symbol. In addition to * that, maintain two counts for each level: inner nodes count and * leaf nodes count. */ typedef struct { int symbol_size; /* Size of the symbol table */ int treelevels; /* Levels for the huffman tree */ int *symbolsin; /* Table of leaf symbols count in each level */ int *inodesin; /* Table of internal nodes count in each level */ char *symbol; /* The symbol table */ char *symbol_eob; /* Pointer to the EOB symbol */ char **tree; /* Decoding huffman tree (pointers to first symbol of each tree level */ off_t uncompressed_size; /* Uncompressed size */ FILE *fpIn; /* Input stream */ FILE *fpOut; /* Output stream */ } unpack_descriptor_t; int maybe_err(char*fmt,...) { } int maybe_errx(char*fmt,...) { } /* * Release resource allocated to an unpack descriptor. * * Caller is responsible to make sure that all of these pointers are * initialized (in our case, they all point to valid memory block). * We don't zero out pointers here because nobody else would ever * reference the memory block without scrubbing them. */ static void unpack_descriptor_fini(unpack_descriptor_t *unpackd) { free(unpackd->symbolsin); free(unpackd->inodesin); free(unpackd->symbol); free(unpackd->tree); fclose(unpackd->fpIn); fclose(unpackd->fpOut); } /* * Recursively fill the internal node count table */ static void unpackd_fill_inodesin(const unpack_descriptor_t *unpackd, int level) { /* * The internal nodes would be 1/2 of total internal nodes and * leaf nodes in the next level. For the last level there * would be no internal node by definition. */ if (level < unpackd->treelevels) { unpackd_fill_inodesin(unpackd, level + 1); unpackd->inodesin[level] = (unpackd->inodesin[level + 1] + unpackd->symbolsin[level + 1]) / 2; } else unpackd->inodesin[level] = 0; } /* * Update counter for accepted bytes */ static void accepted_bytes(off_t *bytes_in, off_t newbytes) { if (bytes_in != NULL) (*bytes_in) += newbytes; } /* * Read file header and construct the tree. Also, prepare the buffered I/O * for decode routine. * * Return value is uncompressed size. */ static void unpack_parse_header(int in, int out, char *pre, size_t prelen, off_t *bytes_in, unpack_descriptor_t *unpackd) { unsigned char hdr[PACK_HEADER_LENGTH]; /* buffer for header */ ssize_t bytesread; /* Bytes read from the file */ int i, j, thisbyte; /* Prepend the header buffer if we already read some data */ if (prelen != 0) memcpy(hdr, pre, prelen); /* Read in and fill the rest bytes of header */ bytesread = read(in, hdr + prelen, PACK_HEADER_LENGTH - prelen); if (bytesread < 0) maybe_err("Error reading pack header"); accepted_bytes(bytes_in, PACK_HEADER_LENGTH); /* Reset uncompressed size */ unpackd->uncompressed_size = 0; /* Get the levels of the tree */ unpackd->treelevels = hdr[0]; if (unpackd->treelevels > HTREE_MAXLEVEL || unpackd->treelevels < 1) maybe_errx("Huffman tree has insane levels"); /* Let libc take care for buffering from now on */ if ((unpackd->fpIn = fdopen(in, "r")) == NULL) maybe_err("Can not fdopen() input stream"); if ((unpackd->fpOut = fdopen(out, "w")) == NULL) maybe_err("Can not fdopen() output stream"); /* Allocate for the tables of bounds and the tree itself */ unpackd->inodesin = calloc(unpackd->treelevels, sizeof(*(unpackd->inodesin))); unpackd->symbolsin = calloc(unpackd->treelevels, sizeof(*(unpackd->symbolsin))); unpackd->tree = calloc(unpackd->treelevels, (sizeof (*(unpackd->tree)))); if (unpackd->inodesin == NULL || unpackd->symbolsin == NULL || unpackd->tree == NULL) maybe_err("calloc"); /* We count from 0 so adjust to match array upper bound */ unpackd->treelevels--; /* Read the levels symbol count table and calculate total */ unpackd->symbol_size = 1; /* EOB */ for (i = 0; i <= unpackd->treelevels; i++) { if ((thisbyte = fgetc(unpackd->fpIn)) == EOF) maybe_err("File appears to be truncated"); unpackd->symbolsin[i] = (unsigned char)thisbyte; unpackd->symbol_size += unpackd->symbolsin[i]; } accepted_bytes(bytes_in, unpackd->treelevels); if (unpackd->symbol_size > 256) maybe_errx("Bad symbol table"); /* Allocate for the symbol table, point symbol_eob at the beginning */ unpackd->symbol_eob = unpackd->symbol = calloc(1, unpackd->symbol_size); if (unpackd->symbol == NULL) maybe_err("calloc"); /* * Read in the symbol table, which contain [2, 256] symbols. * In order to fit the count in one byte, pack(1) would offset * it by reducing 2 from the actual number from the last level. * * We adjust the last level's symbol count by 1 here, because * the EOB symbol is not being transmitted explicitly. Another * adjustment would be done later afterward. */ unpackd->symbolsin[unpackd->treelevels]++; for (i = 0; i <= unpackd->treelevels; i++) { unpackd->tree[i] = unpackd->symbol_eob; for (j = 0; j < unpackd->symbolsin[i]; j++) { if ((thisbyte = fgetc(unpackd->fpIn)) == EOF) maybe_errx("Symbol table truncated"); *unpackd->symbol_eob++ = (char)thisbyte; } accepted_bytes(bytes_in, unpackd->symbolsin[i]); } /* Now, take account for the EOB symbol as well */ unpackd->symbolsin[unpackd->treelevels]++; /* * The symbolsin table has been constructed now. * Calculate the internal nodes count table based on it. */ unpackd_fill_inodesin(unpackd, 0); } /* * Decode huffman stream, based on the huffman tree. */ static void unpack_decode(unpack_descriptor_t *unpackd, off_t *bytes_in) { int thislevel, thiscode, thisbyte, inlevelindex; int i; off_t bytes_out = 0; const char *thissymbol; /* The symbol pointer decoded from stream */ /* * Decode huffman. Fetch every bytes from the file, get it * into 'thiscode' bit-by-bit, then output the symbol we got * when one has been found. * * Assumption: sizeof(int) > ((max tree levels + 1) / 8). * bad things could happen if not. */ thislevel = 0; thiscode = thisbyte = 0; while ((thisbyte = fgetc(unpackd->fpIn)) != EOF) { accepted_bytes(bytes_in, 1); /* * Split one bit from thisbyte, from highest to lowest, * feed the bit into thiscode, until we got a symbol from * the tree. */ for (i = 7; i >= 0; i--) { thiscode = (thiscode << 1) | ((thisbyte >> i) & 1); /* Did we got a symbol? (referencing leaf node) */ if (thiscode >= unpackd->inodesin[thislevel]) { inlevelindex = thiscode - unpackd->inodesin[thislevel]; if (inlevelindex > unpackd->symbolsin[thislevel]) maybe_errx("File corrupt"); thissymbol = &(unpackd->tree[thislevel][inlevelindex]); if (thissymbol == unpackd->symbol_eob) goto finished; fputc((*thissymbol), unpackd->fpOut); bytes_out++; /* Prepare for next input */ thislevel = 0; thiscode = 0; } else { thislevel++; if (thislevel > unpackd->treelevels) maybe_errx("File corrupt"); } } } finished: if (bytes_out != unpackd->uncompressed_size) maybe_errx("Premature EOF"); unpackd->uncompressed_size=bytes_out; // hack } /* Handler for pack(1)'ed file */ static off_t unpack(int in, int out, char *pre, size_t prelen, off_t *bytes_in) { unpack_descriptor_t unpackd; unpack_parse_header(dup(in), dup(out), pre, prelen, bytes_in, &unpackd); unpack_decode(&unpackd, bytes_in); unpack_descriptor_fini(&unpackd); /* If we reached here, the unpack was successful */ return (unpackd.uncompressed_size); } void usage() { printf("Usage:\n ./bff_huffman_decompress INFILE OUTFILE\n"); } int main(int argc,char**argv) { if (argc<3) { fprintf(stderr,"[!] Please specify the input and output file as command line arguments\n"); usage(); return 1; } FILE*in=fopen(argv[1],"r"); if (!in) { fprintf(stderr,"[-] Could *not* open input file\n"); return 1; } int in_fd=fileno(in); FILE*out=fopen(argv[2],"w"); if (!out) { fprintf(stderr,"[-] Could *not* open output file\n"); return 1; } int out_fd=fileno(out); off_t uncompressed_size=unpack(in_fd,out_fd,0,0,0); if (uncompressed_size>0) { printf("[+] File was successfully decompressed, decompressed size is %lu (%luKB)\n", uncompressed_size,uncompressed_size/1024); return 0; } else { fprintf(stderr,"[-] Decompression of the file *not* succeeded. FAILED!\n"); return 1; } return 0; } ================================================ FILE: src/bff/bffxtractor.py ================================================ #!/usr/bin/env python # A hacky extraction utility for extracting the contents of BFF volume entries. # It can't parse a BFF file itself, but expects the BFF volume entry to already # be extracted to a file; it then extracts the original file from the volume entry # file. Thus, it is best used with binwalk. import os import sys import struct import subprocess ## {{{ http://code.activestate.com/recipes/82465/ (r4) def _mkdir(newdir): """works the way a good mkdir should :) - already exists, silently complete - regular file in the way, raise an exception - parent directory(ies) does not exist, make them as well """ if os.path.isdir(newdir): pass elif os.path.isfile(newdir): raise OSError("a file with the same name as the desired " \ "dir, '%s', already exists." % newdir) else: head, tail = os.path.split(newdir) if head and not os.path.isdir(head): _mkdir(head) #print "_mkdir %s" % repr(newdir) if tail: os.mkdir(newdir) ## end of http://code.activestate.com/recipes/82465/ }}} HUFFMAN_MAGIC = 0xEA6C MAGICS = [0xEA6B, HUFFMAN_MAGIC, 0xEA6D] HEADER_SIZE = 64 POST_HEADER_SIZE = 40 script_path = os.path.dirname(os.path.realpath(__file__)) try: fd = open(sys.argv[1], 'rb') except: print "Usage: %s " % sys.argv[0] sys.exit(1) header = fd.read(HEADER_SIZE) magic = struct.unpack(" $(MAGIC).binwalk for FILE in magic/*; do \ cat $$FILE >> $(MAGIC).binwalk ; \ done install: mkdir -p $(ETC) mkdir -p $(BIN) cp $(MAGIC).* $(ETC) cp binwalk $(BIN)/binwalk clean: rm -f binwalk *.o cleanall: clean rm -rf $(FILE) rm -rf config.* *.cache rm -f Makefile distclean: cleanall rm -rf $(ETC) rm -f $(BIN)/binwalk ================================================ FILE: src/binwalk-0.4.1/src/binwalk.c ================================================ #include #include #include #include #include #include #include #include #include #include #include "update.h" #include "binwalk.h" int main(int argc, char *argv[]) { char *out_file = NULL, *last_optarg = NULL; char *magic_file_contents = NULL, *marker = NULL, *magic = NULL; size_t mfsize = 0; int c = 0, i = 0; int filter_count = 0, magic_offset = 0, magic_size = 0, wildcard = 0, num_sigs = 0, check_magic_file = 0, fast_filter = 0; int update = 0, ignore_short_sigs = 1, use_default_filters = 1; int retval = EXIT_FAILURE; struct magic_signature *signatures[MAX_SIGNATURES]; struct magic_filter *filters[MAX_FILTERS]; struct binconf config = { 0 }; int long_opt_index = 0; char *short_options = "b:l:m:o:f:y:x:i:aAcCdkstvquh"; struct option long_options[] = { { "align", required_argument, NULL, 'b' }, { "length", required_argument, NULL, 'l' }, { "magic", required_argument, NULL, 'm' }, { "offset", required_argument, NULL, 'o' }, { "file", required_argument, NULL, 'f' }, { "search", required_argument, NULL, 'y' }, { "exclude", required_argument, NULL, 'x' }, { "include", required_argument, NULL, 'i' }, { "all", no_argument, NULL, 'a' }, { "opcodes", no_argument, NULL, 'A' }, { "validate", no_argument, NULL, 'c' }, { "cast", no_argument, NULL, 'C' }, { "defaults", no_argument, NULL, 'd' }, { "keep-going", no_argument, NULL, 'k' }, { "smart", no_argument, NULL, 's' }, { "fast", no_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "quiet", no_argument, NULL, 'q' }, { "update", no_argument, NULL, 'u' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; /* Need at least one argument: the target file */ if(argc == 1) { usage(argv[0]); goto end; } /* Initialize global variables */ memset((void *) &globals,0,sizeof(globals)); /* Initialize default configuration settings */ config.flags = MAGIC_NONE; config.align = DEFAULT_BYTE_ALIGN; config.smart = 1; while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'a': ignore_short_sigs = 0; break; case 'b': config.align = str2int(optarg); break; case 'c': check_magic_file = 1; break; case 'C': config.magic = strdup(MAGIC_CAST); config.flags |= MAGIC_CONTINUE; break; case 'A': config.magic = strdup(MAGIC_ARCH); ignore_short_sigs = 0; break; case 'f': out_file = strdup(optarg); break; case 'i': add_filter(filters, &filter_count, FILTER_ADD, optarg); break; case 'l': config.length = str2int(optarg); break; case 'm': config.magic = strdup(optarg); break; case 'o': config.offset = str2int(optarg); break; case 'd': use_default_filters = 0; break; case 's': config.smart = 0; break; case 't': fast_filter = 1; break; case 'k': config.flags |= MAGIC_CONTINUE; break; case 'y': fast_filter = 1; use_default_filters = 0; add_filter(filters, &filter_count, FILTER_INCLUDE, optarg); break; case 'x': add_filter(filters, &filter_count, FILTER_EXCLUDE, optarg); break; case 'q': globals.quiet = 1; break; case 'u': update = 1; break; case 'v': config.verbose = 1; break; default: usage(argv[0]); goto end; } /* Keep a copy of the last optarg so we can distinguish between option arguments and file names later on */ if(optarg) { if(last_optarg) free(last_optarg); last_optarg = strdup(optarg); } } /* Update magic files from SVN repository */ if(update) { printf("Updating magic signatures..."); if(update_magic_file(BINWALK_UPDATE_URL, MAGIC) && update_magic_file(BINCAST_UPDATE_URL, MAGIC_CAST) && update_magic_file(BINARCH_UPDATE_URL, MAGIC_ARCH)) { printf("finished.\n"); retval = EXIT_SUCCESS; } else { printf("failed.\n"); } goto end; } /* Unless otherwise specified, apply default filters */ if(use_default_filters) { add_filter(filters, &filter_count, FILTER_ADD, GZIP_FILTER); add_filter(filters, &filter_count, FILTER_ADD, LZMA_FILTER); add_filter(filters, &filter_count, FILTER_ADD, JFFS_FILTER); add_filter(filters, &filter_count, FILTER_EXCLUDE, INVALID_FILTER); } /* Use the default magic file if none was specified on the command line */ if(config.magic == NULL) { config.magic = strdup(MAGIC); } /* Initialize libmagic */ config.cookie = magic_open(config.flags); if(!config.cookie) { fprintf(stderr,"ERROR: Failed to initialize libmagic: %s\n", magic_error(config.cookie)); goto end; } /* Validate the magic file */ if(check_magic_file) { if(magic_check(config.cookie, config.magic) != 0) { fprintf(stderr, "ERROR: Invalid magic file '%s': %s\n", config.magic, magic_error(config.cookie)); } else { retval = EXIT_SUCCESS; } goto end; } /* If an output file was specified, open it */ if(out_file != NULL) { globals.fsout = fopen(out_file,"w"); if(!globals.fsout) { perror("ERROR: Failed to open output file for writing"); goto end; } } /* Load the magic signatures file */ if(magic_load(config.cookie, config.magic) == -1) { fprintf(stderr,"ERROR: Failed to load magic file '%s': %s\n", config.magic, magic_error(config.cookie)); goto end; } if(config.smart) { /* Load magic signatures into the signatures struct array. */ magic_file_contents = (char *) file_read((char *) config.magic, &mfsize); marker = magic_file_contents; for(i=0; i= '0' && marker[0] <= '9') { /* Parse out the magic value, file offset and size for this entry */ magic = parse_magic(marker, &magic_offset, &magic_size, &wildcard, filters, filter_count, ignore_short_sigs, fast_filter); if(magic && magic_size > 0) { signatures[num_sigs] = malloc(sizeof(struct magic_signature)); signatures[num_sigs]->size = magic_size; signatures[num_sigs]->offset = magic_offset; signatures[num_sigs]->wildcard = wildcard; signatures[num_sigs]->signature = malloc(magic_size); memcpy(signatures[num_sigs]->signature, magic, magic_size); num_sigs++; } if(magic) free(magic); } /* Find the next new line. Break if not found, skip to the next character if one is found. */ marker = strstr(marker, "\n"); if(!marker) break; marker++; } } else { num_sigs = 1; } /* Process all the files specified on the command line */ for(i=argc-1; i>0; i--) { /* If we've gotten to the arguments, we're done */ if((argv[i][0] == '-') || ((last_optarg != NULL) && (strcmp(argv[i], last_optarg) == 0)) ) { break; } retval = process_file(argv[i], &config, signatures, num_sigs, filters, filter_count); } end: if(config.magic) free(config.magic); if(magic_file_contents) munmap((void *) magic_file_contents, mfsize); if(globals.fsout != NULL) fclose(globals.fsout); if(config.cookie) magic_close(config.cookie); return retval; } /* Search a file for magic signatures */ int process_file(char *bin_file, struct binconf *config, struct magic_signature **signatures, int num_sigs, struct magic_filter **filters, int filter_count) { char *md5 = NULL, *current_time = NULL, *ptr = NULL; const void *buffer = NULL, *type = NULL; size_t fsize = 0; int i = 0, j = 0, retval = EXIT_FAILURE; /* Read in the target file */ buffer = file_read(bin_file, &fsize); if(!buffer || fsize == 0) { fprintf(stderr,"ERROR: Failed to read file '%s'.\n", bin_file); goto end; } /* If no scan length was specified, scan the entire file */ if(!config->length || config->length > fsize) { config->length = fsize; } /* Sanity check on the length + offset values */ if((config->length + config->offset) > fsize) { config->length -= (config->length + config->offset) - fsize; } if(config->verbose) { md5 = md5_string((void *) buffer,fsize); current_time = timestamp(); print("\n"); print("Scan Time: %s\n", current_time); print("Magic File: %s\n", config->magic); if(config->smart) { print("Signatures: %d\n", num_sigs); } else { print("Signatures: *\n"); } print("Target File: %s\n", bin_file); print("MD5 Checksum: %s\n", md5); if(current_time) free(current_time); if(md5) free(md5); } print("\nDECIMAL \tHEX \tDESCRIPTION\n"); print("-------------------------------------------------------------------------------------------------------\n"); /* Loop through the file contents starting at the given offset. * Honor the given byte alignment (i.e., if align == 4, only look at every 4th byte). * Stop looping when length bytes have been searched, or when the end of the file is reached. */ for(i=config->offset; ((i-config->offset)length && i<(fsize-config->align)); i+=config->align) { for(j=0; jsmart || (i+signatures[j]->offset < fsize)) { /* Pre-screen data for magic file signatures prior to invoking libmagic. This significantly improves scan time. */ if(!config->smart || signatures[j]->wildcard == 1 || memcmp((buffer+i+signatures[j]->offset), signatures[j]->signature, signatures[j]->size) == 0 ) { /* Since we found a signature match, ask libmagic to further examine the given offset into the file buffer */ type = magic_buffer(config->cookie, buffer+i, (fsize-i)); /* Ignore NULL, ".*text.*" and "data" responses */ if(type != NULL && strncmp(type,DATA,DATA_SIZE) != 0 && strstr(type,TEXT) == NULL) { /* * If filters were specified and the filter check specifies that * result should be excluded, then don't display it. */ if(filter_count > 0) { /* Don't display anything that has been explicitly marked in the exclude list */ if(filter_check(filters, filter_count, (char *) type) == RESULT_EXCLUDE) { break; } } /* Prettify output if multiple matches were found at the same offset */ if((config->flags | MAGIC_CONTINUE) == config->flags) { while((ptr = strstr(type, MULTIPLE_MATCH_DELIM))) { memcpy(ptr, MULTIPLE_MATCH_NEWLINE, MULTIPLE_MATCH_SIZE); } } print("%-10d\t0x%-8X\t",i,i); print("%s\n",type); break; } } } } } print("\n"); retval = EXIT_SUCCESS; end: if(buffer) munmap((void *) buffer, fsize); return retval; } void usage(char *progname) { fprintf(stderr,"\n"); fprintf(stderr,"Binwalk v%s\n", PACKAGE_VERSION); fprintf(stderr,"\n"); fprintf(stderr,"Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n", progname); fprintf(stderr,"\n"); fprintf(stderr,USAGE_OPTIONS, MAGIC, GZIP_FILTER, LZMA_FILTER, JFFS_FILTER, INVALID_FILTER); fprintf(stderr,"\n"); return; } ================================================ FILE: src/binwalk-0.4.1/src/binwalk.h ================================================ #ifndef BINWALK_H #define BINWALK_H #include #include "md5.h" #include "mparse.h" #include "filter.h" #include "common.h" #include "config.h" /* These should get defined by the Makefile. If not, default to /etc/binwalk/magic.bin*. */ #ifndef MAGIC #define MAGIC "/etc/binwalk/magic.binwalk" #endif #ifndef MAGIC_CAST #define MAGIC_CAST "/etc/binwalk/magic.bincast" #endif #ifndef MAGIC_ARCH #define MAGIC_ARCH "/etc/binwalk/magic.binarch" #endif #define DATA "data" #define DATA_SIZE 4 #define TEXT "text" #define DEFAULT_BYTE_ALIGN 1 #define PROGRESS_INTERVAL 1000 #define MAX_SIGNATURES 8192 #define MULTIPLE_MATCH_DELIM "\\012- " #define MULTIPLE_MATCH_NEWLINE "\r\n\t\t\t\t" #define MULTIPLE_MATCH_SIZE 6 #define GZIP_FILTER "gzip" #define LZMA_FILTER "lzma" #define JFFS_FILTER "jffs2" #define INVALID_FILTER "invalid" #define USAGE_OPTIONS "\ OPTIONS\n\ \t-o, --offset= File offset to start searching at\n\ \t-l, --length= Number of bytes to search\n\ \t-b, --align= Set byte alignment\n\ \t-f, --file= Log results to file\n\ \t-m, --magic= Magic file to use [%s]\n\ \t-y, --search= Only search for matches that have in their description (implies -n, -t)\n\ \t-x, --exclude= Exclude matches that have in their description\n\ \t-i, --include= Include matches that are normally excluded and that have in their description *\n\ \t-a, --all Search for all matches, including those that are normally excluded *\n\ \t-d, --defaults Speed up scan by disabling default filters **\n\ \t-t, --fast Speed up scan by only loading signatures specified by -i or -y\n\ \t-u, --update Update magic signature files\n\ \t-v, --verbose Enable verbose mode\n\ \t-s, --smart Disable smart matching (implies -a)\n\ \t-k, --keep-going Don't stop at the first match\n\ \t-c, --validate Validate magic file\n\ \t-q, --quiet Supress output to stdout\n\ \t-A, --opcodes Scan for executable code (implies -a)\n\ \t-C, --cast Cast file contents as various data types (implies -k)\n\ \n\n\ * Signatures of two bytes or less are excluded by default. Use -i or -a to include them in the search.\n\ \n\ ** Default filters include '%s', '%s' and '%s' results, and exclude '%s' results. Disabling the default\n\ filters will speed up scan time, but may miss these file types.\n\ " struct magic_signature { int offset; int size; int wildcard; char *signature; }; struct binconf { int smart; int verbose; int flags; int offset; int align; int length; char *magic; magic_t cookie; }; void usage(char *progname); int process_file(char *bin_file, struct binconf *config, struct magic_signature **signatures, int num_sigs, struct magic_filter **filters, int filter_count); #endif ================================================ FILE: src/binwalk-0.4.1/src/common.c ================================================ #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #ifdef __linux #include #endif /* Convert decimal and hexadecimal strings to integers */ int str2int(char *str) { int val = 0; int strsize = 0; int base = 10; char *strptr = NULL; char buffer[INT_MAX_STR_SIZE] = { 0 }; if(str != NULL) { strsize = strlen(str); if(strsize < INT_MAX_STR_SIZE) { memcpy((void *) &buffer, str, strsize); strptr = (char *) &buffer; /* If the string starts with '0x' or '\x', or if it ends in 'h' or 'H', treat it as hex */ if(strsize >= 2) { if(strptr[1] == 'x') { strptr += 2; base = 16; } else if(strptr[strsize-1] == 'h' || strptr[strsize-1] == 'H') { strptr[strsize-1] = '\0'; base = 16; } } val = strtol(strptr,NULL,base); } } return val; } /* Reads in and returns the contents and size of a given file */ const void *file_read(char *file, size_t *fsize) { int fd = 0; size_t file_size = 0; struct stat _fstat = { 0 }; const void *buffer = NULL; fd = open(file, O_RDONLY); if(!fd) { perror(file); goto end; } if(stat(file, &_fstat) == -1) { perror(file); goto end; } if(_fstat.st_size > 0) { file_size = _fstat.st_size; } #ifdef __linux else { long long long_file_size = 0; /* Special files may report a zero size in stat(); must get their file size via an ioctl call */ if(ioctl(fd, BLKGETSIZE64, &long_file_size) == -1) { perror("ioctl"); goto end; } else { file_size = (size_t) long_file_size; } } #endif if(file_size > 0) { buffer = mmap(NULL, file_size, PROT_READ, (MAP_SHARED | MAP_NORESERVE), fd, 0); if(buffer == MAP_FAILED) { perror("mmap"); buffer = NULL; } else { *fsize = file_size; } } end: if(fd) close(fd); return buffer; } /* Print messages to both the log file and stdout, as appropriate */ void print(const char* format, ...) { va_list args; va_start(args,format); if(globals.fsout != NULL) { vfprintf(globals.fsout,format,args); fflush(globals.fsout); } if(globals.quiet == 0) { vfprintf(stdout,format,args); fflush(stdout); } va_end(args); return; } /* Returns the current timestamp as a string */ char *timestamp() { time_t t = { 0 }; struct tm *tmp = NULL; char *ts = NULL; t = time(NULL); tmp = localtime(&t); if(!tmp) { perror("Localtime failure"); goto end; } ts = malloc(MAX_TIMESTAMP_SIZE); if(!ts) { perror("Malloc failure"); goto end; } memset(ts,0,MAX_TIMESTAMP_SIZE); if(strftime(ts,MAX_TIMESTAMP_SIZE-1,TIMESTAMP_FORMAT,tmp) == 0) { if(ts) free(ts); ts = NULL; } end: return ts; } ================================================ FILE: src/binwalk-0.4.1/src/common.h ================================================ #ifndef COMMON_H #define COMMON_H #define INT_MAX_STR_SIZE 1024 #define MAX_TIMESTAMP_SIZE 1024 #define TIMESTAMP_FORMAT "%b %d, %Y @ %T" /* These globals are set once, read many */ struct bin_globals { FILE *fsout; int quiet; } globals; int str2int(char *str); const void *file_read(char *file, size_t *fsize); void print(const char* format, ...); char *timestamp(); #endif ================================================ FILE: src/binwalk-0.4.1/src/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for binwalk 0.4.1. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: http://code.google.com/p/binwalk/issues/list about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='binwalk' PACKAGE_TARNAME='binwalk' PACKAGE_VERSION='0.4.1' PACKAGE_STRING='binwalk 0.4.1' PACKAGE_BUGREPORT='http://code.google.com/p/binwalk/issues/list' PACKAGE_URL='' ac_unique_file="md5.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS DOFILE FILE LIBOBJS EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_static enable_libmagic enable_updates ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures binwalk 0.4.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/binwalk] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of binwalk 0.4.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-static perform static build --enable-libmagic build against libmagic --disable-updates disable update features that rely on libcurl Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF binwalk configure 0.4.1 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( cat <<\_ASBOX ## ----------------------------------------------------------- ## ## Report this to http://code.google.com/p/binwalk/issues/list ## ## ----------------------------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by binwalk $as_me 0.4.1, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu FILE="file-5.07" CFLAGS="-Wall $CFLAGS" LDFLAGS="-lz $LDFLAGS" # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; STATIC=y else STATIC=n fi # Check whether --enable-libmagic was given. if test "${enable_libmagic+set}" = set; then : enableval=$enable_libmagic; MAGIC=y else MAGIC=n fi # Check whether --enable-updates was given. if test "${enable_updates+set}" = set; then : enableval=$enable_updates; CURL=n else CURL=y fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in arpa/inet.h fcntl.h stdlib.h string.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else echo "error: missing necessary header file" && exit fi done for ac_func in memset strdup strstr strtol do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else as_fn_error "\"Missing necessary function\"" "$LINENO" 5 fi done if test $CURL = y then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init in -lcurl" >&5 $as_echo_n "checking for curl_easy_init in -lcurl... " >&6; } if test "${ac_cv_lib_curl_curl_easy_init+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char curl_easy_init (); int main () { return curl_easy_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_curl_curl_easy_init=yes else ac_cv_lib_curl_curl_easy_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init" >&5 $as_echo "$ac_cv_lib_curl_curl_easy_init" >&6; } if test "x$ac_cv_lib_curl_curl_easy_init" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCURL 1 _ACEOF LIBS="-lcurl $LIBS" else echo "error: missing libcurl library" && exit fi for ac_header in curl/curl.h do : ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default" if test "x$ac_cv_header_curl_curl_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CURL_CURL_H 1 _ACEOF else echo "error: missing curl header files" && exit fi done LDFLAGS="-lcurl $LDFLAGS" else CFLAGS="-DNOCURL $CFLAGS" fi if test $MAGIC = n then tar -zxvf $FILE.tar.gz && cd $FILE && ./configure && cd - DOFILE="file" CFLAGS="$CFLAGS -I./$FILE/src" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for magic_buffer in -lmagic" >&5 $as_echo_n "checking for magic_buffer in -lmagic... " >&6; } if test "${ac_cv_lib_magic_magic_buffer+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmagic $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char magic_buffer (); int main () { return magic_buffer (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_magic_magic_buffer=yes else ac_cv_lib_magic_magic_buffer=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_magic_magic_buffer" >&5 $as_echo "$ac_cv_lib_magic_magic_buffer" >&6; } if test "x$ac_cv_lib_magic_magic_buffer" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMAGIC 1 _ACEOF LIBS="-lmagic $LIBS" else echo "error: missing libmagic library" && exit fi for ac_header in magic.h do : ac_fn_c_check_header_mongrel "$LINENO" "magic.h" "ac_cv_header_magic_h" "$ac_includes_default" if test "x$ac_cv_header_magic_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MAGIC_H 1 _ACEOF else echo "error: missing libmagic header files" && exit fi done DOFILE="" LDFLAGS="-lmagic $LDFLAGS" fi if test $STATIC = y then CLIBS=$(curl-config --static-libs) LDFLAGS="-static $CLIBS $LDFLAGS" fi cp confdefs.h config.h FILE=$FILE DOFILE=$DOFILE ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by binwalk $as_me 0.4.1, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ binwalk config.status 0.4.1 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: src/binwalk-0.4.1/src/configure.ac ================================================ dnl Many thanks to Anthony Basile for the initial configure script and Makefile AC_PREREQ([2.65]) AC_INIT([binwalk],[0.4.1],[http://code.google.com/p/binwalk/issues/list]) AC_CONFIG_SRCDIR([md5.c]) AC_PROG_CC AC_LANG(C) FILE="file-5.07" CFLAGS="-Wall $CFLAGS" LDFLAGS="-lz $LDFLAGS" AC_ARG_ENABLE([static], [ --enable-static perform static build ], [STATIC=y], [STATIC=n]) AC_ARG_ENABLE([libmagic], [ --enable-libmagic build against libmagic ], [MAGIC=y], [MAGIC=n]) AC_ARG_ENABLE([updates], [ --disable-updates disable update features that rely on libcurl ], [CURL=n], [CURL=y]) AC_TYPE_SIZE_T AC_FUNC_MALLOC AC_CHECK_HEADERS([arpa/inet.h fcntl.h stdlib.h string.h unistd.h],[],[echo "error: missing necessary header file" && exit]) AC_CHECK_FUNCS([memset strdup strstr strtol],[],AC_MSG_ERROR(["Missing necessary function"])) if test $CURL = y then AC_CHECK_LIB([curl],[curl_easy_init],[],[echo "error: missing libcurl library" && exit],[]) AC_CHECK_HEADERS([curl/curl.h],[],[echo "error: missing curl header files" && exit]) LDFLAGS="-lcurl $LDFLAGS" else CFLAGS="-DNOCURL $CFLAGS" fi dnl extract and run file utility configure script if test $MAGIC = n then tar -zxvf $FILE.tar.gz && cd $FILE && ./configure && cd - DOFILE="file" CFLAGS="$CFLAGS -I./$FILE/src" else AC_CHECK_LIB([magic],[magic_buffer],[],[echo "error: missing libmagic library" && exit],[]) AC_CHECK_HEADERS([magic.h],[],[echo "error: missing libmagic header files" && exit]) DOFILE="" LDFLAGS="-lmagic $LDFLAGS" fi dnl curl static libs only required if we're doing a static build if test $STATIC = y then CLIBS=$(curl-config --static-libs) LDFLAGS="-static $CLIBS $LDFLAGS" fi cp confdefs.h config.h AC_SUBST(FILE, $FILE) AC_SUBST(DOFILE, $DOFILE) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ================================================ FILE: src/binwalk-0.4.1/src/filter.c ================================================ #include #include #include #include #include "filter.h" /* Appends a new filter to the filters array */ void add_filter(struct magic_filter *filters[], int *filter_count, enum filter_type_t type, char* filter) { if(*filter_count < MAX_FILTERS) { filters[*filter_count] = malloc(sizeof(struct magic_filter)); if(filters[*filter_count] != NULL) { memset(filters[*filter_count], 0, sizeof(struct magic_filter)); filters[*filter_count]->type = type; filters[*filter_count]->filter = strdup(filter); uppercase(filters[*filter_count]->filter); *filter_count = *filter_count+1; } else { perror("Malloc failure"); } } return; } /* Check to see if the description matches any of the include / exclude filters */ enum filter_result_t filter_check(struct magic_filter *filters[], int filter_count, char *description) { int i = 0; enum filter_result_t found = RESULT_NOT_FOUND; /* If include filters have been specified, then ONLY those descriptions that match the include filters * should be used. Loop through to see if there are any include filters; if so, make sure this desciption * matches one of the include filters. */ for(i=0; itype == FILTER_INCLUDE || filters[i]->type == FILTER_ADD) { /* If an explicit include filter was specified, then default to RESULT_EXCLUDE unless a match is found */ if(filters[i]->type == FILTER_INCLUDE) { found = RESULT_EXCLUDE; } if(string_contains(description, filters[i]->filter)) { found = RESULT_INCLUDE; break; } } } /* Check to see if description matches any exclude filters */ for(i=0; itype == FILTER_EXCLUDE) { if(string_contains(description, filters[i]->filter)) { found = RESULT_EXCLUDE; break; } } } return found; } /* Performs a case-insensitive string search */ int string_contains(char *haystack, char *needle) { char *my_haystack = NULL; int retval = 0; /* Duplicate the haystack string, as we will be converting it to all uppercase */ my_haystack = strdup(haystack); if(!my_haystack) { perror("strdup"); } else { /* Convert haystack to all upper case */ uppercase(my_haystack); /* Search for needle in haystack */ if(strstr(my_haystack, needle) != NULL) { retval = 1; } } if(my_haystack) free(my_haystack); return retval; } /* Convert a given string to all upper case */ void uppercase(char *string) { int i = 0; for(i=0; i\n__________E MIPS archive >20 string U with MIPS Ucode members >21 string L with MIPSEL members >21 string B with MIPSEB members >19 string L and an EL hash table >19 string B and an EB hash table >22 string X -- out of date # JAR archiver (.j), this is the successor to ARJ, not Java's JAR (which is essentially ZIP) 0xe string \x1aJar\x1b JAR (ARJ Software, Inc.) archive data 0 string JARCS JAR (ARJ Software, Inc.) archive data # ARJ archiver (jason@jarthur.Claremont.EDU) 0 leshort 0xea60 ARJ archive data !:mime application/x-arj >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: %s, >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # [JW] idarc says this is also possible 2 leshort 0xea60 ARJ archive data >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: %s, >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # RAR archiver (Greg Roelofs, newt@uchicago.edu) 0 string Rar! RAR archive data [NSRL|RAR] # HPACK archiver (Peter Gutmann, pgut1@cs.aukuni.ac.nz) 0 string HPAK HPACK archive data [NSRL|HPAK] # JAM Archive volume format, by Dmitry.Kohmanyuk@UA.net 0 string \351,\001JAM\ JAM archive, [NSRL|JAM] # LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) 2 string -lh0- LHarc 1.x archive data [lh0] [NSRL|LHA1] 2 string -lh1- LHarc 1.x archive data [lh1] [NSRL|LHA1] 2 string -lz4- LHarc 1.x archive data [lz4] [NSRL|LHA1] 2 string -lz5- LHarc 1.x archive data [lz5] [NSRL|LHA1] # [never seen any but the last; -lh4- reported in comp.compression:] 2 string -lzs- LHa 2.x? archive data [lzs] [NSRL|LHA2] 2 string -lh\40- LHa 2.x? archive data [lh ] [NSRL|LHA2] 2 string -lhd- LHa 2.x? archive data [lhd] [NSRL|LHA2] 2 string -lh2- LHa 2.x? archive data [lh2] [NSRL|LHA2] 2 string -lh3- LHa 2.x? archive data [lh3] [NSRL|LHA2] 2 string -lh4- LHa (2.x) archive data [lh4] [NSRL|LHA2] 2 string -lh5- LHa (2.x) archive data [lh5] [NSRL|LHA2] 2 string -lh6- LHa (2.x) archive data [lh6] [NSRL|LHA2] 2 string -lh7- LHa (2.x) archive data [lh7] [NSRL|LHA2] # SQUISH archiver (Greg Roelofs, newt@uchicago.edu) 0 string SQSH squished archive data (Acorn RISCOS) [NSRL|SQSH] # UC2 archiver (Greg Roelofs, newt@uchicago.edu) # I can't figure out the self-extracting form of these buggers... 0 string UC2\x1a UC2 archive data [NSRL|UC2] # Zoo archiver 20 lelong 0xfdc4a7dc Zoo archive data [NSRL|ZOO] # Shell archives # JT, 2004-03-17: The "#" in the middle of the line makes it look like the # rest of the line is commented out - I guess it's OK? Beware if parsing! 10 string #\ This\ is\ a\ shell\ archive shell archive text [NSRL|SH] # # LBR. NB: May conflict with the questionable # "binary Computer Graphics Metafile" format. # 0 string \0\ \ \ \ \ \ \ \ \ \ \ \0\0 LBR archive data [NSRL|LBR] # # PMA (CP/M derivative of LHA) # 2 string -pm0- PMarc archive data [pm0] [NSRL|PMA] 2 string -pm1- PMarc archive data [pm1] [NSRL|PMA] 2 string -pm2- PMarc archive data [pm2] [NSRL|PMA] 2 string -pms- PMarc SFX archive (CP/M, DOS) [NSRL|PMA-SFX] 5 string -pc1- PopCom compressed executable archive (CP/M) [NSRL|PPC-SFX] # From rafael@icp.inpg.fr (Rafael Laboissiere) # The Project Revision Control System (see # http://www.XCF.Berkeley.EDU/~jmacd/prcs.html) generates a packaged project # file which is recognized by the following entry: 0 leshort 0xeb81 PRCS packaged project archive [NSRL|PRCS] # GTKtalog catalogs # by David Necas (Yeti) 4 string gtktalog\ GTKtalog catalog data archive, [NSRL|GTK] >>14 beshort 0x677a (gzipped) ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.bootloaders ================================================ #---------------------------Bootloaders-------------------------------- # CFE bootloader 0 string CFE1CFE1 CFE boot loader, little endian 0 string 1EFC1EFC CFE boot loader, big endian ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.compressed ================================================ #------------------Compression Formats----------------------------- # bzip2 0 string BZh >4 string 1AY&SY bzip2 compressed data !:mime application/x-bzip2 >>3 byte >47 \b, block size = %c00k # lzip 0 string LZIP lzip compressed data !:mime application/x-lzip >4 byte x \b, version: %d # LZO 0 string \211LZO\000\015\012\032\012 LZO compressed data # 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) # http://www.7-zip.org or DOC/7zFormat.txt # 0 string 7z\274\257\047\034 7-zip archive data, >6 byte x version %d >7 byte x \b.%d # standard unix compress 0 beshort 0x1f9d compress'd data >2 byte&0x80 >0 block compressed >2 byte&0x1f x %d bits # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) # Edited by Chris Chittleborough , March 2002 # * Original filename is only at offset 10 if "extra field" absent # * Produce shorter output - notably, only report compression methods # other than 8 ("deflate", the only method defined in RFC 1952). 0 string \037\213 gzip compressed data !:mime application/x-gzip >2 byte <8 \b, reserved (invalid) method >2 byte >8 \b, unknown (invalid) method >3 byte &0x01 \b, ASCII >3 byte &0x02 \b, has CRC >3 byte &0x04 \b, extra field >3 byte&0xC =0x08 >>10 string x \b, was "%s" >3 byte &0x10 \b, has comment >9 byte =0x00 \b, from FAT filesystem (MS-DOS, OS/2, NT) >9 byte =0x01 \b, from Amiga >9 byte =0x02 \b, from VMS >9 byte =0x03 \b, from Unix >9 byte =0x04 \b, from VM/CMS >9 byte =0x05 \b, from Atari >9 byte =0x06 \b, from HPFS filesystem (OS/2, NT) >9 byte =0x07 \b, from MacOS >9 byte =0x08 \b, from Z-System >9 byte =0x09 \b, from CP/M >9 byte =0x0A \b, from TOPS/20 >9 byte =0x0B \b, from NTFS filesystem (NT) >9 byte =0x0C \b, from QDOS >9 byte =0x0D \b, from Acorn RISCOS >9 byte >0x0D \b, invalid source >3 byte &0x10 \b, comment >3 byte &0x20 \b, encrypted # Dates before 1992 are invalid, unless of course you're DD-WRT in which # case you don't know how to set a date in your gzip files. Brilliant. >4 lelong =0 \b, DD-WRT date: >4 lelong <0 \b, invalid date: >4 lelong >0 >>4 lelong <694224000 \b, invalid date: >>4 lelong =694224000 \b, invalid date: >>4 lelong >694224000 \b, last modified: >4 ledate x %s >8 byte 2 \b, max compression >8 byte 4 \b, max speed # Zlib signatures 0 beshort 0x789C zlib compressed data 0 beshort 0x78DA zlib compressed data 0 beshort 0x7801 zlib compressed data # Supplementary magic data for the file(1) command to support # rzip(1). The format is described in magic(5). # # Copyright (C) 2003 by Andrew Tridgell. You may do whatever you want with # this file. # 0 string RZIP rzip compressed data >4 byte x - version %d >5 byte x \b.%d >6 belong x (%d bytes) # ZIP compression (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) 0 string PK\003\004 Zip archive data, >4 byte 0x00 v0.0 !:mime application/zip >4 byte 0x09 at least v0.9 to extract !:mime application/zip >4 byte 0x0a at least v1.0 to extract !:mime application/zip >4 byte 0x0b at least v1.1 to extract !:mime application/zip >0x161 string WINZIP WinZIP self-extracting !:mime application/zip >4 byte 0x14 >>30 ubelong !0x6d696d65 at least v2.0 to extract !:mime application/zip # Alternate ZIP string (amc@arwen.cs.berkeley.edu) 0 string PK00PK\003\004 Zip archive data [NSRL|ZIP] # Type: LZMA # URL: http://www.7-zip.org/sdk.html # # Added additional parsing to help verify LZMA matches and weed out false positives. # Added improved signature checking. # Added checks for possibly (probably) invalid matches. # From: Craig Heffner #First LZMA signature 0 string \x5d\x00\x00 LZMA compressed data, >0 leshort >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes #An alternative common LZMA signature 1 belong 0x00008000 LZMA compressed data, >0 byte 0 invalid >0 leshort >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes #Signature for less common LZMA flag/dictionary values. Results in lots of false positives, but usually marked as invalid. 1 beshort 0x0000 LZMA compressed data, >0 byte 0 invalid >0 byte >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.executables ================================================ #------------------Standard file formats------------------------------------ # elf: file(1) magic for ELF executables # # We have to check the byte order flag to see what byte order all the # other stuff in the header is in. # # What're the correct byte orders for the nCUBE and the Fujitsu VPP500? # # Created by: unknown # Modified by (1): Daniel Quinlan # Modified by (2): Peter Tobias (core support) # Modified by (3): Christian 'Dr. Disk' Hechelmann (fix of core support) # Modified by (4): (VMS Itanium) # Modified by (5): Matthias Urlichs (Listing of many architectures) 0 string \177ELF ELF >4 byte 0 invalid class >4 byte 1 32-bit >4 byte 2 64-bit >5 byte 0 invalid byte order >5 byte 1 LSB >>16 leshort 0 no file type, !:strength *2 !:mime application/octet-stream >>16 leshort 1 relocatable, !:mime application/x-object >>16 leshort 2 executable, !:mime application/x-executable >>16 leshort 3 shared object, !:mime application/x-sharedlib >>16 leshort 4 core file !:mime application/x-coredump # Core file detection is not reliable. #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, >>18 leshort 4 Motorola >>>36 lelong &0x01000000 68000 - invalid byte order, >>>36 lelong &0x00810000 CPU32 - invalid byte order, >>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, # The official e_machine number for MIPS is now #8, regardless of endianness. # The second number (#10) will be deprecated later. For now, we still # say something if #10 is encountered, but only gory details for #8. >>18 leshort 8 MIPS, >>>36 lelong &0x20 N32 >>18 leshort 10 MIPS, >>>36 lelong &0x20 N32 >>18 leshort 8 # only for 32-bit >>>4 byte 1 >>>>36 lelong&0xf0000000 0x00000000 MIPS-I >>>>36 lelong&0xf0000000 0x10000000 MIPS-II >>>>36 lelong&0xf0000000 0x20000000 MIPS-III >>>>36 lelong&0xf0000000 0x30000000 MIPS-IV >>>>36 lelong&0xf0000000 0x40000000 MIPS-V >>>>36 lelong&0xf0000000 0x50000000 MIPS32 >>>>36 lelong&0xf0000000 0x60000000 MIPS64 >>>>36 lelong&0xf0000000 0x70000000 MIPS32 rel2 >>>>36 lelong&0xf0000000 0x80000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 lelong&0xf0000000 0x00000000 MIPS-I >>>>48 lelong&0xf0000000 0x10000000 MIPS-II >>>>48 lelong&0xf0000000 0x20000000 MIPS-III >>>>48 lelong&0xf0000000 0x30000000 MIPS-IV >>>>48 lelong&0xf0000000 0x40000000 MIPS-V >>>>48 lelong&0xf0000000 0x50000000 MIPS32 >>>>48 lelong&0xf0000000 0x60000000 MIPS64 >>>>48 lelong&0xf0000000 0x70000000 MIPS32 rel2 >>>>48 lelong&0xf0000000 0x80000000 MIPS64 rel2 >>18 leshort 9 Amdahl - invalid byte order, >>18 leshort 10 MIPS (deprecated), >>18 leshort 11 RS6000 - invalid byte order, >>18 leshort 15 PA-RISC - invalid byte order, >>>50 leshort 0x0214 2.0 >>>48 leshort &0x0008 (LP64), >>18 leshort 16 nCUBE, >>18 leshort 17 Fujitsu VPP500, >>18 leshort 18 SPARC32PLUS - invalid byte order, >>18 leshort 20 PowerPC, >>18 leshort 22 IBM S/390, >>18 leshort 36 NEC V800, >>18 leshort 37 Fujitsu FR20, >>18 leshort 38 TRW RH-32, >>18 leshort 39 Motorola RCE, >>18 leshort 40 ARM, >>18 leshort 41 Alpha, >>18 leshort 0xa390 IBM S/390 (obsolete), >>18 leshort 42 Renesas SH, >>18 leshort 43 SPARC V9 - invalid byte order, >>18 leshort 44 Siemens Tricore Embedded Processor, >>18 leshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 leshort 46 Renesas H8/300, >>18 leshort 47 Renesas H8/300H, >>18 leshort 48 Renesas H8S, >>18 leshort 49 Renesas H8/500, >>18 leshort 50 IA-64, >>18 leshort 51 Stanford MIPS-X, >>18 leshort 52 Motorola Coldfire, >>18 leshort 53 Motorola M68HC12, >>18 leshort 54 Fujitsu MMA, >>18 leshort 55 Siemens PCP, >>18 leshort 56 Sony nCPU, >>18 leshort 57 Denso NDR1, >>18 leshort 58 Start*Core, >>18 leshort 59 Toyota ME16, >>18 leshort 60 ST100, >>18 leshort 61 Tinyj emb., >>18 leshort 62 x86-64, >>18 leshort 63 Sony DSP, >>18 leshort 66 FX66, >>18 leshort 67 ST9+ 8/16 bit, >>18 leshort 68 ST7 8 bit, >>18 leshort 69 MC68HC16, >>18 leshort 70 MC68HC11, >>18 leshort 71 MC68HC08, >>18 leshort 72 MC68HC05, >>18 leshort 73 SGI SVx, >>18 leshort 74 ST19 8 bit, >>18 leshort 75 Digital VAX, >>18 leshort 76 Axis cris, >>18 leshort 77 Infineon 32-bit embedded, >>18 leshort 78 Element 14 64-bit DSP, >>18 leshort 79 LSI Logic 16-bit DSP, >>18 leshort 80 MMIX, >>18 leshort 81 Harvard machine-independent, >>18 leshort 82 SiTera Prism, >>18 leshort 83 Atmel AVR 8-bit, >>18 leshort 84 Fujitsu FR30, >>18 leshort 85 Mitsubishi D10V, >>18 leshort 86 Mitsubishi D30V, >>18 leshort 87 NEC v850, >>18 leshort 88 Renesas M32R, >>18 leshort 89 Matsushita MN10300, >>18 leshort 90 Matsushita MN10200, >>18 leshort 91 picoJava, >>18 leshort 92 OpenRISC, >>18 leshort 93 ARC Cores Tangent-A5, >>18 leshort 94 Tensilica Xtensa, >>18 leshort 97 NatSemi 32k, >>18 leshort 106 Analog Devices Blackfin, >>18 leshort 113 Altera Nios II, >>18 leshort 0xae META, >>18 leshort 0x3426 OpenRISC (obsolete), >>18 leshort 0x8472 OpenRISC (obsolete), >>18 leshort 0x9026 Alpha (unofficial), >>20 lelong 0 invalid version >>20 lelong 1 version 1 >>36 lelong 1 MathCoPro/FPU/MAU Required >5 byte 2 MSB >>16 beshort 0 no file type, !:mime application/octet-stream >>16 beshort 1 relocatable, !:mime application/x-object >>16 beshort 2 executable, !:mime application/x-executable >>16 beshort 3 shared object, !:mime application/x-sharedlib >>16 beshort 4 core file, !:mime application/x-coredump #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) belong >0 (signal %d), >>16 beshort &0xff00 processor-specific, >>18 beshort 0 no machine, >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, >>18 beshort 4 Motorola >>>36 belong &0x01000000 68000, >>>36 belong &0x00810000 CPU32, >>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, # only for MIPS - see comment in little-endian section above. >>18 beshort 8 MIPS, >>>36 belong &0x20 N32 >>18 beshort 10 MIPS, >>>36 belong &0x20 N32 >>18 beshort 8 # only for 32-bit >>>4 byte 1 >>>>36 belong&0xf0000000 0x00000000 MIPS-I >>>>36 belong&0xf0000000 0x10000000 MIPS-II >>>>36 belong&0xf0000000 0x20000000 MIPS-III >>>>36 belong&0xf0000000 0x30000000 MIPS-IV >>>>36 belong&0xf0000000 0x40000000 MIPS-V >>>>36 belong&0xf0000000 0x50000000 MIPS32 >>>>36 belong&0xf0000000 0x60000000 MIPS64 >>>>36 belong&0xf0000000 0x70000000 MIPS32 rel2 >>>>36 belong&0xf0000000 0x80000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 belong&0xf0000000 0x00000000 MIPS-I >>>>48 belong&0xf0000000 0x10000000 MIPS-II >>>>48 belong&0xf0000000 0x20000000 MIPS-III >>>>48 belong&0xf0000000 0x30000000 MIPS-IV >>>>48 belong&0xf0000000 0x40000000 MIPS-V >>>>48 belong&0xf0000000 0x50000000 MIPS32 >>>>48 belong&0xf0000000 0x60000000 MIPS64 >>>>48 belong&0xf0000000 0x70000000 MIPS32 rel2 >>>>48 belong&0xf0000000 0x80000000 MIPS64 rel2 >>18 beshort 9 Amdahl, >>18 beshort 10 MIPS (deprecated), >>18 beshort 11 RS6000, >>18 beshort 15 PA-RISC >>>50 beshort 0x0214 2.0 >>>48 beshort &0x0008 (LP64) >>18 beshort 16 nCUBE, >>18 beshort 17 Fujitsu VPP500, >>18 beshort 18 SPARC32PLUS, >>>36 belong&0xffff00 0x000100 V8+ Required, >>>36 belong&0xffff00 0x000200 Sun UltraSPARC1 Extensions Required, >>>36 belong&0xffff00 0x000400 HaL R1 Extensions Required, >>>36 belong&0xffff00 0x000800 Sun UltraSPARC3 Extensions Required, >>18 beshort 20 PowerPC or cisco 4500, >>18 beshort 21 64-bit PowerPC or cisco 7500, >>18 beshort 22 IBM S/390, >>18 beshort 23 Cell SPU, >>18 beshort 24 cisco SVIP, >>18 beshort 25 cisco 7200, >>18 beshort 36 NEC V800 or cisco 12000, >>18 beshort 37 Fujitsu FR20, >>18 beshort 38 TRW RH-32, >>18 beshort 39 Motorola RCE, >>18 beshort 40 ARM, >>18 beshort 41 Alpha, >>18 beshort 42 Renesas SH, >>18 beshort 43 SPARC V9, >>>48 belong&0xffff00 0x000200 Sun UltraSPARC1 Extensions Required, >>>48 belong&0xffff00 0x000400 HaL R1 Extensions Required, >>>48 belong&0xffff00 0x000800 Sun UltraSPARC3 Extensions Required, >>>48 belong&0x3 0 total store ordering, >>>48 belong&0x3 1 partial store ordering, >>>48 belong&0x3 2 relaxed memory ordering, >>18 beshort 44 Siemens Tricore Embedded Processor, >>18 beshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 beshort 46 Renesas H8/300, >>18 beshort 47 Renesas H8/300H, >>18 beshort 48 Renesas H8S, >>18 beshort 49 Renesas H8/500, >>18 beshort 50 IA-64, >>18 beshort 51 Stanford MIPS-X, >>18 beshort 52 Motorola Coldfire, >>18 beshort 53 Motorola M68HC12, >>18 beshort 73 Cray NV1, >>18 beshort 75 Digital VAX, >>18 beshort 88 Renesas M32R, >>18 leshort 92 OpenRISC, >>18 leshort 0x3426 OpenRISC (obsolete), >>18 leshort 0x8472 OpenRISC (obsolete), >>18 beshort 94 Tensilica Xtensa, >>18 beshort 97 NatSemi 32k, >>18 beshort 0x18ad AVR32 (unofficial), >>18 beshort 0x9026 Alpha (unofficial), >>18 beshort 0xa390 IBM S/390 (obsolete), >>20 belong 0 invalid version >>20 belong 1 version 1 >>36 belong 1 MathCoPro/FPU/MAU Required # Up to now only 0, 1 and 2 are defined; I've seen a file with 0x83, it seemed # like proper ELF, but extracting the string had bad results. >4 byte <0x80 >>8 string >\0 (%s) >8 string \0 >>7 byte 0 (SYSV) >>7 byte 1 (HP-UX) >>7 byte 2 (NetBSD) >>7 byte 3 (GNU/Linux) >>7 byte 4 (GNU/Hurd) >>7 byte 5 (86Open) >>7 byte 6 (Solaris) >>7 byte 7 (Monterey) >>7 byte 8 (IRIX) >>7 byte 9 (FreeBSD) >>7 byte 10 (Tru64) >>7 byte 11 (Novell Modesto) >>7 byte 12 (OpenBSD) >8 string \2 >>7 byte 13 (OpenVMS) >>7 byte 97 (ARM) >>7 byte 255 (embedded) # XXX - according to Microsoft's spec, at an offset of 0x3c in a # PE-format executable is the offset in the file of the PE header; # unfortunately, that's a little-endian offset, and there's no way # to specify an indirect offset with a specified byte order. # So, for now, we assume the standard MS-DOS stub, which puts the # PE header at 0x80 = 128. # # Required OS version and subsystem version were 4.0 on some NT 3.51 # executables built with Visual C++ 4.0, so it's not clear that # they're interesting. The user version was 0.0, but there's # probably some linker directive to set it. The linker version was # 3.0, except for one ".exe" which had it as 4.20 (same damn linker!). # # many of the compressed formats were extraced from IDARC 1.23 source code # 0 string MZ !:mime application/x-dosexec >0x18 leshort <0x40 MS-DOS executable >0 string MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b, PE for MS Windows >>&18 leshort&0x2000 >0 (DLL) >>&88 leshort 0 (unknown subsystem) >>&88 leshort 1 (native) >>&88 leshort 2 (GUI) >>&88 leshort 3 (console) >>&88 leshort 7 (POSIX) >>&0 leshort 0x0 unknown processor >>&0 leshort 0x14c Intel 80386 >>&0 leshort 0x166 MIPS R4000 >>&0 leshort 0x184 Alpha >>&0 leshort 0x268 Motorola 68000 >>&0 leshort 0x1f0 PowerPC >>&0 leshort 0x290 PA-RISC >>&18 leshort&0x0100 >0 32-bit >>&18 leshort&0x1000 >0 system file >>&228 lelong >0 \b, Mono/.Net assembly >>&0xf4 search/0x140 \x0\x40\x1\x0 >>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive >30 string Copyright\ 1989-1990\ PKWARE\ Inc. Self-extracting PKZIP archive !:mime application/zip # Is next line correct? One might expect "Corp." not "Copr." If it is right, add a note to that effect. >30 string PKLITE\ Copr. Self-extracting PKZIP archive !:mime application/zip >0x18 leshort >0x3f >>(0x3c.l) string PE\0\0 PE >>>(0x3c.l+25) byte 1 \b32 executable >>>(0x3c.l+25) byte 2 \b32+ executable # hooray, there's a DOS extender using the PE format, with a valid PE # executable inside (which just prints a message and exits if run in win) >>>(0x3c.l+92) leshort <10 >>>>(8.s*16) string 32STUB for MS-DOS, 32rtm DOS extender >>>>(8.s*16) string !32STUB for MS Windows >>>>>(0x3c.l+22) leshort&0x2000 >0 (DLL) >>>>>(0x3c.l+92) leshort 0 (unknown subsystem) >>>>>(0x3c.l+92) leshort 1 (native) >>>>>(0x3c.l+92) leshort 2 (GUI) >>>>>(0x3c.l+92) leshort 3 (console) >>>>>(0x3c.l+92) leshort 7 (POSIX) >>>(0x3c.l+92) leshort 10 (EFI application) >>>(0x3c.l+92) leshort 11 (EFI boot service driver) >>>(0x3c.l+92) leshort 12 (EFI runtime driver) >>>(0x3c.l+92) leshort 13 (XBOX) >>>(0x3c.l+4) leshort 0x0 unknown processor >>>(0x3c.l+4) leshort 0x14c Intel 80386 >>>(0x3c.l+4) leshort 0x166 MIPS R4000 >>>(0x3c.l+4) leshort 0x184 Alpha >>>(0x3c.l+4) leshort 0x268 Motorola 68000 >>>(0x3c.l+4) leshort 0x1f0 PowerPC >>>(0x3c.l+4) leshort 0x290 PA-RISC >>>(0x3c.l+4) leshort 0x200 Intel Itanium >>>(0x3c.l+22) leshort&0x0100 >0 32-bit >>>(0x3c.l+22) leshort&0x1000 >0 system file >>>(0x3c.l+232) lelong >0 Mono/.Net assembly >>>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed >>>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed >>>>(0x3c.l+0xf8) search/0x140 UPX2 >>>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>(0x3c.l+0xf8) search/0x140 .idata >>>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive >>>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .rsrc >>>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive >>>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive >>>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive >>>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .data >>>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed >>>>>(0x3c.l+0xf7) byte x >>>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .reloc >>>>>(&0xe.l+(-4)) search/0x180 PK\3\4 \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive >>>>0x30 string Inno \b, InnoSetup self-extracting archive >>(0x3c.l) string !PE\0\0 MS-DOS executable >>(0x3c.l) string NE \b, NE >>>(0x3c.l+0x36) byte 0 (unknown OS) >>>(0x3c.l+0x36) byte 1 for OS/2 1.x >>>(0x3c.l+0x36) byte 2 for MS Windows 3.x >>>(0x3c.l+0x36) byte 3 for MS-DOS >>>(0x3c.l+0x36) byte >3 (unknown OS) >>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender >>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) >>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) >>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive >>>(0x3c.l+0x70) search/0x80 WinZip(R)\ Self-Extractor \b, ZIP self-extracting archive (WinZip) >>(0x3c.l) string LX\0\0 \b, LX >>>(0x3c.l+0x0a) leshort <1 (unknown OS) >>>(0x3c.l+0x0a) leshort 1 for OS/2 >>>(0x3c.l+0x0a) leshort 2 for MS Windows >>>(0x3c.l+0x0a) leshort 3 for DOS >>>(0x3c.l+0x0a) leshort >3 (unknown OS) >>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) >>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) >>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) >>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) >>>(0x3c.l+0x08) leshort 1 i80286 >>>(0x3c.l+0x08) leshort 2 i80386 >>>(0x3c.l+0x08) leshort 3 i80486 >>>(8.s*16) string emx \b, emx >>>>&1 string x %s >>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive #------------------------------------------------------------------------------ # bFLT: file(1) magic for BFLT uclinux binary files # # From Philippe De Muyter # # Additional fields added by Craig Heffner # 0 string bFLT BFLT executable >4 belong x version %ld, >4 belong 4 >8 belong x code offset: 0x%.8X, >12 belong x data segment starts at: 0x%.8X, >16 belong x bss segment starts at: 0x%.8X, >20 belong x bss segment ends at: 0x%.8X, >24 belong x stack size: %d bytes, >28 belong x relocation records start at: 0x%.8X, >32 belong x number of reolcation records: %d, >>36 belong&0x1 0x1 ram >>36 belong&0x2 0x2 gotpic >>36 belong&0x4 0x4 gzip >>36 belong&0x8 0x8 gzdata #----------------------------------------------------------------- # MIPS COFF file formats # 0 beshort 0x0160 MIPSEB ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0162 MIPSEL-BE ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x ^H.%ld # 0 beshort 0x6001 MIPSEB-LE ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x ^H.%ld # 0 beshort 0x6201 MIPSEL ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # MIPS 2 additions # 0 beshort 0x0163 MIPSEB MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0166 MIPSEL-BE MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x6301 MIPSEB-LE MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x6601 MIPSEL MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # MIPS 3 additions # 0 beshort 0x0140 MIPSEB MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0142 MIPSEL-BE MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x4001 MIPSEB-LE MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x4201 MIPSEL MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x180 MIPSEB Ucode 0 beshort 0x182 MIPSEL-BE Ucode # Windows CE package files 0 string MSCE\0\0\0\0 Microsoft WinCE installer >20 lelong 0 \b, architecture-independent >20 lelong 103 \b, Hitachi SH3 >20 lelong 104 \b, Hitachi SH4 >20 lelong 0xA11 \b, StrongARM >20 lelong 4000 \b, MIPS R4000 >20 lelong 10003 \b, Hitachi SH3 >20 lelong 10004 \b, Hitachi SH3E >20 lelong 10005 \b, Hitachi SH4 >20 lelong 70001 \b, ARM 7TDMI >52 leshort 1 \b, 1 file >52 leshort >1 \b, %u files >56 leshort 1 \b, 1 registry entry >56 leshort >1 \b, %u registry entries #------------------------------------------------------------------------------ # Microsoft Xbox executables .xbe (Esa Hyytiä ) 0 string XBEH XBE, Microsoft Xbox executable # probabilistic checks whether signed or not >0x0004 ulelong =0x0 >>&2 ulelong =0x0 >>>&2 ulelong =0x0 \b, not signed >0x0004 ulelong >0 >>&2 ulelong >0 >>>&2 ulelong >0 \b, signed # expect base address of 0x10000 >0x0104 ulelong =0x10000 >>(0x0118-0x0FF60) ulelong&0x80000007 0x80000007 \b, all regions >>(0x0118-0x0FF60) ulelong&0x80000007 !0x80000007 >>>(0x0118-0x0FF60) ulelong >0 (regions: >>>>(0x0118-0x0FF60) ulelong &0x00000001 NA >>>>(0x0118-0x0FF60) ulelong &0x00000002 Japan >>>>(0x0118-0x0FF60) ulelong &0x00000004 Rest_of_World >>>>(0x0118-0x0FF60) ulelong &0x80000000 Manufacturer >>>(0x0118-0x0FF60) ulelong >0 \b) #------------------------------------------------------------------------------ # motorola: file(1) magic for Motorola 68K and 88K binaries # # 68K # 0 beshort 0x0208 mc68k COFF >18 beshort ^00000020 object >18 beshort &00000020 executable >12 belong >0 not stripped >168 string .lowmem Apple toolbox >20 beshort 0407 (impure) >20 beshort 0410 (pure) >20 beshort 0413 (demand paged) >20 beshort 0421 (standalone) 0 beshort 0x0209 mc68k executable (shared) >12 belong >0 not stripped 0 beshort 0x020A mc68k executable (shared demand paged) >12 belong >0 not stripped # # Motorola/UniSoft 68K Binary Compatibility Standard (BCS) # 0 beshort 0x022A 68K BCS executable # # 88K # # Motorola/88Open BCS # 0 beshort 0x022B 88K BCS executable #------------------------------------------------------------------------------ # Sony Playstation executables (Adam Sjoegren ) : 0 string PS-X\ EXE Sony Playstation executable # Area: >113 string x (%s) #------------------------------------------------------------------------------ # cisco: file(1) magic for cisco Systems routers # # Most cisco file-formats are covered by the generic elf code # # Microcode files are non-ELF, 0x8501 conflicts with NetBSD/alpha. 0 beshort 0x8501 cisco IOS >0 belong&0xffffff00 0x85011400 microcode >0 belong&0xffffff00 0x8501cb00 experimental microcode >7 string >\0 for '%s' ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.filesystems ================================================ #--------------------File Systems--------------------- # Minix filesystems - Juan Cespedes # Disabled for now until better signatures can be created. Too many false positives. #0x410 leshort 0x137f Minix filesystem #>0x402 beshort !0 \b, %d zones #>0x1e string minix \b, bootable #0x410 leshort 0x138f Minix filesystem, 30 char names #0x410 leshort 0x2468 Minix filesystem, version 2 #0x410 leshort 0x2478 Minix filesystem, version 2, 30 char names #0x410 beshort 0x137f Minix filesystem (big endian) #>0x402 beshort !0 \b, %d zones #>0x1e string minix \b, bootable #0x410 beshort 0x138f Minix filesystem (big endian), 30 char names #0x410 beshort 0x2468 Minix filesystem (big endian), version 2 #0x410 beshort 0x2478 Minix filesystem (big endian), version 2, 30 char names # YAFFS 0 belong 0x03000000 >4 belong 0x01000000 >>8 beshort 0xFFFF YAFFS filesystem # EFS2 file system - jojo@utulsa.edu 8 string EFSSuper EFS2 Qualcomm filesystem super block, >0 lelong 0x53000000 little endian, >>4 leshort &1 NAND >>4 leshort ^1 NOR >>4 leshort x version 0x%x, >>24 lelong x %d blocks, >>16 lelong x 0x%x pages per block, >>20 lelong x 0x%x bytes per page 8 string SSFErepu EFS2 Qualcomm filesystem super block, >0 belong 0x53000000 big endian, >>4 beshort &1 NAND >>4 beshort ^1 NOR >>4 beshort x version 0x%x, >>24 belong x %d blocks, >>16 belong x 0x%x pages per block, >>20 belong x 0x%x bytes per page # TROC file system 0 string TROC TROC filesystem, >4 lelong x %d file entries # PFS file system 0 string PFS/ PFS filesystem, >4 string x version %s, >14 leshort x %d files # MPFS file system 0 string MPFS MPFS (Microchip) filesystem, >4 byte x version %d. >5 byte x \b%d, >6 leshort x %d file entries # cramfs filesystem - russell@coker.com.au 0 lelong 0x28cd3d45 CramFS filesystem, little endian >4 lelong <0 invalid >4 lelong x size %lu >8 lelong &1 version #2 >8 lelong &2 sorted_dirs >8 lelong &4 hole_support >32 lelong x CRC 0x%x, >36 lelong x edition %lu, >40 lelong <0 invalid >40 lelong x %lu blocks, >44 lelong <0 invalid >44 lelong x %lu files 0 belong 0x28cd3d45 CramFS filesystem, big endian >4 belong <0 invalid >4 belong x size %lu >8 belong &1 version #2 >8 belong &2 sorted_dirs >8 belong &4 hole_support >32 belong x CRC 0x%x, >36 belong x edition %lu, >40 belong <0 invalid >40 belong x %lu blocks, >44 belong <0 invalid >44 belong x %lu files # JFFS2 file system 0 leshort 0x1984 JFFS2 filesystem (old) data little endian, >4 lelong >1000000 invalid >4 lelong <0 invalid >4 lelong 0 invalid >4 lelong x JFFS node length: %d 0 beshort 0x1984 JFFS2 filesystem (old) data big endian, >4 belong >1000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x JFFS node length: %d 0 leshort 0x1985 JFFS2 filesystem data little endian, >4 lelong >1000000 invalid >4 lelong <0 invalid >4 lelong 0 invalid >4 lelong x JFFS node length: %d 0 beshort 0x1985 JFFS2 filesystem data big endian, >4 belong >1000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x JFFS node length: %d # Squashfs 0 string sqsh Squashfs filesystem, big endian, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort 3 >>63 bequad x size: %lld bytes, >28 beshort >3 >>40 bequad x size: %lld bytes, >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s 0 string hsqs Squashfs filesystem, little endian, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort 3 >>63 lequad x size: %lld bytes, >28 leshort >3 >>40 lequad x size: %lld bytes, >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s # Squashfs with LZMA compression 0 string sqlz Squashfs filesystem, big endian, lzma compression, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs 3.3 LZMA signature 0 string qshs Squashfs filesystem, big endian, lzma signature, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs for DD-WRT 0 string tqsh Squashfs filesystem, big endian, DD-WRT signature, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs for DD-WRT 0 string hsqt Squashfs filesystem, little endian, DD-WRT signature, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort >2 >>63 lequad x size: %lld bytes, #>>63 lelong x %d bytes, >4 lelong x %d inodes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort >1 >>51 lelong x blocksize: %d bytes, >39 ledate x created: %s # Non-standard Squashfs signature found on some D-Link routers 0 string shsq Squashfs filesystem, little endian, non-standard signature, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort >2 >>63 lequad x size: %lld bytes, #>>63 lelong x %d bytes, >4 lelong x %d inodes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort >1 >>51 lelong x blocksize: %d bytes, >39 ledate x created: %s # Commented out for now - unlikely to be found in firmware # CDROM Filesystems # Modified for UDF by gerardo.cacciari@gmail.com #32769 string CD001 # #!:mime application/x-iso9660-image #>38913 string !NSR0 ISO 9660 CD-ROM filesystem data #>38913 string NSR0 UDF filesystem data #>>38917 string 1 (version 1.0) #>>38917 string 2 (version 1.5) #>>38917 string 3 (version 2.0) #>>38917 byte >0x33 (unknown version, ID 0x%X) #>>38917 byte <0x31 (unknown version, ID 0x%X) # "application id" which appears to be used as a volume label #>32808 string >\0 '%s' #>34816 string \000CD001\001EL\ TORITO\ SPECIFICATION (bootable) #37633 string CD001 ISO 9660 CD-ROM filesystem data (raw 2352 byte sectors) #!:mime application/x-iso9660-image #32776 string CDROM High Sierra CD-ROM filesystem data # reiserfs - russell@coker.com.au 0x10034 string ReIsErFs ReiserFS filesystem V3.5 0x10034 string ReIsEr2Fs ReiserFS filesystem V3.6 0x10034 string ReIsEr3Fs ReiserFS filesystem V3.6.19 >0x1002c leshort x block size %d >0x10032 leshort &2 (mounted or unclean) >0x10000 lelong x num blocks %d >0x10040 lelong 1 tea hash >0x10040 lelong 2 yura hash >0x10040 lelong 3 r5 hash # ext2/ext3 filesystems - Andreas Dilger # ext4 filesystem - Eric Sandeen # volume label and UUID Russell Coker # http://etbe.coker.com.au/2008/07/08/label-vs-uuid-vs-device/ 0x438 leshort 0xEF53 Linux EXT filesystem >0x44c lelong <0 invalid >0x44c lelong >4 invalid >0x44c lelong x rev %d >0x43e leshort x \b.%d # No journal? ext2 >0x45c lelong ^0x0000004 ext2 filesystem data >>0x43a leshort ^0x0000001 (mounted or unclean) # Has a journal? ext3 or ext4 >0x45c lelong &0x0000004 # and small INCOMPAT? >>0x460 lelong <0x0000040 # and small RO_COMPAT? >>>0x464 lelong <0x0000008 ext3 filesystem data # else large RO_COMPAT? >>>0x464 lelong >0x0000007 ext4 filesystem data # else large INCOMPAT? >>0x460 lelong >0x000003f ext4 filesystem data >0x468 belong x \b, UUID=%08x >0x46c beshort x \b-%04x >0x46e beshort x \b-%04x >0x470 beshort x \b-%04x >0x472 belong x \b-%08x >0x476 beshort x \b%04x >0x478 string >0 \b, volume name "%s" # General flags for any ext* fs >0x460 lelong &0x0000004 (needs journal recovery) >0x43a leshort &0x0000002 (errors, invalid) # INCOMPAT flags >0x460 lelong &0x0000001 (compressed) #>0x460 lelong &0x0000002 (filetype) #>0x460 lelong &0x0000010 (meta bg) >0x460 lelong &0x0000040 (extents) >0x460 lelong &0x0000080 (64bit) #>0x460 lelong &0x0000100 (mmp) #>0x460 lelong &0x0000200 (flex bg) # RO_INCOMPAT flags #>0x464 lelong &0x0000001 (sparse super) >0x464 lelong &0x0000002 (large files) >0x464 lelong &0x0000008 (huge files) #>0x464 lelong &0x0000010 (gdt checksum) #romfs filesystems - Juan Cespedes 0 string -rom1fs- romfs filesystem, version 1 >8 belong >10000000 invalid >8 belong x size: %d bytes, >16 string x named %s. # JFFS - russell@coker.com.au 0 lelong 0x34383931 Linux Journalled Flash filesystem, little endian 0 belong 0x34383931 Linux Journalled Flash filesystem, big endian # Wind River MemFS file system, found in some VxWorks devices 0 string owowowowowowowowowowowowowowow Wind River management filesystem, >32 belong 0 uncompressed >32 belong 1 compressed, >36 belong x %d files # FATX 0 string FATX FATX filesystem data # updated by Joerg Jenderek at Sep 2007 # only for sector sizes with 512 or more Bytes 0x1FE leshort 0xAA55 start boot sector # to do also for sectors < than 512 Bytes and some other files, GRR #30 search/481 \x55\xAA start boot sector / filesystem # not for BeOS floppy 1440k, MBRs #(11.s-2) uleshort 0xAA55 start boot sector / filesystem >2 string OSBS \b, OS/BS MBR # J\xf6rg Jenderek >0x8C string Invalid\ partition\ table \b, MS-DOS MBR # dr-dos with some upper-, lowercase variants >0x9D string Invalid\ partition\ table$ >>181 string No\ Operating\ System$ >>>201 string Operating\ System\ load\ error$ \b, DR-DOS MBR, Version 7.01 to 7.03 >0x9D string Invalid\ partition\ table$ >>181 string No\ operating\ system$ >>>201 string Operating\ system\ load\ error$ \b, DR-DOS MBR, Version 7.01 to 7.03 >342 string Invalid\ partition\ table$ >>366 string No\ operating\ system$ >>>386 string Operating\ system\ load\ error$ \b, DR-DOS MBR, version 7.01 to 7.03 >295 string NEWLDR\0 >>302 string Bad\ PT\ $ >>>310 string No\ OS\ $ >>>>317 string OS\ load\ err$ >>>>>329 string Moved\ or\ missing\ IBMBIO.LDR\n\r >>>>>>358 string Press\ any\ key\ to\ continue.\n\r$ >>>>>>>387 string Copyright\ (c)\ 1984,1998 >>>>>>>>411 string Caldera\ Inc.\0 \b, DR-DOS MBR (IBMBIO.LDR) >0x10F string Ung\201ltige\ Partitionstabelle \b, MS-DOS MBR, german version 4.10.1998, 4.10.2222 >>0x1B8 ubelong >0 \b, Serial 0x%-.4x >0x8B string Ung\201ltige\ Partitionstabelle \b, MS-DOS MBR, german version 5.00 to 4.00.950 >271 string Invalid\ partition\ table\0 >>295 string Error\ loading\ operating\ system\0 >>>326 string Missing\ operating\ system\0 \b, mbr # >139 string Invalid\ partition\ table\0 >>163 string Error\ loading\ operating\ system\0 >>>194 string Missing\ operating\ system\0 \b, Microsoft Windows XP mbr # http://www.heise.de/ct/05/09/006/ page 184 #HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices\DosDevices\?:=Serial4Bytes+8Bytes >>>>0x1B8 ulelong >0 \b,Serial 0x%-.4x >300 string Invalid\ partition\ table\0 >>324 string Error\ loading\ operating\ system\0 >>>355 string Missing\ operating\ system\0 \b, Microsoft Windows XP MBR #??>>>389 string Invalid\ system\ disk >>>>0x1B8 ulelong >0 \b, Serial 0x%-.4x >300 string Ung\201ltige\ Partitionstabelle #split string to avoid error: String too long >>328 string Fehler\ beim\ Laden\ >>>346 string des\ Betriebssystems >>>>366 string Betriebssystem\ nicht\ vorhanden \b, Microsoft Windows XP MBR (german) >>>>>0x1B8 ulelong >0 \b, Serial 0x%-.4x #>0x145 string Default:\ F \b, FREE-DOS MBR #>0x14B string Default:\ F \b, FREE-DOS 1.0 MBR >0x145 search/7 Default:\ F \b, FREE-DOS MBR #>>313 string F0\ .\ .\ . #>>>322 string disk\ 1 #>>>>382 string FAT3 >64 string no\ active\ partition\ found >>96 string read\ error\ while\ reading\ drive \b, FREE-DOS Beta 0.9 MBR # Ranish Partition Manager http://www.ranish.com/part/ >387 search/4 \0\ Error!\r >>378 search/7 Virus! >>>397 search/4 Booting\ >>>>408 search/4 HD1/\0 \b, Ranish MBR ( >>>>>416 string Writing\ changes... \b2.37 >>>>>>438 ubyte x \b,0x%x dots >>>>>>440 ubyte >0 \b,virus check >>>>>>441 ubyte >0 \b,partition %c #2.38,2.42,2.44 >>>>>416 string !Writing\ changes... \b >>>>>>418 ubyte 1 \bvirus check, >>>>>>419 ubyte x \b0x%x seconds >>>>>>420 ubyte&0x0F >0 \b,partition >>>>>>>420 ubyte&0x0F <5 \b %x >>>>>>>420 ubyte&0x0F 0Xf \b ask >>>>>420 ubyte x \b) # >271 string Operating\ system\ loading >>296 string error\r \b, SYSLINUX MBR (2.10) # http://www.acronis.de/ >362 string MBR\ Error\ \0\r >>376 string ress\ any\ key\ to\ >>>392 string boot\ from\ floppy...\0 \b, Acronis MBR # added by Joerg Jenderek # http://www.visopsys.org/ # http://partitionlogic.org.uk/ >309 string No\ bootable\ partition\ found\r >>339 string I/O\ Error\ reading\ boot\ sector\r \b, Visopsys MBR >349 string No\ bootable\ partition\ found\r >>379 string I/O\ Error\ reading\ boot\ sector\r \b, simple Visopsys MBR # bootloader, bootmanager >0x40 string SBML # label with 11 characters of FAT 12 bit filesystem >>43 string SMART\ BTMGR >>>430 string SBMK\ Bad!\r \b, Smart Boot Manager # OEM-ID not always "SBM" #>>>>3 strings SBM >>>>6 string >\0 \b, version %s >382 string XOSLLOADXCF \b, eXtended Operating System Loader >6 string LILO \b, LInux i386 boot LOader >>120 string LILO \b, version 22.3.4 SuSe >>172 string LILO \b, version 22.5.8 Debian # updated by Joerg Jenderek at Oct 2008 # variables according to grub-0.97/stage1/stage1.S or # http://www.gnu.org/software/grub/manual/grub.html#Embedded-data # usual values are marked with comments to get only informations of strange GRUB loaders >342 search/60 \0Geom\0 #>0 ulelong x %x=0x009048EB , 0x2a9048EB 0 >>0x41 ubyte <2 >>>0x3E ubyte >2 \b; GRand Unified Bootloader # 0x3 for 0.5.95,0.93,0.94,0.96 0x4 for 1.90 >>>>0x3E ubyte x \b, stage1 version 0x%x #If it is 0xFF, use a drive passed by BIOS >>>>0x40 ubyte <0xFF \b, boot drive 0x%x # in most case 0,1,0x2e for GRUB 0.5.95 >>>>0x41 ubyte >0 \b, LBA flag 0x%x >>>>0x42 uleshort <0x8000 \b, stage2 address 0x%x #>>>>0x42 uleshort =0x8000 \b, stage2 address 0x%x (usual) >>>>0x42 uleshort >0x8000 \b, stage2 address 0x%x #>>>>0x44 ulelong =1 \b, 1st sector stage2 0x%x (default) >>>>0x44 ulelong >1 \b, 1st sector stage2 0x%x >>>>0x48 uleshort <0x800 \b, stage2 segment 0x%x #>>>>0x48 uleshort =0x800 \b, stage2 segment 0x%x (usual) >>>>0x48 uleshort >0x800 \b, stage2 segment 0x%x >>>>402 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>394 string stage1 \b, GRUB version 0.5.95 >>>>382 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>376 string GRUB\ \0 \b, GRUB version 0.93 or 1.94 >>>>383 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>377 string GRUB\ \0 \b, GRUB version 0.94 >>>>385 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>379 string GRUB\ \0 \b, GRUB version 0.95 or 0.96 >>>>391 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>385 string GRUB\ \0 \b, GRUB version 0.97 #unkown version >>>343 string Geom\0Read\0\ Error\0 >>>>321 string Loading\ stage1.5 \b, GRUB version x.y >>>380 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>374 string GRUB\ \0 \b, GRUB version n.m # http://syslinux.zytor.com/ >478 string Boot\ failed\r >>495 string LDLINUX\ SYS \b, SYSLINUX bootloader (1.62) >480 string Boot\ failed\r >>495 string LDLINUX\ SYS \b, SYSLINUX bootloader (2.06 or 2.11) >484 string Boot\ error\r \b, SYSLINUX bootloader (3.11) >395 string chksum\0\ ERROR!\0 \b, Gujin bootloader # http://www.bcdwb.de/bcdw/index_e.htm >3 string BCDL >>498 string BCDL\ \ \ \ BIN \b, Bootable CD Loader (1.50Z) # mbr partion table entries # OEM-ID does not contain MicroSoft,NEWLDR,DOS,SYSLINUX,or MTOOLs >3 string !MS >>3 string !SYSLINUX >>>3 string !MTOOL >>>>3 string !NEWLDR >>>>>5 string !DOS # not FAT (32 bit) >>>>>>82 string !FAT32 #not Linux kernel >>>>>>>514 string !HdrS #not BeOS >>>>>>>>422 string !Be\ Boot\ Loader # active flag 0 or 0x80 and type > 0 >>>>>>>>>446 ubyte <0x81 >>>>>>>>>>446 ubyte&0x7F 0 >>>>>>>>>>>450 ubyte >0 \b; partition 1: ID=0x%x >>>>>>>>>>>>446 ubyte 0x80 \b, active >>>>>>>>>>>>447 ubyte x \b, starthead %u #>>>>>>>>>>>>448 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>448 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>454 ulelong x \b, startsector %u >>>>>>>>>>>>458 ulelong x \b, %u sectors # >>>>>>>>>462 ubyte <0x81 >>>>>>>>>>462 ubyte&0x7F 0 >>>>>>>>>>>466 ubyte >0 \b; partition 2: ID=0x%x >>>>>>>>>>>>462 ubyte 0x80 \b, active >>>>>>>>>>>>463 ubyte x \b, starthead %u #>>>>>>>>>>>>464 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>464 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>470 ulelong x \b, startsector %u >>>>>>>>>>>>474 ulelong x \b, %u sectors # >>>>>>>>>478 ubyte <0x81 >>>>>>>>>>478 ubyte&0x7F 0 >>>>>>>>>>>482 ubyte >0 \b; partition 3: ID=0x%x >>>>>>>>>>>>478 ubyte 0x80 \b, active >>>>>>>>>>>>479 ubyte x \b, starthead %u #>>>>>>>>>>>>480 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>481 ubyte x \b, start C2S: 0x%x #>>>>>>>>>>>>480 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>486 ulelong x \b, startsector %u >>>>>>>>>>>>490 ulelong x \b, %u sectors # >>>>>>>>>494 ubyte <0x81 >>>>>>>>>>494 ubyte&0x7F 0 >>>>>>>>>>>498 ubyte >0 \b; partition 4: ID=0x%x >>>>>>>>>>>>494 ubyte 0x80 \b, active >>>>>>>>>>>>495 ubyte x \b, starthead %u #>>>>>>>>>>>>496 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>496 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>502 ulelong x \b, startsector %u >>>>>>>>>>>>506 ulelong x \b, %u sectors # mbr partion table entries end # http://www.acronis.de/ #FAT label=ACRONIS\ SZ #OEM-ID=BOOTWIZ0 >442 string Non-system\ disk,\ >>459 string press\ any\ key...\x7\0 \b, Acronis Startup Recovery Loader # DOS names like F11.SYS are 8 right space padded bytes+3 bytes >>>477 ubyte&0xDF >0 >>>>477 string x \b %-.3s >>>>>480 ubyte&0xDF >0 >>>>>>480 string x \b%-.5s >>>>485 ubyte&0xDF >0 >>>>>485 string x \b.%-.3s # >185 string FDBOOT\ Version\ >>204 string \rNo\ Systemdisk.\ >>>220 string Booting\ from\ harddisk.\n\r >>>245 string Cannot\ load\ from\ harddisk.\n\r >>>>273 string Insert\ Systemdisk\ >>>>>291 string and\ press\ any\ key.\n\r \b, FDBOOT harddisk Bootloader >>>>>>200 string >\0 \b, version %-3s >242 string Bootsector\ from\ C.H.\ Hochst\204 >>278 string No\ Systemdisk.\ >>>293 string Booting\ from\ harddisk.\n\r >>>441 string Cannot\ load\ from\ harddisk.\n\r >>>>469 string Insert\ Systemdisk\ >>>>>487 string and\ press\ any\ key.\n\r \b, WinImage harddisk Bootloader >>>>>>209 string >\0 \b, version %-4.4s >(1.b+2) ubyte 0xe >>(1.b+3) ubyte 0x1f >>>(1.b+4) ubyte 0xbe >>>>(1.b+5) ubyte 0x77 >>>>(1.b+6) ubyte 0x7c >>>>>(1.b+7) ubyte 0xac >>>>>>(1.b+8) ubyte 0x22 >>>>>>>(1.b+9) ubyte 0xc0 >>>>>>>>(1.b+10) ubyte 0x74 >>>>>>>>>(1.b+11) ubyte 0xb >>>>>>>>>>(1.b+12) ubyte 0x56 >>>>>>>>>>(1.b+13) ubyte 0xb4 \b, mkdosfs boot message display >214 string Please\ try\ to\ install\ FreeDOS\ \b, DOS Emulator boot message display #>>244 string from\ dosemu-freedos-*-bin.tgz\r #>>>170 string Sorry,\ could\ not\ load\ an\ #>>>>195 string operating\ system.\r\n # >103 string This\ is\ not\ a\ bootable\ disk.\ >>132 string Please\ insert\ a\ bootable\ >>>157 string floppy\ and\r\n >>>>169 string press\ any\ key\ to\ try\ again...\r \b, FREE-DOS message display # >66 string Solaris\ Boot\ Sector >>99 string Incomplete\ MDBoot\ load. >>>89 string Version \b, Sun Solaris Bootloader >>>>97 byte x version %c # >408 string OS/2\ !!\ SYS01475\r\0 >>429 string OS/2\ !!\ SYS02025\r\0 >>>450 string OS/2\ !!\ SYS02027\r\0 >>>469 string OS2BOOT\ \ \ \ \b, IBM OS/2 Warp bootloader # >409 string OS/2\ !!\ SYS01475\r\0 >>430 string OS/2\ !!\ SYS02025\r\0 >>>451 string OS/2\ !!\ SYS02027\r\0 >>>470 string OS2BOOT\ \ \ \ \b, IBM OS/2 Warp Bootloader >112 string This\ disk\ is\ not\ bootable\r >>142 string If\ you\ wish\ to\ make\ it\ bootable >>>176 string run\ the\ DOS\ program\ SYS\ >>>200 string after\ the\r >>>>216 string system\ has\ been\ loaded\r\n >>>>>242 string Please\ insert\ a\ DOS\ diskette\ >>>>>271 string into\r\n\ the\ drive\ and\ >>>>>>292 string strike\ any\ key...\0 \b, IBM OS/2 Warp message display # XP >430 string NTLDR\ is\ missing\xFF\r\n >>449 string Disk\ error\xFF\r\n >>>462 string Press\ any\ key\ to\ restart\r \b, Microsoft Windows XP Bootloader # DOS names like NTLDR,CMLDR,$LDR$ are 8 right space padded bytes+3 bytes >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # >430 string NTLDR\ nicht\ gefunden\xFF\r\n >>453 string Datentr\204gerfehler\xFF\r\n >>>473 string Neustart\ mit\ beliebiger\ Taste\r \b, Microsoft Windows XP Bootloader (german) >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # offset variant >>>>379 string \0 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s # >430 string NTLDR\ fehlt\xFF\r\n >>444 string Datentr\204gerfehler\xFF\r\n >>>464 string Neustart\ mit\ beliebiger\ Taste\r \b, Microsoft Windows XP Bootloader (2.german) >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # variant >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # >430 string NTLDR\ fehlt\xFF\r\n >>444 string Medienfehler\xFF\r\n >>>459 string Neustart:\ Taste\ dr\201cken\r \b, Microsoft Windows XP Bootloader (3.german) >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # variant >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # >430 string Datentr\204ger\ entfernen\xFF\r\n >>454 string Medienfehler\xFF\r\n >>>469 string Neustart:\ Taste\ dr\201cken\r \b, Microsoft Windows XP Bootloader (4.german) >>>>379 string \0 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # variant >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # #>3 string NTFS\ \ \ \ >389 string Fehler\ beim\ Lesen\ >>407 string des\ Datentr\204gers >>>426 string NTLDR\ fehlt >>>>440 string NTLDR\ ist\ komprimiert >>>>>464 string Neustart\ mit\ Strg+Alt+Entf\r \b, Microsoft Windows XP Bootloader NTFS (german) #>3 string NTFS\ \ \ \ >313 string A\ disk\ read\ error\ occurred.\r >>345 string A\ kernel\ file\ is\ missing\ >>>370 string from\ the\ disk.\r >>>>484 string NTLDR\ is\ compressed >>>>>429 string Insert\ a\ system\ diskette\ >>>>>>454 string and\ restart\r\nthe\ system.\r \b, Microsoft Windows XP Bootloader NTFS # DOS loader variants different languages,offsets >472 ubyte&0xDF >0 >>389 string Invalid\ system\ disk\xFF\r\n >>>411 string Disk\ I/O\ error >>>>428 string Replace\ the\ disk,\ and\ >>>>>455 string press\ any\ key \b, Microsoft Windows 98 Bootloader #IO.SYS >>>>>>472 ubyte&0xDF >0 >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.5s >>>>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>>>479 string x \b%-.1s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>390 string Invalid\ system\ disk\xFF\r\n >>>412 string Disk\ I/O\ error\xFF\r\n >>>>429 string Replace\ the\ disk,\ and\ >>>>>451 string then\ press\ any\ key\r \b, Microsoft Windows 98 Bootloader >>388 string Ungueltiges\ System\ \xFF\r\n >>>410 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>427 string Datentraeger\ wechseln\ und\ >>>>>453 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (german) #WINBOOT.SYS only not spaces (0xDF) >>>>>>497 ubyte&0xDF >0 >>>>>>>497 string x %-.5s >>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>502 string x \b%-.1s >>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>504 string x \b%-.1s >>>>>>505 ubyte&0xDF >0 >>>>>>>505 string x \b.%-.3s #IO.SYS >>>>>>472 ubyte&0xDF >0 or >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.5s >>>>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>>>479 string x \b%-.1s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>390 string Ungueltiges\ System\ \xFF\r\n >>>412 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>429 string Datentraeger\ wechseln\ und\ >>>>>455 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (German) #WINBOOT.SYS only not spaces (0xDF) >>>>>>497 ubyte&0xDF >0 >>>>>>>497 string x %-.7s >>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>504 string x \b%-.1s >>>>>>505 ubyte&0xDF >0 >>>>>>>505 string x \b.%-.3s #IO.SYS >>>>>>472 ubyte&0xDF >0 or >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.6s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>389 string Ungueltiges\ System\ \xFF\r\n >>>411 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>428 string Datentraeger\ wechseln\ und\ >>>>>454 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (GERMAN) # DOS names like IO.SYS,WINBOOT.SYS,MSDOS.SYS,WINBOOT.INI are 8 right space padded bytes+3 bytes >>>>>>472 string x %-.2s >>>>>>>474 ubyte&0xDF >0 >>>>>>>>474 string x \b%-.5s >>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>479 string x \b%-.1s >>>>>>480 ubyte&0xDF >0 >>>>>>>480 string x \b.%-.3s >>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>483 string x \b%-.5s >>>>>>>488 ubyte&0xDF >0 >>>>>>>>488 string x \b%-.2s >>>>>>>>490 ubyte&0xDF >0 >>>>>>>>>490 string x \b%-.1s >>>>>>>491 ubyte&0xDF >0 >>>>>>>>491 string x \b.%-.3s >479 ubyte&0xDF >0 >>416 string Kein\ System\ oder\ >>>433 string Laufwerksfehler >>>>450 string Wechseln\ und\ Taste\ dr\201cken \b, Microsoft DOS Bootloader (german) #IO.SYS >>>>>479 string x \b %-.2s >>>>>>481 ubyte&0xDF >0 >>>>>>>481 string x \b%-.6s >>>>>487 ubyte&0xDF >0 >>>>>>487 string x \b.%-.3s #MSDOS.SYS >>>>>>490 ubyte&0xDF >0 \b+ >>>>>>>490 string x \b%-.5s >>>>>>>>495 ubyte&0xDF >0 >>>>>>>>>495 string x \b%-.3s >>>>>>>498 ubyte&0xDF >0 >>>>>>>>498 string x \b.%-.3s # >376 search/41 Non-System\ disk\ or\ >>395 search/41 disk\ error\r >>>407 search/41 Replace\ and\ >>>>419 search/41 press\ \b, >>>>419 search/41 strike\ \b, old >>>>426 search/41 any\ key\ when\ ready\r MS or PC-DOS bootloader #449 Disk\ Boot\ failure\r MS 3.21 #466 Boot\ Failure\r MS 3.30 >>>>>468 search/18 \0 #IO.SYS,IBMBIO.COM >>>>>>&0 string x \b %-.2s >>>>>>>&-20 ubyte&0xDF >0 >>>>>>>>&-1 string x \b%-.4s >>>>>>>>>&-16 ubyte&0xDF >0 >>>>>>>>>>&-1 string x \b%-.2s >>>>>>&8 ubyte&0xDF >0 \b. >>>>>>>&-1 string x \b%-.3s #MSDOS.SYS,IBMDOS.COM >>>>>>&11 ubyte&0xDF >0 \b+ >>>>>>>&-1 string x \b%-.5s >>>>>>>>&-6 ubyte&0xDF >0 >>>>>>>>>&-1 string x \b%-.1s >>>>>>>>>>&-5 ubyte&0xDF >0 >>>>>>>>>>>&-1 string x \b%-.2s >>>>>>>&7 ubyte&0xDF >0 \b. >>>>>>>>&-1 string x \b%-.3s >441 string Cannot\ load\ from\ harddisk.\n\r >>469 string Insert\ Systemdisk\ >>>487 string and\ press\ any\ key.\n\r \b, MS (2.11) DOS bootloader #>43 string \224R-LOADER\ \ SYS =label >54 string SYS >>324 string VASKK >>>495 string NEWLDR\0 \b, DR-DOS Bootloader (LOADER.SYS) # >98 string Press\ a\ key\ to\ retry\0\r >>120 string Cannot\ find\ file\ \0\r >>>139 string Disk\ read\ error\0\r >>>>156 string Loading\ ...\0 \b, DR-DOS (3.41) Bootloader #DRBIOS.SYS >>>>>44 ubyte&0xDF >0 >>>>>>44 string x \b %-.6s >>>>>>>50 ubyte&0xDF >0 >>>>>>>>50 string x \b%-.2s >>>>>>52 ubyte&0xDF >0 >>>>>>>52 string x \b.%-.3s # >70 string IBMBIO\ \ COM >>472 string Cannot\ load\ DOS!\ >>>489 string Any\ key\ to\ retry \b, DR-DOS Bootloader >>471 string Cannot\ load\ DOS\ >>487 string press\ key\ to\ retry \b, Open-DOS Bootloader #?? >444 string KERNEL\ \ SYS >>314 string BOOT\ error! \b, FREE-DOS Bootloader >499 string KERNEL\ \ SYS >>305 string BOOT\ err!\0 \b, Free-DOS Bootloader >449 string KERNEL\ \ SYS >>319 string BOOT\ error! \b, FREE-DOS 0.5 Bootloader # >449 string Loading\ FreeDOS >>0x1AF ulelong >0 \b, FREE-DOS 0.95,1.0 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s # >331 string Error!.0 \b, FREE-DOS 1.0 bootloader # >125 string Loading\ FreeDOS...\r >>311 string BOOT\ error!\r \b, FREE-DOS bootloader >>>441 ubyte&0xDF >0 >>>>441 string x \b %-.6s >>>>>447 ubyte&0xDF >0 >>>>>>447 string x \b%-.1s >>>>>>>448 ubyte&0xDF >0 >>>>>>>>448 string x \b%-.1s >>>>449 ubyte&0xDF >0 >>>>>449 string x \b.%-.3s >124 string FreeDOS\0 >>331 string \ err\0 \b, FREE-DOS BETa 0.9 Bootloader # DOS names like KERNEL.SYS,KERNEL16.SYS,KERNEL32.SYS,METAKERN.SYS are 8 right space padded bytes+3 bytes >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >>333 string \ err\0 \b, FREE-DOS BEta 0.9 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >>334 string \ err\0 \b, FREE-DOS Beta 0.9 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >336 string Error!\ >>343 string Hit\ a\ key\ to\ reboot. \b, FREE-DOS Beta 0.9sr1 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s # added by Joerg Jenderek # http://www.visopsys.org/ # http://partitionlogic.org.uk/ # OEM-ID=Visopsys >478 ulelong 0 >>(1.b+326) string I/O\ Error\ reading\ >>>(1.b+344) string Visopsys\ loader\r >>>>(1.b+361) string Press\ any\ key\ to\ continue.\r \b, Visopsys loader # http://alexfru.chat.ru/epm.html#bootprog >494 ubyte >0x4D >>495 string >E >>>495 string >>>3 string BootProg # It just looks for a program file name at the root directory # and loads corresponding file with following execution. # DOS names like STARTUP.BIN,STARTUPC.COM,STARTUPE.EXE are 8 right space padded bytes+3 bytes >>>>499 ubyte&0xDF >0 \b, COM/EXE Bootloader >>>>>499 string x \b %-.1s >>>>>>500 ubyte&0xDF >0 >>>>>>>500 string x \b%-.1s >>>>>>>>501 ubyte&0xDF >0 >>>>>>>>>501 string x \b%-.1s >>>>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>>>502 string x \b%-.1s >>>>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>>>504 string x \b%-.1s >>>>>>>>>>>>>>>>505 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>505 string x \b%-.1s >>>>>>>>>>>>>>>>>>506 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>>>506 string x \b%-.1s #name extension >>>>>507 ubyte&0xDF >0 \b. >>>>>>507 string x \b%-.1s >>>>>>>508 ubyte&0xDF >0 >>>>>>>>508 string x \b%-.1s >>>>>>>>>509 ubyte&0xDF >0 >>>>>>>>>>509 string x \b%-.1s #If the boot sector fails to read any other sector, #it prints a very short message ("RE") to the screen and hangs the computer. #If the boot sector fails to find needed program in the root directory, #it also hangs with another message ("NF"). >>>>>492 string RENF \b, FAT (12 bit) >>>>>495 string RENF \b, FAT (16 bit) # http://alexfru.chat.ru/epm.html#bootprog >494 ubyte >0x4D >>495 string >E >>>495 string >>>3 string BootProg # It just looks for a program file name at the root directory # and loads corresponding file with following execution. # DOS names like STARTUP.BIN,STARTUPC.COM,STARTUPE.EXE are 8 right space padded bytes+3 bytes >>>>499 ubyte&0xDF >0 \b, COM/EXE Bootloader >>>>>499 string x \b %-.1s >>>>>>500 ubyte&0xDF >0 >>>>>>>500 string x \b%-.1s >>>>>>>>501 ubyte&0xDF >0 >>>>>>>>>501 string x \b%-.1s >>>>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>>>502 string x \b%-.1s >>>>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>>>504 string x \b%-.1s >>>>>>>>>>>>>>>>505 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>505 string x \b%-.1s >>>>>>>>>>>>>>>>>>506 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>>>506 string x \b%-.1s #name extension >>>>>507 ubyte&0xDF >0 \b. >>>>>>507 string x \b%-.1s >>>>>>>508 ubyte&0xDF >0 >>>>>>>>508 string x \b%-.1s >>>>>>>>>509 ubyte&0xDF >0 >>>>>>>>>>509 string x \b%-.1s #If the boot sector fails to read any other sector, #it prints a very short message ("RE") to the screen and hangs the computer. #If the boot sector fails to find needed program in the root directory, #it also hangs with another message ("NF"). >>>>>492 string RENF \b, FAT (12 bit) >>>>>495 string RENF \b, FAT (16 bit) # x86 bootloader end # updated by Joerg Jenderek at Sep 2007 >3 ubyte 0 #no active flag >>446 ubyte 0 # partition 1 not empty >>>450 ubyte >0 # partitions 3,4 empty >>>>482 ubyte 0 >>>>>498 ubyte 0 # partition 2 ID=0,5,15 >>>>>>466 ubyte <0x10 >>>>>>>466 ubyte 0x05 \b, extended partition table >>>>>>>466 ubyte 0x0F \b, extended partition table (LBA) >>>>>>>466 ubyte 0x0 \b, extended partition table (last) # JuMP short bootcodeoffset NOP assembler instructions will usually be EB xx 90 # http://mirror.href.com/thestarman/asm/2bytejumps.htmm#FWD # older drives may use Near JuMP instruction E9 xx xx >0 lelong&0x009000EB 0x009000EB >0 lelong&0x000000E9 0x000000E9 # minimal short forward jump found 03cx?? # maximal short forward jump is 07fx >1 ubyte <0xff \b, code offset 0x%x # mtools-3.9.8/msdos.h # usual values are marked with comments to get only informations of strange FAT systems # valid sectorsize must be a power of 2 from 32 to 32768 >>11 uleshort&0x000f x >>>11 uleshort <32769 >>>>11 uleshort >31 >>>>>21 ubyte&0xf0 0xF0 >>>>>>3 string >\0 \b, OEM-ID "%8.8s" #http://mirror.href.com/thestarman/asm/debug/debug2.htm#IHC >>>>>>>8 string IHC \b cached by Windows 9M >>>>>>11 uleshort >512 \b, Bytes/sector %u #>>>>>>11 uleshort =512 \b, Bytes/sector %u=512 (usual) >>>>>>11 uleshort <512 \b, Bytes/sector %u >>>>>>13 ubyte >1 \b, sectors/cluster %u #>>>>>>13 ubyte =1 \b, sectors/cluster %u (usual on Floppies) >>>>>>14 uleshort >32 \b, reserved sectors %u #>>>>>>14 uleshort =32 \b, reserved sectors %u (usual Fat32) #>>>>>>14 uleshort >1 \b, reserved sectors %u #>>>>>>14 uleshort =1 \b, reserved sectors %u (usual FAT12,FAT16) >>>>>>14 uleshort <1 \b, reserved sectors %u >>>>>>16 ubyte >2 \b, FATs %u #>>>>>>16 ubyte =2 \b, FATs %u (usual) >>>>>>16 ubyte =1 \b, FAT %u >>>>>>16 ubyte >0 >>>>>>17 uleshort >0 \b, root entries %u #>>>>>>17 uleshort =0 \b, root entries %u=0 (usual Fat32) >>>>>>19 uleshort >0 \b, sectors %u (volumes <=32 MB) #>>>>>>19 uleshort =0 \b, sectors %u=0 (usual Fat32) >>>>>>21 ubyte >0xF0 \b, Media descriptor 0x%x #>>>>>>21 ubyte =0xF0 \b, Media descriptor 0x%x (usual floppy) >>>>>>21 ubyte <0xF0 \b, Media descriptor 0x%x >>>>>>22 uleshort >0 \b, sectors/FAT %u #>>>>>>22 uleshort =0 \b, sectors/FAT %u=0 (usual Fat32) >>>>>>26 ubyte >2 \b, heads %u #>>>>>>26 ubyte =2 \b, heads %u (usual floppy) >>>>>>26 ubyte =1 \b, heads %u #skip for Digital Research DOS (version 3.41) 1440 kB Bootdisk >>>>>>38 ubyte !0x70 >>>>>>>28 ulelong >0 \b, hidden sectors %u #>>>>>>>28 ulelong =0 \b, hidden sectors %u (usual floppy) >>>>>>>32 ulelong >0 \b, sectors %u (volumes > 32 MB) #>>>>>>>32 ulelong =0 \b, sectors %u (volumes > 32 MB) # FAT<32 specific >>>>>>82 string !FAT32 #>>>>>>>36 ubyte 0x80 \b, physical drive 0x%x=0x80 (usual harddisk) #>>>>>>>36 ubyte 0 \b, physical drive 0x%x=0 (usual floppy) >>>>>>>36 ubyte !0x80 >>>>>>>>36 ubyte !0 \b, physical drive 0x%x >>>>>>>37 ubyte >0 \b, reserved 0x%x #>>>>>>>37 ubyte =0 \b, reserved 0x%x >>>>>>>38 ubyte >0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>38 ubyte <0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>38 ubyte =0x29 >>>>>>>>39 ulelong x \b, serial number 0x%x >>>>>>>>43 string >>>>>>>43 string >NO\ NAME \b, label: "%11.11s" >>>>>>>>43 string =NO\ NAME \b, unlabeled >>>>>>>54 string FAT \b, FAT >>>>>>>>54 string FAT12 \b (12 bit) >>>>>>>>54 string FAT16 \b (16 bit) # FAT32 specific >>>>>>82 string FAT32 \b, FAT (32 bit) >>>>>>>36 ulelong x \b, sectors/FAT %u >>>>>>>40 uleshort >0 \b, extension flags %u #>>>>>>>40 uleshort =0 \b, extension flags %u >>>>>>>42 uleshort >0 \b, fsVersion %u #>>>>>>>42 uleshort =0 \b, fsVersion %u (usual) >>>>>>>44 ulelong >2 \b, rootdir cluster %u #>>>>>>>44 ulelong =2 \b, rootdir cluster %u #>>>>>>>44 ulelong =1 \b, rootdir cluster %u >>>>>>>48 uleshort >1 \b, infoSector %u #>>>>>>>48 uleshort =1 \b, infoSector %u (usual) >>>>>>>48 uleshort <1 \b, infoSector %u >>>>>>>50 uleshort >6 \b, Backup boot sector %u #>>>>>>>50 uleshort =6 \b, Backup boot sector %u (usual) >>>>>>>50 uleshort <6 \b, Backup boot sector %u >>>>>>>54 ulelong >0 \b, reserved1 0x%x >>>>>>>58 ulelong >0 \b, reserved2 0x%x >>>>>>>62 ulelong >0 \b, reserved3 0x%x # same structure as FAT1X >>>>>>>64 ubyte >0x80 \b, physical drive 0x%x #>>>>>>>64 ubyte =0x80 \b, physical drive 0x%x=80 (usual harddisk) >>>>>>>64 ubyte&0x7F >0 \b, physical drive 0x%x #>>>>>>>64 ubyte =0 \b, physical drive 0x%x=0 (usual floppy) >>>>>>>65 ubyte >0 \b, reserved 0x%x >>>>>>>66 ubyte >0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>66 ubyte <0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>66 ubyte =0x29 >>>>>>>>67 ulelong x \b, serial number 0x%x >>>>>>>>71 string >>>>>>71 string >NO\ NAME \b, label: "%11.11s" >>>>>>>71 string =NO\ NAME \b, unlabeled ### FATs end >0x200 lelong 0x82564557 \b, BSD disklabel ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.firmware ================================================ #--------------------------Firmware Formats--------------------------- # uImage file # From: Craig Heffner, U-Boot image.h header definitions file 0 belong 0x27051956 uImage header, header size: 64 bytes, >4 belong x header CRC: 0x%X, >8 bedate x created: %s, >12 belong x image size: %d bytes, >16 belong x Data Address: 0x%X, >20 belong x Entry Point: 0x%X, >24 belong x data CRC: 0x%X, #>28 byte x OS type: %d, >28 byte 0 OS: Invalid OS, >28 byte 1 OS: OpenBSD, >28 byte 2 OS: NetBSD, >28 byte 3 OS: FreeBSD, >28 byte 4 OS: 4.4BSD, >28 byte 5 OS: Linux, >28 byte 6 OS: SVR4, >28 byte 7 OS: Esix, >28 byte 8 OS: Solaris, >28 byte 9 OS: Irix, >28 byte 10 OS: SCO, >28 byte 11 OS: Dell, >28 byte 12 OS: NCR, >28 byte 13 OS: LynxOS, >28 byte 14 OS: VxWorks, >28 byte 15 OS: pSOS, >28 byte 16 OS: QNX, >28 byte 17 OS: Firmware, >28 byte 18 OS: RTEMS, >28 byte 19 OS: ARTOS, >28 byte 20 OS: Unity OS, #>29 byte x CPU arch: %d, >29 byte 0 CPU: Invalid OS, >29 byte 1 CPU: Alpha, >29 byte 2 CPU: ARM, >29 byte 3 CPU: Intel x86, >29 byte 4 CPU: IA64, >29 byte 5 CPU: MIPS, >29 byte 6 CPU: MIPS 64 bit, >29 byte 7 CPU: PowerPC, >29 byte 8 CPU: IBM S390, >29 byte 9 CPU: SuperH, >29 byte 10 CPU: Sparc, >29 byte 11 CPU: Sparc 64 bit, >29 byte 12 CPU: M68K, >29 byte 13 CPU: Nios-32, >29 byte 14 CPU: MicroBlaze, >29 byte 15 CPU: Nios-II, >29 byte 16 CPU: Blackfin, >29 byte 17 CPU: AVR, >29 byte 18 CPU: STMicroelectronics ST200, #>30 byte x image type: %d, >30 byte 0 image type: Invalid Image, >30 byte 1 image type: Standalone Program, >30 byte 2 image type: OS Kernel Image, >30 byte 3 image type: RAMDisk Image, >30 byte 4 image type: Multi-File Image, >30 byte 5 image type: Firmware Image, >30 byte 6 image type: Script file, >30 byte 7 image type: Filesystem Image, >30 byte 8 image type: Binary Flat Device Tree Blob #>31 byte x compression type: %d, >31 byte 0 compression type: none, >31 byte 1 compression type: gzip, >31 byte 2 compression type: bzip2, >31 byte 3 compression type: lzma, >32 string x image name: %s #IMG0 header, found in VxWorks-based Mercury router firmware 0 string IMG0 IMG0 (VxWorks) header, >4 belong x size: %d #Mediatek bootloader signature #From xp-dev.com 0 string BOOTLOADER! Mediatek bootloader #CSYS header formats 0 string CSYS\x00 CSYS header, little endian, >8 lelong x size: %d 0 string CSYS\x80 CSYS header, big endian, >8 belong x size: %d # wrgg firmware image 0 string wrgg02 WRGG firmware header, >6 string x name: %s, >48 string x root device: %s # trx image file 0 string HDR0 TRX firmware header, little endian, header size: 28 bytes, >4 lelong x image size: %d bytes, >8 lelong x CRC32: 0x%X >12 lelong x flags/version: 0x%X 0 string 0RDH TRX firmware header, big endian, header size: 28 bytes, >4 belong x image size: %d bytes, >8 belong x CRC32: 0x%X >12 belong x flags/version: 0x%X # Ubicom firmware image 0 belong 0xFA320080 Ubicom firmware header, >12 belong x checksum: 0x%X, >24 belong x image size: %d # The ROME bootloader is used by several RealTek-based products. # Unfortunately, the magic bytes are specific to each product, so # separate signatures must be created for each one. # Netgear KWGR614 ROME image 0 string G614 Realtek firmware header (ROME bootloader), >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # Linksys WRT54GX ROME image 0 belong 0x59a0e842 Realtek firmware header (ROME bootloader) >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # PackImg tag, somtimes used as a delimiter between the kernel and rootfs in firmware images. 0 string --PaCkImGs-- PackImg Tag, >16 lelong x little endian size: %d bytes; >16 belong x big endian size: %d bytes #------------------------------------------------------------------------------ # Broadcom header format # 0 string BCRM Broadcom header, >4 lelong x number of sections: %d, >>8 lelong 18 first section type: flash >>8 lelong 19 first section type: disk >>8 lelong 21 first section type: tag # Berkeley Lab Checkpoint Restart (BLCR) checkpoint context files # http://ftg.lbl.gov/checkpoint 0 string Ck0\0\0R\0\0\0 BLCR >16 lelong 1 x86 >16 lelong 3 alpha >16 lelong 5 x86-64 >16 lelong 7 ARM >8 lelong x context data (little endian, version %d) 0 string \0\0\0C\0\0\0R BLCR >16 belong 2 SPARC >16 belong 4 ppc >16 belong 6 ppc64 >16 belong 7 ARMEB >16 belong 8 SPARC64 >8 belong x context data (big endian, version %d) # Aculab VoIP firmware # From: Mark Brown 0 string VoIP\ Startup\ and Aculab VoIP firmware >35 string x format %s #------------------------------------------------------------------------------ # HP LaserJet 1000 series downloadable firmware file 0 string \xbe\xefABCDEFGH HP LaserJet 1000 series downloadable firmware # From Albert Cahalan # really le32 operation,destination,payloadsize (but quite predictable) # 01 00 00 00 00 00 00 c0 00 02 00 00 0 string \1\0\0\0\0\0\0\300\0\2\0\0 Marvell Libertas firmware #--------------------------------------------------------------------------- # The following entries have been tested by Duncan Laurie (a # lead Sun/Cobalt developer) who agrees that they are good and worthy of # inclusion. # Boot ROM images for Sun/Cobalt Linux server appliances 0 string Cobalt\ Networks\ Inc.\nFirmware\ v Paged COBALT boot rom >38 string x V%.4s # New format for Sun/Cobalt boot ROMs is annoying, it stores the version code # at the very end where file(1) can't get it. 0 string CRfs COBALT boot rom data (Flat boot rom or file system) # # Motorola S-Records, from Gerd Truschinski 0 string S0 Motorola S-Record; binary data in text format # -------------------------------- # Microsoft Xbox data file formats 0 string XIP0 XIP, Microsoft Xbox data 0 string XTF0 XTF, Microsoft Xbox data #Windows CE 64 string CECE Windows CE RTOS # -------------------------------- # ZynOS ROM header format # From openwrt zynos.h. 6 string SIG ZynOS header, header size: 48 bytes, >0 belong x load address 0x%X, >9 byte <0x7F rom image type: >>9 byte <1 invalid, >>9 byte >7 invalid, >>9 byte 1 ROMIMG, >>9 byte 2 ROMBOOT, >>9 byte 3 BOOTEXT, >>9 byte 4 ROMBIN, >>9 byte 5 ROMDIR, >>9 byte 6 6, >>9 byte 7 ROMMAP, >9 byte >0x7F ram image type: >>9 byte >0x82 invalid, >>9 byte 0x80 RAM, >>9 byte 0x81 RAMCODE, >>9 byte 0x82 RAMBOOT, >10 belong >0x40000000 invalid >10 belong <0 invalid >10 belong 0 invalid >10 belong x uncompressed size: %d, >14 belong >0x40000000 invalid >14 belong <0 invalid >14 belong 0 invalid >14 belong x compressed size: %d, >20 beshort x uncompressed checksum: 0x%X, >22 beshort x compressed checksum: 0x%X, >18 byte x flags: 0x%X, >18 byte &0x40 uncompressed checksum is valid, >18 byte &0x80 the binary is compressed, >>18 byte &0x20 compressed checksum is valid, >41 belong x memory map table address: 0x%X # Firmware header used by some VxWorks-based Cisco products 0 string CI032.00 Cisco VxWorks firmware header, >8 lelong >1024 invalid >8 lelong <0 invalid >8 lelong x header size: %d bytes, >32 lelong >1024 invalid >32 lelong <0 invalid >32 lelong x number of files: %d, >48 lelong <0 invalid >48 lelong x image size: %d, >64 string x firmware version: %s # Firmware header used by some TV's 0 string FNIB ZBOOT firmware header, header size: 32 bytes, >8 lelong x load address: 0x%.8X, >12 lelong x start address: 0x%.8X, >16 lelong x checksum: 0x%.8X, >20 lelong x version: 0x%.8X, >24 lelong <1 invalid >24 lelong x image size: %d bytes # Firmware header used by several D-Link routers (and probably others) 0 string \x5e\xa3\xa4\x17 >(7.b+12) string \x5e\xa3\xa4\x17 DLOB firmware header, >>12 string x %s, >>(7.b+40) string x %s ================================================ FILE: src/binwalk-0.4.1/src/magic/magic.kernels ================================================ #-------------------------Kernels------------------------------------- # Linux kernel boot images, from Albert Cahalan # and others such as Axel Kohlmeyer # and Nicolás Lichtmaier # All known start with: b8 c0 07 8e d8 b8 00 90 8e c0 b9 00 01 29 f6 29 514 string HdrS Linux kernel ================================================ FILE: src/binwalk-0.4.1/src/magic.binarch ================================================ # MIPS prologue # addiu $sp, -XX # 27 BD FF XX 1 string \377\275\47 MIPSEL function prologue 0 string \47\275\377 MIPS function prologue # MIPS epilogue # jr $ra 0 belong 0x03e00008 MIPS function epilogue 0 lelong 0x03e00008 MIPSEL function epilogue # PowerPC epilogue # blr 0 belong 0x4E800020 PowerPC big endian function epilogue 0 lelong 0x4E800020 PowerPC little endian function epilogue # ARM prologue # STMFD SP!, {XX} 0 beshort 0xE92D ARMEB function prologue 2 leshort 0xE92D ARM function prologue # ARM epilogue # LDMFD SP!, {XX} 0 beshort 0xE8BD ARMEB function epilogue 2 leshort 0xE8BD ARM function epilogue ================================================ FILE: src/binwalk-0.4.1/src/magic.bincast ================================================ 0 belong x Hex: 0x%.8X #0 string x String: %s 0 lelong x Little Endian Long: %d 0 belong x Big Endian Long: %d 0 leshort x Little Endian Short: %d 0 beshort x Big Endian Short: %d 0 ledate x Little Endian Date: %s 0 bedate x Big Endian Date: %s ================================================ FILE: src/binwalk-0.4.1/src/magic.binwalk ================================================ # ----------------------------Archive Formats-------------------------------------- # POSIX tar archives 257 string ustar\000 POSIX tar archive !:mime application/x-tar # encoding: posix 257 string ustar\040\040\000 GNU tar archive !:mime application/x-tar # encoding: gnu # MIPS archive (needs to go before regular portable archives) # 0 string =!\n__________E MIPS archive >20 string U with MIPS Ucode members >21 string L with MIPSEL members >21 string B with MIPSEB members >19 string L and an EL hash table >19 string B and an EB hash table >22 string X -- out of date # JAR archiver (.j), this is the successor to ARJ, not Java's JAR (which is essentially ZIP) 0xe string \x1aJar\x1b JAR (ARJ Software, Inc.) archive data 0 string JARCS JAR (ARJ Software, Inc.) archive data # ARJ archiver (jason@jarthur.Claremont.EDU) 0 leshort 0xea60 ARJ archive data !:mime application/x-arj >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: %s, >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # [JW] idarc says this is also possible 2 leshort 0xea60 ARJ archive data >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: %s, >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # RAR archiver (Greg Roelofs, newt@uchicago.edu) 0 string Rar! RAR archive data [NSRL|RAR] # HPACK archiver (Peter Gutmann, pgut1@cs.aukuni.ac.nz) 0 string HPAK HPACK archive data [NSRL|HPAK] # JAM Archive volume format, by Dmitry.Kohmanyuk@UA.net 0 string \351,\001JAM\ JAM archive, [NSRL|JAM] # LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) 2 string -lh0- LHarc 1.x archive data [lh0] [NSRL|LHA1] 2 string -lh1- LHarc 1.x archive data [lh1] [NSRL|LHA1] 2 string -lz4- LHarc 1.x archive data [lz4] [NSRL|LHA1] 2 string -lz5- LHarc 1.x archive data [lz5] [NSRL|LHA1] # [never seen any but the last; -lh4- reported in comp.compression:] 2 string -lzs- LHa 2.x? archive data [lzs] [NSRL|LHA2] 2 string -lh\40- LHa 2.x? archive data [lh ] [NSRL|LHA2] 2 string -lhd- LHa 2.x? archive data [lhd] [NSRL|LHA2] 2 string -lh2- LHa 2.x? archive data [lh2] [NSRL|LHA2] 2 string -lh3- LHa 2.x? archive data [lh3] [NSRL|LHA2] 2 string -lh4- LHa (2.x) archive data [lh4] [NSRL|LHA2] 2 string -lh5- LHa (2.x) archive data [lh5] [NSRL|LHA2] 2 string -lh6- LHa (2.x) archive data [lh6] [NSRL|LHA2] 2 string -lh7- LHa (2.x) archive data [lh7] [NSRL|LHA2] # SQUISH archiver (Greg Roelofs, newt@uchicago.edu) 0 string SQSH squished archive data (Acorn RISCOS) [NSRL|SQSH] # UC2 archiver (Greg Roelofs, newt@uchicago.edu) # I can't figure out the self-extracting form of these buggers... 0 string UC2\x1a UC2 archive data [NSRL|UC2] # Zoo archiver 20 lelong 0xfdc4a7dc Zoo archive data [NSRL|ZOO] # Shell archives # JT, 2004-03-17: The "#" in the middle of the line makes it look like the # rest of the line is commented out - I guess it's OK? Beware if parsing! 10 string #\ This\ is\ a\ shell\ archive shell archive text [NSRL|SH] # # LBR. NB: May conflict with the questionable # "binary Computer Graphics Metafile" format. # 0 string \0\ \ \ \ \ \ \ \ \ \ \ \0\0 LBR archive data [NSRL|LBR] # # PMA (CP/M derivative of LHA) # 2 string -pm0- PMarc archive data [pm0] [NSRL|PMA] 2 string -pm1- PMarc archive data [pm1] [NSRL|PMA] 2 string -pm2- PMarc archive data [pm2] [NSRL|PMA] 2 string -pms- PMarc SFX archive (CP/M, DOS) [NSRL|PMA-SFX] 5 string -pc1- PopCom compressed executable archive (CP/M) [NSRL|PPC-SFX] # From rafael@icp.inpg.fr (Rafael Laboissiere) # The Project Revision Control System (see # http://www.XCF.Berkeley.EDU/~jmacd/prcs.html) generates a packaged project # file which is recognized by the following entry: 0 leshort 0xeb81 PRCS packaged project archive [NSRL|PRCS] # GTKtalog catalogs # by David Necas (Yeti) 4 string gtktalog\ GTKtalog catalog data archive, [NSRL|GTK] >>14 beshort 0x677a (gzipped) #---------------------------Bootloaders-------------------------------- # CFE bootloader 0 string CFE1CFE1 CFE boot loader, little endian 0 string 1EFC1EFC CFE boot loader, big endian #------------------Compression Formats----------------------------- # bzip2 0 string BZh >4 string 1AY&SY bzip2 compressed data !:mime application/x-bzip2 >>3 byte >47 \b, block size = %c00k # lzip 0 string LZIP lzip compressed data !:mime application/x-lzip >4 byte x \b, version: %d # LZO 0 string \211LZO\000\015\012\032\012 LZO compressed data # 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) # http://www.7-zip.org or DOC/7zFormat.txt # 0 string 7z\274\257\047\034 7-zip archive data, >6 byte x version %d >7 byte x \b.%d # standard unix compress 0 beshort 0x1f9d compress'd data >2 byte&0x80 >0 block compressed >2 byte&0x1f x %d bits # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) # Edited by Chris Chittleborough , March 2002 # * Original filename is only at offset 10 if "extra field" absent # * Produce shorter output - notably, only report compression methods # other than 8 ("deflate", the only method defined in RFC 1952). 0 string \037\213 gzip compressed data !:mime application/x-gzip >2 byte <8 \b, reserved (invalid) method >2 byte >8 \b, unknown (invalid) method >3 byte &0x01 \b, ASCII >3 byte &0x02 \b, has CRC >3 byte &0x04 \b, extra field >3 byte&0xC =0x08 >>10 string x \b, was "%s" >3 byte &0x10 \b, has comment >9 byte =0x00 \b, from FAT filesystem (MS-DOS, OS/2, NT) >9 byte =0x01 \b, from Amiga >9 byte =0x02 \b, from VMS >9 byte =0x03 \b, from Unix >9 byte =0x04 \b, from VM/CMS >9 byte =0x05 \b, from Atari >9 byte =0x06 \b, from HPFS filesystem (OS/2, NT) >9 byte =0x07 \b, from MacOS >9 byte =0x08 \b, from Z-System >9 byte =0x09 \b, from CP/M >9 byte =0x0A \b, from TOPS/20 >9 byte =0x0B \b, from NTFS filesystem (NT) >9 byte =0x0C \b, from QDOS >9 byte =0x0D \b, from Acorn RISCOS >9 byte >0x0D \b, invalid source >3 byte &0x10 \b, comment >3 byte &0x20 \b, encrypted # Dates before 1992 are invalid, unless of course you're DD-WRT in which # case you don't know how to set a date in your gzip files. Brilliant. >4 lelong =0 \b, DD-WRT date: >4 lelong <0 \b, invalid date: >4 lelong >0 >>4 lelong <694224000 \b, invalid date: >>4 lelong =694224000 \b, invalid date: >>4 lelong >694224000 \b, last modified: >4 ledate x %s >8 byte 2 \b, max compression >8 byte 4 \b, max speed # Zlib signatures 0 beshort 0x789C zlib compressed data 0 beshort 0x78DA zlib compressed data 0 beshort 0x7801 zlib compressed data # Supplementary magic data for the file(1) command to support # rzip(1). The format is described in magic(5). # # Copyright (C) 2003 by Andrew Tridgell. You may do whatever you want with # this file. # 0 string RZIP rzip compressed data >4 byte x - version %d >5 byte x \b.%d >6 belong x (%d bytes) # ZIP compression (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) 0 string PK\003\004 Zip archive data, >4 byte 0x00 v0.0 !:mime application/zip >4 byte 0x09 at least v0.9 to extract !:mime application/zip >4 byte 0x0a at least v1.0 to extract !:mime application/zip >4 byte 0x0b at least v1.1 to extract !:mime application/zip >0x161 string WINZIP WinZIP self-extracting !:mime application/zip >4 byte 0x14 >>30 ubelong !0x6d696d65 at least v2.0 to extract !:mime application/zip # Alternate ZIP string (amc@arwen.cs.berkeley.edu) 0 string PK00PK\003\004 Zip archive data [NSRL|ZIP] # Type: LZMA # URL: http://www.7-zip.org/sdk.html # # Added additional parsing to help verify LZMA matches and weed out false positives. # Added improved signature checking. # Added checks for possibly (probably) invalid matches. # From: Craig Heffner #First LZMA signature 0 string \x5d\x00\x00 LZMA compressed data, >0 leshort >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes #An alternative common LZMA signature 1 belong 0x00008000 LZMA compressed data, >0 byte 0 invalid >0 leshort >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes #Signature for less common LZMA flag/dictionary values. Results in lots of false positives, but usually marked as invalid. 1 beshort 0x0000 LZMA compressed data, >0 byte 0 invalid >0 byte >0xE0 invalid >0 byte x properties: 0x%.2X, >1 lelong <1 invalid >1 lelong x dictionary size: %d bytes, >5 lequad 0 invalid >5 lequad <0 invalid >5 lequad >0x40000000 invalid >5 lequad x uncompressed size: %lld bytes #------------------Standard file formats------------------------------------ # elf: file(1) magic for ELF executables # # We have to check the byte order flag to see what byte order all the # other stuff in the header is in. # # What're the correct byte orders for the nCUBE and the Fujitsu VPP500? # # Created by: unknown # Modified by (1): Daniel Quinlan # Modified by (2): Peter Tobias (core support) # Modified by (3): Christian 'Dr. Disk' Hechelmann (fix of core support) # Modified by (4): (VMS Itanium) # Modified by (5): Matthias Urlichs (Listing of many architectures) 0 string \177ELF ELF >4 byte 0 invalid class >4 byte 1 32-bit >4 byte 2 64-bit >5 byte 0 invalid byte order >5 byte 1 LSB >>16 leshort 0 no file type, !:strength *2 !:mime application/octet-stream >>16 leshort 1 relocatable, !:mime application/x-object >>16 leshort 2 executable, !:mime application/x-executable >>16 leshort 3 shared object, !:mime application/x-sharedlib >>16 leshort 4 core file !:mime application/x-coredump # Core file detection is not reliable. #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, >>18 leshort 4 Motorola >>>36 lelong &0x01000000 68000 - invalid byte order, >>>36 lelong &0x00810000 CPU32 - invalid byte order, >>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, # The official e_machine number for MIPS is now #8, regardless of endianness. # The second number (#10) will be deprecated later. For now, we still # say something if #10 is encountered, but only gory details for #8. >>18 leshort 8 MIPS, >>>36 lelong &0x20 N32 >>18 leshort 10 MIPS, >>>36 lelong &0x20 N32 >>18 leshort 8 # only for 32-bit >>>4 byte 1 >>>>36 lelong&0xf0000000 0x00000000 MIPS-I >>>>36 lelong&0xf0000000 0x10000000 MIPS-II >>>>36 lelong&0xf0000000 0x20000000 MIPS-III >>>>36 lelong&0xf0000000 0x30000000 MIPS-IV >>>>36 lelong&0xf0000000 0x40000000 MIPS-V >>>>36 lelong&0xf0000000 0x50000000 MIPS32 >>>>36 lelong&0xf0000000 0x60000000 MIPS64 >>>>36 lelong&0xf0000000 0x70000000 MIPS32 rel2 >>>>36 lelong&0xf0000000 0x80000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 lelong&0xf0000000 0x00000000 MIPS-I >>>>48 lelong&0xf0000000 0x10000000 MIPS-II >>>>48 lelong&0xf0000000 0x20000000 MIPS-III >>>>48 lelong&0xf0000000 0x30000000 MIPS-IV >>>>48 lelong&0xf0000000 0x40000000 MIPS-V >>>>48 lelong&0xf0000000 0x50000000 MIPS32 >>>>48 lelong&0xf0000000 0x60000000 MIPS64 >>>>48 lelong&0xf0000000 0x70000000 MIPS32 rel2 >>>>48 lelong&0xf0000000 0x80000000 MIPS64 rel2 >>18 leshort 9 Amdahl - invalid byte order, >>18 leshort 10 MIPS (deprecated), >>18 leshort 11 RS6000 - invalid byte order, >>18 leshort 15 PA-RISC - invalid byte order, >>>50 leshort 0x0214 2.0 >>>48 leshort &0x0008 (LP64), >>18 leshort 16 nCUBE, >>18 leshort 17 Fujitsu VPP500, >>18 leshort 18 SPARC32PLUS - invalid byte order, >>18 leshort 20 PowerPC, >>18 leshort 22 IBM S/390, >>18 leshort 36 NEC V800, >>18 leshort 37 Fujitsu FR20, >>18 leshort 38 TRW RH-32, >>18 leshort 39 Motorola RCE, >>18 leshort 40 ARM, >>18 leshort 41 Alpha, >>18 leshort 0xa390 IBM S/390 (obsolete), >>18 leshort 42 Renesas SH, >>18 leshort 43 SPARC V9 - invalid byte order, >>18 leshort 44 Siemens Tricore Embedded Processor, >>18 leshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 leshort 46 Renesas H8/300, >>18 leshort 47 Renesas H8/300H, >>18 leshort 48 Renesas H8S, >>18 leshort 49 Renesas H8/500, >>18 leshort 50 IA-64, >>18 leshort 51 Stanford MIPS-X, >>18 leshort 52 Motorola Coldfire, >>18 leshort 53 Motorola M68HC12, >>18 leshort 54 Fujitsu MMA, >>18 leshort 55 Siemens PCP, >>18 leshort 56 Sony nCPU, >>18 leshort 57 Denso NDR1, >>18 leshort 58 Start*Core, >>18 leshort 59 Toyota ME16, >>18 leshort 60 ST100, >>18 leshort 61 Tinyj emb., >>18 leshort 62 x86-64, >>18 leshort 63 Sony DSP, >>18 leshort 66 FX66, >>18 leshort 67 ST9+ 8/16 bit, >>18 leshort 68 ST7 8 bit, >>18 leshort 69 MC68HC16, >>18 leshort 70 MC68HC11, >>18 leshort 71 MC68HC08, >>18 leshort 72 MC68HC05, >>18 leshort 73 SGI SVx, >>18 leshort 74 ST19 8 bit, >>18 leshort 75 Digital VAX, >>18 leshort 76 Axis cris, >>18 leshort 77 Infineon 32-bit embedded, >>18 leshort 78 Element 14 64-bit DSP, >>18 leshort 79 LSI Logic 16-bit DSP, >>18 leshort 80 MMIX, >>18 leshort 81 Harvard machine-independent, >>18 leshort 82 SiTera Prism, >>18 leshort 83 Atmel AVR 8-bit, >>18 leshort 84 Fujitsu FR30, >>18 leshort 85 Mitsubishi D10V, >>18 leshort 86 Mitsubishi D30V, >>18 leshort 87 NEC v850, >>18 leshort 88 Renesas M32R, >>18 leshort 89 Matsushita MN10300, >>18 leshort 90 Matsushita MN10200, >>18 leshort 91 picoJava, >>18 leshort 92 OpenRISC, >>18 leshort 93 ARC Cores Tangent-A5, >>18 leshort 94 Tensilica Xtensa, >>18 leshort 97 NatSemi 32k, >>18 leshort 106 Analog Devices Blackfin, >>18 leshort 113 Altera Nios II, >>18 leshort 0xae META, >>18 leshort 0x3426 OpenRISC (obsolete), >>18 leshort 0x8472 OpenRISC (obsolete), >>18 leshort 0x9026 Alpha (unofficial), >>20 lelong 0 invalid version >>20 lelong 1 version 1 >>36 lelong 1 MathCoPro/FPU/MAU Required >5 byte 2 MSB >>16 beshort 0 no file type, !:mime application/octet-stream >>16 beshort 1 relocatable, !:mime application/x-object >>16 beshort 2 executable, !:mime application/x-executable >>16 beshort 3 shared object, !:mime application/x-sharedlib >>16 beshort 4 core file, !:mime application/x-coredump #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) belong >0 (signal %d), >>16 beshort &0xff00 processor-specific, >>18 beshort 0 no machine, >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, >>18 beshort 4 Motorola >>>36 belong &0x01000000 68000, >>>36 belong &0x00810000 CPU32, >>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, # only for MIPS - see comment in little-endian section above. >>18 beshort 8 MIPS, >>>36 belong &0x20 N32 >>18 beshort 10 MIPS, >>>36 belong &0x20 N32 >>18 beshort 8 # only for 32-bit >>>4 byte 1 >>>>36 belong&0xf0000000 0x00000000 MIPS-I >>>>36 belong&0xf0000000 0x10000000 MIPS-II >>>>36 belong&0xf0000000 0x20000000 MIPS-III >>>>36 belong&0xf0000000 0x30000000 MIPS-IV >>>>36 belong&0xf0000000 0x40000000 MIPS-V >>>>36 belong&0xf0000000 0x50000000 MIPS32 >>>>36 belong&0xf0000000 0x60000000 MIPS64 >>>>36 belong&0xf0000000 0x70000000 MIPS32 rel2 >>>>36 belong&0xf0000000 0x80000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 belong&0xf0000000 0x00000000 MIPS-I >>>>48 belong&0xf0000000 0x10000000 MIPS-II >>>>48 belong&0xf0000000 0x20000000 MIPS-III >>>>48 belong&0xf0000000 0x30000000 MIPS-IV >>>>48 belong&0xf0000000 0x40000000 MIPS-V >>>>48 belong&0xf0000000 0x50000000 MIPS32 >>>>48 belong&0xf0000000 0x60000000 MIPS64 >>>>48 belong&0xf0000000 0x70000000 MIPS32 rel2 >>>>48 belong&0xf0000000 0x80000000 MIPS64 rel2 >>18 beshort 9 Amdahl, >>18 beshort 10 MIPS (deprecated), >>18 beshort 11 RS6000, >>18 beshort 15 PA-RISC >>>50 beshort 0x0214 2.0 >>>48 beshort &0x0008 (LP64) >>18 beshort 16 nCUBE, >>18 beshort 17 Fujitsu VPP500, >>18 beshort 18 SPARC32PLUS, >>>36 belong&0xffff00 0x000100 V8+ Required, >>>36 belong&0xffff00 0x000200 Sun UltraSPARC1 Extensions Required, >>>36 belong&0xffff00 0x000400 HaL R1 Extensions Required, >>>36 belong&0xffff00 0x000800 Sun UltraSPARC3 Extensions Required, >>18 beshort 20 PowerPC or cisco 4500, >>18 beshort 21 64-bit PowerPC or cisco 7500, >>18 beshort 22 IBM S/390, >>18 beshort 23 Cell SPU, >>18 beshort 24 cisco SVIP, >>18 beshort 25 cisco 7200, >>18 beshort 36 NEC V800 or cisco 12000, >>18 beshort 37 Fujitsu FR20, >>18 beshort 38 TRW RH-32, >>18 beshort 39 Motorola RCE, >>18 beshort 40 ARM, >>18 beshort 41 Alpha, >>18 beshort 42 Renesas SH, >>18 beshort 43 SPARC V9, >>>48 belong&0xffff00 0x000200 Sun UltraSPARC1 Extensions Required, >>>48 belong&0xffff00 0x000400 HaL R1 Extensions Required, >>>48 belong&0xffff00 0x000800 Sun UltraSPARC3 Extensions Required, >>>48 belong&0x3 0 total store ordering, >>>48 belong&0x3 1 partial store ordering, >>>48 belong&0x3 2 relaxed memory ordering, >>18 beshort 44 Siemens Tricore Embedded Processor, >>18 beshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 beshort 46 Renesas H8/300, >>18 beshort 47 Renesas H8/300H, >>18 beshort 48 Renesas H8S, >>18 beshort 49 Renesas H8/500, >>18 beshort 50 IA-64, >>18 beshort 51 Stanford MIPS-X, >>18 beshort 52 Motorola Coldfire, >>18 beshort 53 Motorola M68HC12, >>18 beshort 73 Cray NV1, >>18 beshort 75 Digital VAX, >>18 beshort 88 Renesas M32R, >>18 leshort 92 OpenRISC, >>18 leshort 0x3426 OpenRISC (obsolete), >>18 leshort 0x8472 OpenRISC (obsolete), >>18 beshort 94 Tensilica Xtensa, >>18 beshort 97 NatSemi 32k, >>18 beshort 0x18ad AVR32 (unofficial), >>18 beshort 0x9026 Alpha (unofficial), >>18 beshort 0xa390 IBM S/390 (obsolete), >>20 belong 0 invalid version >>20 belong 1 version 1 >>36 belong 1 MathCoPro/FPU/MAU Required # Up to now only 0, 1 and 2 are defined; I've seen a file with 0x83, it seemed # like proper ELF, but extracting the string had bad results. >4 byte <0x80 >>8 string >\0 (%s) >8 string \0 >>7 byte 0 (SYSV) >>7 byte 1 (HP-UX) >>7 byte 2 (NetBSD) >>7 byte 3 (GNU/Linux) >>7 byte 4 (GNU/Hurd) >>7 byte 5 (86Open) >>7 byte 6 (Solaris) >>7 byte 7 (Monterey) >>7 byte 8 (IRIX) >>7 byte 9 (FreeBSD) >>7 byte 10 (Tru64) >>7 byte 11 (Novell Modesto) >>7 byte 12 (OpenBSD) >8 string \2 >>7 byte 13 (OpenVMS) >>7 byte 97 (ARM) >>7 byte 255 (embedded) # XXX - according to Microsoft's spec, at an offset of 0x3c in a # PE-format executable is the offset in the file of the PE header; # unfortunately, that's a little-endian offset, and there's no way # to specify an indirect offset with a specified byte order. # So, for now, we assume the standard MS-DOS stub, which puts the # PE header at 0x80 = 128. # # Required OS version and subsystem version were 4.0 on some NT 3.51 # executables built with Visual C++ 4.0, so it's not clear that # they're interesting. The user version was 0.0, but there's # probably some linker directive to set it. The linker version was # 3.0, except for one ".exe" which had it as 4.20 (same damn linker!). # # many of the compressed formats were extraced from IDARC 1.23 source code # 0 string MZ !:mime application/x-dosexec >0x18 leshort <0x40 MS-DOS executable >0 string MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b, PE for MS Windows >>&18 leshort&0x2000 >0 (DLL) >>&88 leshort 0 (unknown subsystem) >>&88 leshort 1 (native) >>&88 leshort 2 (GUI) >>&88 leshort 3 (console) >>&88 leshort 7 (POSIX) >>&0 leshort 0x0 unknown processor >>&0 leshort 0x14c Intel 80386 >>&0 leshort 0x166 MIPS R4000 >>&0 leshort 0x184 Alpha >>&0 leshort 0x268 Motorola 68000 >>&0 leshort 0x1f0 PowerPC >>&0 leshort 0x290 PA-RISC >>&18 leshort&0x0100 >0 32-bit >>&18 leshort&0x1000 >0 system file >>&228 lelong >0 \b, Mono/.Net assembly >>&0xf4 search/0x140 \x0\x40\x1\x0 >>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive >30 string Copyright\ 1989-1990\ PKWARE\ Inc. Self-extracting PKZIP archive !:mime application/zip # Is next line correct? One might expect "Corp." not "Copr." If it is right, add a note to that effect. >30 string PKLITE\ Copr. Self-extracting PKZIP archive !:mime application/zip >0x18 leshort >0x3f >>(0x3c.l) string PE\0\0 PE >>>(0x3c.l+25) byte 1 \b32 executable >>>(0x3c.l+25) byte 2 \b32+ executable # hooray, there's a DOS extender using the PE format, with a valid PE # executable inside (which just prints a message and exits if run in win) >>>(0x3c.l+92) leshort <10 >>>>(8.s*16) string 32STUB for MS-DOS, 32rtm DOS extender >>>>(8.s*16) string !32STUB for MS Windows >>>>>(0x3c.l+22) leshort&0x2000 >0 (DLL) >>>>>(0x3c.l+92) leshort 0 (unknown subsystem) >>>>>(0x3c.l+92) leshort 1 (native) >>>>>(0x3c.l+92) leshort 2 (GUI) >>>>>(0x3c.l+92) leshort 3 (console) >>>>>(0x3c.l+92) leshort 7 (POSIX) >>>(0x3c.l+92) leshort 10 (EFI application) >>>(0x3c.l+92) leshort 11 (EFI boot service driver) >>>(0x3c.l+92) leshort 12 (EFI runtime driver) >>>(0x3c.l+92) leshort 13 (XBOX) >>>(0x3c.l+4) leshort 0x0 unknown processor >>>(0x3c.l+4) leshort 0x14c Intel 80386 >>>(0x3c.l+4) leshort 0x166 MIPS R4000 >>>(0x3c.l+4) leshort 0x184 Alpha >>>(0x3c.l+4) leshort 0x268 Motorola 68000 >>>(0x3c.l+4) leshort 0x1f0 PowerPC >>>(0x3c.l+4) leshort 0x290 PA-RISC >>>(0x3c.l+4) leshort 0x200 Intel Itanium >>>(0x3c.l+22) leshort&0x0100 >0 32-bit >>>(0x3c.l+22) leshort&0x1000 >0 system file >>>(0x3c.l+232) lelong >0 Mono/.Net assembly >>>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed >>>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed >>>>(0x3c.l+0xf8) search/0x140 UPX2 >>>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>(0x3c.l+0xf8) search/0x140 .idata >>>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive >>>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .rsrc >>>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive >>>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive >>>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive >>>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .data >>>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed >>>>>(0x3c.l+0xf7) byte x >>>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .reloc >>>>>(&0xe.l+(-4)) search/0x180 PK\3\4 \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive >>>>0x30 string Inno \b, InnoSetup self-extracting archive >>(0x3c.l) string !PE\0\0 MS-DOS executable >>(0x3c.l) string NE \b, NE >>>(0x3c.l+0x36) byte 0 (unknown OS) >>>(0x3c.l+0x36) byte 1 for OS/2 1.x >>>(0x3c.l+0x36) byte 2 for MS Windows 3.x >>>(0x3c.l+0x36) byte 3 for MS-DOS >>>(0x3c.l+0x36) byte >3 (unknown OS) >>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender >>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) >>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) >>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive >>>(0x3c.l+0x70) search/0x80 WinZip(R)\ Self-Extractor \b, ZIP self-extracting archive (WinZip) >>(0x3c.l) string LX\0\0 \b, LX >>>(0x3c.l+0x0a) leshort <1 (unknown OS) >>>(0x3c.l+0x0a) leshort 1 for OS/2 >>>(0x3c.l+0x0a) leshort 2 for MS Windows >>>(0x3c.l+0x0a) leshort 3 for DOS >>>(0x3c.l+0x0a) leshort >3 (unknown OS) >>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) >>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) >>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) >>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) >>>(0x3c.l+0x08) leshort 1 i80286 >>>(0x3c.l+0x08) leshort 2 i80386 >>>(0x3c.l+0x08) leshort 3 i80486 >>>(8.s*16) string emx \b, emx >>>>&1 string x %s >>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive #------------------------------------------------------------------------------ # bFLT: file(1) magic for BFLT uclinux binary files # # From Philippe De Muyter # # Additional fields added by Craig Heffner # 0 string bFLT BFLT executable >4 belong x version %ld, >4 belong 4 >8 belong x code offset: 0x%.8X, >12 belong x data segment starts at: 0x%.8X, >16 belong x bss segment starts at: 0x%.8X, >20 belong x bss segment ends at: 0x%.8X, >24 belong x stack size: %d bytes, >28 belong x relocation records start at: 0x%.8X, >32 belong x number of reolcation records: %d, >>36 belong&0x1 0x1 ram >>36 belong&0x2 0x2 gotpic >>36 belong&0x4 0x4 gzip >>36 belong&0x8 0x8 gzdata #----------------------------------------------------------------- # MIPS COFF file formats # 0 beshort 0x0160 MIPSEB ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0162 MIPSEL-BE ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x ^H.%ld # 0 beshort 0x6001 MIPSEB-LE ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x ^H.%ld # 0 beshort 0x6201 MIPSEL ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # MIPS 2 additions # 0 beshort 0x0163 MIPSEB MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0166 MIPSEL-BE MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x6301 MIPSEB-LE MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x6601 MIPSEL MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # MIPS 3 additions # 0 beshort 0x0140 MIPSEB MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x0142 MIPSEL-BE MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x ^H.%ld # 0 beshort 0x4001 MIPSEB-LE MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x4201 MIPSEL MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x ^H.%ld # 0 beshort 0x180 MIPSEB Ucode 0 beshort 0x182 MIPSEL-BE Ucode # Windows CE package files 0 string MSCE\0\0\0\0 Microsoft WinCE installer >20 lelong 0 \b, architecture-independent >20 lelong 103 \b, Hitachi SH3 >20 lelong 104 \b, Hitachi SH4 >20 lelong 0xA11 \b, StrongARM >20 lelong 4000 \b, MIPS R4000 >20 lelong 10003 \b, Hitachi SH3 >20 lelong 10004 \b, Hitachi SH3E >20 lelong 10005 \b, Hitachi SH4 >20 lelong 70001 \b, ARM 7TDMI >52 leshort 1 \b, 1 file >52 leshort >1 \b, %u files >56 leshort 1 \b, 1 registry entry >56 leshort >1 \b, %u registry entries #------------------------------------------------------------------------------ # Microsoft Xbox executables .xbe (Esa Hyytiä ) 0 string XBEH XBE, Microsoft Xbox executable # probabilistic checks whether signed or not >0x0004 ulelong =0x0 >>&2 ulelong =0x0 >>>&2 ulelong =0x0 \b, not signed >0x0004 ulelong >0 >>&2 ulelong >0 >>>&2 ulelong >0 \b, signed # expect base address of 0x10000 >0x0104 ulelong =0x10000 >>(0x0118-0x0FF60) ulelong&0x80000007 0x80000007 \b, all regions >>(0x0118-0x0FF60) ulelong&0x80000007 !0x80000007 >>>(0x0118-0x0FF60) ulelong >0 (regions: >>>>(0x0118-0x0FF60) ulelong &0x00000001 NA >>>>(0x0118-0x0FF60) ulelong &0x00000002 Japan >>>>(0x0118-0x0FF60) ulelong &0x00000004 Rest_of_World >>>>(0x0118-0x0FF60) ulelong &0x80000000 Manufacturer >>>(0x0118-0x0FF60) ulelong >0 \b) #------------------------------------------------------------------------------ # motorola: file(1) magic for Motorola 68K and 88K binaries # # 68K # 0 beshort 0x0208 mc68k COFF >18 beshort ^00000020 object >18 beshort &00000020 executable >12 belong >0 not stripped >168 string .lowmem Apple toolbox >20 beshort 0407 (impure) >20 beshort 0410 (pure) >20 beshort 0413 (demand paged) >20 beshort 0421 (standalone) 0 beshort 0x0209 mc68k executable (shared) >12 belong >0 not stripped 0 beshort 0x020A mc68k executable (shared demand paged) >12 belong >0 not stripped # # Motorola/UniSoft 68K Binary Compatibility Standard (BCS) # 0 beshort 0x022A 68K BCS executable # # 88K # # Motorola/88Open BCS # 0 beshort 0x022B 88K BCS executable #------------------------------------------------------------------------------ # Sony Playstation executables (Adam Sjoegren ) : 0 string PS-X\ EXE Sony Playstation executable # Area: >113 string x (%s) #------------------------------------------------------------------------------ # cisco: file(1) magic for cisco Systems routers # # Most cisco file-formats are covered by the generic elf code # # Microcode files are non-ELF, 0x8501 conflicts with NetBSD/alpha. 0 beshort 0x8501 cisco IOS >0 belong&0xffffff00 0x85011400 microcode >0 belong&0xffffff00 0x8501cb00 experimental microcode >7 string >\0 for '%s' #--------------------File Systems--------------------- # Minix filesystems - Juan Cespedes # Disabled for now until better signatures can be created. Too many false positives. #0x410 leshort 0x137f Minix filesystem #>0x402 beshort !0 \b, %d zones #>0x1e string minix \b, bootable #0x410 leshort 0x138f Minix filesystem, 30 char names #0x410 leshort 0x2468 Minix filesystem, version 2 #0x410 leshort 0x2478 Minix filesystem, version 2, 30 char names #0x410 beshort 0x137f Minix filesystem (big endian) #>0x402 beshort !0 \b, %d zones #>0x1e string minix \b, bootable #0x410 beshort 0x138f Minix filesystem (big endian), 30 char names #0x410 beshort 0x2468 Minix filesystem (big endian), version 2 #0x410 beshort 0x2478 Minix filesystem (big endian), version 2, 30 char names # YAFFS 0 belong 0x03000000 >4 belong 0x01000000 >>8 beshort 0xFFFF YAFFS filesystem # EFS2 file system - jojo@utulsa.edu 8 string EFSSuper EFS2 Qualcomm filesystem super block, >0 lelong 0x53000000 little endian, >>4 leshort &1 NAND >>4 leshort ^1 NOR >>4 leshort x version 0x%x, >>24 lelong x %d blocks, >>16 lelong x 0x%x pages per block, >>20 lelong x 0x%x bytes per page 8 string SSFErepu EFS2 Qualcomm filesystem super block, >0 belong 0x53000000 big endian, >>4 beshort &1 NAND >>4 beshort ^1 NOR >>4 beshort x version 0x%x, >>24 belong x %d blocks, >>16 belong x 0x%x pages per block, >>20 belong x 0x%x bytes per page # TROC file system 0 string TROC TROC filesystem, >4 lelong x %d file entries # PFS file system 0 string PFS/ PFS filesystem, >4 string x version %s, >14 leshort x %d files # MPFS file system 0 string MPFS MPFS (Microchip) filesystem, >4 byte x version %d. >5 byte x \b%d, >6 leshort x %d file entries # cramfs filesystem - russell@coker.com.au 0 lelong 0x28cd3d45 CramFS filesystem, little endian >4 lelong <0 invalid >4 lelong x size %lu >8 lelong &1 version #2 >8 lelong &2 sorted_dirs >8 lelong &4 hole_support >32 lelong x CRC 0x%x, >36 lelong x edition %lu, >40 lelong <0 invalid >40 lelong x %lu blocks, >44 lelong <0 invalid >44 lelong x %lu files 0 belong 0x28cd3d45 CramFS filesystem, big endian >4 belong <0 invalid >4 belong x size %lu >8 belong &1 version #2 >8 belong &2 sorted_dirs >8 belong &4 hole_support >32 belong x CRC 0x%x, >36 belong x edition %lu, >40 belong <0 invalid >40 belong x %lu blocks, >44 belong <0 invalid >44 belong x %lu files # JFFS2 file system 0 leshort 0x1984 JFFS2 filesystem (old) data little endian, >4 lelong >1000000 invalid >4 lelong <0 invalid >4 lelong 0 invalid >4 lelong x JFFS node length: %d 0 beshort 0x1984 JFFS2 filesystem (old) data big endian, >4 belong >1000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x JFFS node length: %d 0 leshort 0x1985 JFFS2 filesystem data little endian, >4 lelong >1000000 invalid >4 lelong <0 invalid >4 lelong 0 invalid >4 lelong x JFFS node length: %d 0 beshort 0x1985 JFFS2 filesystem data big endian, >4 belong >1000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x JFFS node length: %d # Squashfs 0 string sqsh Squashfs filesystem, big endian, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort 3 >>63 bequad x size: %lld bytes, >28 beshort >3 >>40 bequad x size: %lld bytes, >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s 0 string hsqs Squashfs filesystem, little endian, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort 3 >>63 lequad x size: %lld bytes, >28 leshort >3 >>40 lequad x size: %lld bytes, >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s # Squashfs with LZMA compression 0 string sqlz Squashfs filesystem, big endian, lzma compression, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs 3.3 LZMA signature 0 string qshs Squashfs filesystem, big endian, lzma signature, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs for DD-WRT 0 string tqsh Squashfs filesystem, big endian, DD-WRT signature, >28 beshort >10 invalid >28 beshort <1 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort >2 >>63 bequad x size: %lld bytes, #>>67 belong x %d bytes, >4 belong x %d inodes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort >1 >>51 belong x blocksize: %d bytes, >39 bedate x created: %s # Squashfs for DD-WRT 0 string hsqt Squashfs filesystem, little endian, DD-WRT signature, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort >2 >>63 lequad x size: %lld bytes, #>>63 lelong x %d bytes, >4 lelong x %d inodes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort >1 >>51 lelong x blocksize: %d bytes, >39 ledate x created: %s # Non-standard Squashfs signature found on some D-Link routers 0 string shsq Squashfs filesystem, little endian, non-standard signature, >28 leshort >10 invalid >28 leshort <1 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort <3 >>8 lelong x size: %d bytes, >28 leshort >2 >>63 lequad x size: %lld bytes, #>>63 lelong x %d bytes, >4 lelong x %d inodes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort >1 >>51 lelong x blocksize: %d bytes, >39 ledate x created: %s # Commented out for now - unlikely to be found in firmware # CDROM Filesystems # Modified for UDF by gerardo.cacciari@gmail.com #32769 string CD001 # #!:mime application/x-iso9660-image #>38913 string !NSR0 ISO 9660 CD-ROM filesystem data #>38913 string NSR0 UDF filesystem data #>>38917 string 1 (version 1.0) #>>38917 string 2 (version 1.5) #>>38917 string 3 (version 2.0) #>>38917 byte >0x33 (unknown version, ID 0x%X) #>>38917 byte <0x31 (unknown version, ID 0x%X) # "application id" which appears to be used as a volume label #>32808 string >\0 '%s' #>34816 string \000CD001\001EL\ TORITO\ SPECIFICATION (bootable) #37633 string CD001 ISO 9660 CD-ROM filesystem data (raw 2352 byte sectors) #!:mime application/x-iso9660-image #32776 string CDROM High Sierra CD-ROM filesystem data # reiserfs - russell@coker.com.au 0x10034 string ReIsErFs ReiserFS filesystem V3.5 0x10034 string ReIsEr2Fs ReiserFS filesystem V3.6 0x10034 string ReIsEr3Fs ReiserFS filesystem V3.6.19 >0x1002c leshort x block size %d >0x10032 leshort &2 (mounted or unclean) >0x10000 lelong x num blocks %d >0x10040 lelong 1 tea hash >0x10040 lelong 2 yura hash >0x10040 lelong 3 r5 hash # ext2/ext3 filesystems - Andreas Dilger # ext4 filesystem - Eric Sandeen # volume label and UUID Russell Coker # http://etbe.coker.com.au/2008/07/08/label-vs-uuid-vs-device/ 0x438 leshort 0xEF53 Linux EXT filesystem >0x44c lelong <0 invalid >0x44c lelong >4 invalid >0x44c lelong x rev %d >0x43e leshort x \b.%d # No journal? ext2 >0x45c lelong ^0x0000004 ext2 filesystem data >>0x43a leshort ^0x0000001 (mounted or unclean) # Has a journal? ext3 or ext4 >0x45c lelong &0x0000004 # and small INCOMPAT? >>0x460 lelong <0x0000040 # and small RO_COMPAT? >>>0x464 lelong <0x0000008 ext3 filesystem data # else large RO_COMPAT? >>>0x464 lelong >0x0000007 ext4 filesystem data # else large INCOMPAT? >>0x460 lelong >0x000003f ext4 filesystem data >0x468 belong x \b, UUID=%08x >0x46c beshort x \b-%04x >0x46e beshort x \b-%04x >0x470 beshort x \b-%04x >0x472 belong x \b-%08x >0x476 beshort x \b%04x >0x478 string >0 \b, volume name "%s" # General flags for any ext* fs >0x460 lelong &0x0000004 (needs journal recovery) >0x43a leshort &0x0000002 (errors, invalid) # INCOMPAT flags >0x460 lelong &0x0000001 (compressed) #>0x460 lelong &0x0000002 (filetype) #>0x460 lelong &0x0000010 (meta bg) >0x460 lelong &0x0000040 (extents) >0x460 lelong &0x0000080 (64bit) #>0x460 lelong &0x0000100 (mmp) #>0x460 lelong &0x0000200 (flex bg) # RO_INCOMPAT flags #>0x464 lelong &0x0000001 (sparse super) >0x464 lelong &0x0000002 (large files) >0x464 lelong &0x0000008 (huge files) #>0x464 lelong &0x0000010 (gdt checksum) #romfs filesystems - Juan Cespedes 0 string -rom1fs- romfs filesystem, version 1 >8 belong >10000000 invalid >8 belong x size: %d bytes, >16 string x named %s. # JFFS - russell@coker.com.au 0 lelong 0x34383931 Linux Journalled Flash filesystem, little endian 0 belong 0x34383931 Linux Journalled Flash filesystem, big endian # Wind River MemFS file system, found in some VxWorks devices 0 string owowowowowowowowowowowowowowow Wind River management filesystem, >32 belong 0 uncompressed >32 belong 1 compressed, >36 belong x %d files # FATX 0 string FATX FATX filesystem data # updated by Joerg Jenderek at Sep 2007 # only for sector sizes with 512 or more Bytes 0x1FE leshort 0xAA55 start boot sector # to do also for sectors < than 512 Bytes and some other files, GRR #30 search/481 \x55\xAA start boot sector / filesystem # not for BeOS floppy 1440k, MBRs #(11.s-2) uleshort 0xAA55 start boot sector / filesystem >2 string OSBS \b, OS/BS MBR # J\xf6rg Jenderek >0x8C string Invalid\ partition\ table \b, MS-DOS MBR # dr-dos with some upper-, lowercase variants >0x9D string Invalid\ partition\ table$ >>181 string No\ Operating\ System$ >>>201 string Operating\ System\ load\ error$ \b, DR-DOS MBR, Version 7.01 to 7.03 >0x9D string Invalid\ partition\ table$ >>181 string No\ operating\ system$ >>>201 string Operating\ system\ load\ error$ \b, DR-DOS MBR, Version 7.01 to 7.03 >342 string Invalid\ partition\ table$ >>366 string No\ operating\ system$ >>>386 string Operating\ system\ load\ error$ \b, DR-DOS MBR, version 7.01 to 7.03 >295 string NEWLDR\0 >>302 string Bad\ PT\ $ >>>310 string No\ OS\ $ >>>>317 string OS\ load\ err$ >>>>>329 string Moved\ or\ missing\ IBMBIO.LDR\n\r >>>>>>358 string Press\ any\ key\ to\ continue.\n\r$ >>>>>>>387 string Copyright\ (c)\ 1984,1998 >>>>>>>>411 string Caldera\ Inc.\0 \b, DR-DOS MBR (IBMBIO.LDR) >0x10F string Ung\201ltige\ Partitionstabelle \b, MS-DOS MBR, german version 4.10.1998, 4.10.2222 >>0x1B8 ubelong >0 \b, Serial 0x%-.4x >0x8B string Ung\201ltige\ Partitionstabelle \b, MS-DOS MBR, german version 5.00 to 4.00.950 >271 string Invalid\ partition\ table\0 >>295 string Error\ loading\ operating\ system\0 >>>326 string Missing\ operating\ system\0 \b, mbr # >139 string Invalid\ partition\ table\0 >>163 string Error\ loading\ operating\ system\0 >>>194 string Missing\ operating\ system\0 \b, Microsoft Windows XP mbr # http://www.heise.de/ct/05/09/006/ page 184 #HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices\DosDevices\?:=Serial4Bytes+8Bytes >>>>0x1B8 ulelong >0 \b,Serial 0x%-.4x >300 string Invalid\ partition\ table\0 >>324 string Error\ loading\ operating\ system\0 >>>355 string Missing\ operating\ system\0 \b, Microsoft Windows XP MBR #??>>>389 string Invalid\ system\ disk >>>>0x1B8 ulelong >0 \b, Serial 0x%-.4x >300 string Ung\201ltige\ Partitionstabelle #split string to avoid error: String too long >>328 string Fehler\ beim\ Laden\ >>>346 string des\ Betriebssystems >>>>366 string Betriebssystem\ nicht\ vorhanden \b, Microsoft Windows XP MBR (german) >>>>>0x1B8 ulelong >0 \b, Serial 0x%-.4x #>0x145 string Default:\ F \b, FREE-DOS MBR #>0x14B string Default:\ F \b, FREE-DOS 1.0 MBR >0x145 search/7 Default:\ F \b, FREE-DOS MBR #>>313 string F0\ .\ .\ . #>>>322 string disk\ 1 #>>>>382 string FAT3 >64 string no\ active\ partition\ found >>96 string read\ error\ while\ reading\ drive \b, FREE-DOS Beta 0.9 MBR # Ranish Partition Manager http://www.ranish.com/part/ >387 search/4 \0\ Error!\r >>378 search/7 Virus! >>>397 search/4 Booting\ >>>>408 search/4 HD1/\0 \b, Ranish MBR ( >>>>>416 string Writing\ changes... \b2.37 >>>>>>438 ubyte x \b,0x%x dots >>>>>>440 ubyte >0 \b,virus check >>>>>>441 ubyte >0 \b,partition %c #2.38,2.42,2.44 >>>>>416 string !Writing\ changes... \b >>>>>>418 ubyte 1 \bvirus check, >>>>>>419 ubyte x \b0x%x seconds >>>>>>420 ubyte&0x0F >0 \b,partition >>>>>>>420 ubyte&0x0F <5 \b %x >>>>>>>420 ubyte&0x0F 0Xf \b ask >>>>>420 ubyte x \b) # >271 string Operating\ system\ loading >>296 string error\r \b, SYSLINUX MBR (2.10) # http://www.acronis.de/ >362 string MBR\ Error\ \0\r >>376 string ress\ any\ key\ to\ >>>392 string boot\ from\ floppy...\0 \b, Acronis MBR # added by Joerg Jenderek # http://www.visopsys.org/ # http://partitionlogic.org.uk/ >309 string No\ bootable\ partition\ found\r >>339 string I/O\ Error\ reading\ boot\ sector\r \b, Visopsys MBR >349 string No\ bootable\ partition\ found\r >>379 string I/O\ Error\ reading\ boot\ sector\r \b, simple Visopsys MBR # bootloader, bootmanager >0x40 string SBML # label with 11 characters of FAT 12 bit filesystem >>43 string SMART\ BTMGR >>>430 string SBMK\ Bad!\r \b, Smart Boot Manager # OEM-ID not always "SBM" #>>>>3 strings SBM >>>>6 string >\0 \b, version %s >382 string XOSLLOADXCF \b, eXtended Operating System Loader >6 string LILO \b, LInux i386 boot LOader >>120 string LILO \b, version 22.3.4 SuSe >>172 string LILO \b, version 22.5.8 Debian # updated by Joerg Jenderek at Oct 2008 # variables according to grub-0.97/stage1/stage1.S or # http://www.gnu.org/software/grub/manual/grub.html#Embedded-data # usual values are marked with comments to get only informations of strange GRUB loaders >342 search/60 \0Geom\0 #>0 ulelong x %x=0x009048EB , 0x2a9048EB 0 >>0x41 ubyte <2 >>>0x3E ubyte >2 \b; GRand Unified Bootloader # 0x3 for 0.5.95,0.93,0.94,0.96 0x4 for 1.90 >>>>0x3E ubyte x \b, stage1 version 0x%x #If it is 0xFF, use a drive passed by BIOS >>>>0x40 ubyte <0xFF \b, boot drive 0x%x # in most case 0,1,0x2e for GRUB 0.5.95 >>>>0x41 ubyte >0 \b, LBA flag 0x%x >>>>0x42 uleshort <0x8000 \b, stage2 address 0x%x #>>>>0x42 uleshort =0x8000 \b, stage2 address 0x%x (usual) >>>>0x42 uleshort >0x8000 \b, stage2 address 0x%x #>>>>0x44 ulelong =1 \b, 1st sector stage2 0x%x (default) >>>>0x44 ulelong >1 \b, 1st sector stage2 0x%x >>>>0x48 uleshort <0x800 \b, stage2 segment 0x%x #>>>>0x48 uleshort =0x800 \b, stage2 segment 0x%x (usual) >>>>0x48 uleshort >0x800 \b, stage2 segment 0x%x >>>>402 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>394 string stage1 \b, GRUB version 0.5.95 >>>>382 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>376 string GRUB\ \0 \b, GRUB version 0.93 or 1.94 >>>>383 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>377 string GRUB\ \0 \b, GRUB version 0.94 >>>>385 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>379 string GRUB\ \0 \b, GRUB version 0.95 or 0.96 >>>>391 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>>385 string GRUB\ \0 \b, GRUB version 0.97 #unkown version >>>343 string Geom\0Read\0\ Error\0 >>>>321 string Loading\ stage1.5 \b, GRUB version x.y >>>380 string Geom\0Hard\ Disk\0Read\0\ Error\0 >>>>374 string GRUB\ \0 \b, GRUB version n.m # http://syslinux.zytor.com/ >478 string Boot\ failed\r >>495 string LDLINUX\ SYS \b, SYSLINUX bootloader (1.62) >480 string Boot\ failed\r >>495 string LDLINUX\ SYS \b, SYSLINUX bootloader (2.06 or 2.11) >484 string Boot\ error\r \b, SYSLINUX bootloader (3.11) >395 string chksum\0\ ERROR!\0 \b, Gujin bootloader # http://www.bcdwb.de/bcdw/index_e.htm >3 string BCDL >>498 string BCDL\ \ \ \ BIN \b, Bootable CD Loader (1.50Z) # mbr partion table entries # OEM-ID does not contain MicroSoft,NEWLDR,DOS,SYSLINUX,or MTOOLs >3 string !MS >>3 string !SYSLINUX >>>3 string !MTOOL >>>>3 string !NEWLDR >>>>>5 string !DOS # not FAT (32 bit) >>>>>>82 string !FAT32 #not Linux kernel >>>>>>>514 string !HdrS #not BeOS >>>>>>>>422 string !Be\ Boot\ Loader # active flag 0 or 0x80 and type > 0 >>>>>>>>>446 ubyte <0x81 >>>>>>>>>>446 ubyte&0x7F 0 >>>>>>>>>>>450 ubyte >0 \b; partition 1: ID=0x%x >>>>>>>>>>>>446 ubyte 0x80 \b, active >>>>>>>>>>>>447 ubyte x \b, starthead %u #>>>>>>>>>>>>448 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>448 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>454 ulelong x \b, startsector %u >>>>>>>>>>>>458 ulelong x \b, %u sectors # >>>>>>>>>462 ubyte <0x81 >>>>>>>>>>462 ubyte&0x7F 0 >>>>>>>>>>>466 ubyte >0 \b; partition 2: ID=0x%x >>>>>>>>>>>>462 ubyte 0x80 \b, active >>>>>>>>>>>>463 ubyte x \b, starthead %u #>>>>>>>>>>>>464 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>464 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>470 ulelong x \b, startsector %u >>>>>>>>>>>>474 ulelong x \b, %u sectors # >>>>>>>>>478 ubyte <0x81 >>>>>>>>>>478 ubyte&0x7F 0 >>>>>>>>>>>482 ubyte >0 \b; partition 3: ID=0x%x >>>>>>>>>>>>478 ubyte 0x80 \b, active >>>>>>>>>>>>479 ubyte x \b, starthead %u #>>>>>>>>>>>>480 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>481 ubyte x \b, start C2S: 0x%x #>>>>>>>>>>>>480 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>486 ulelong x \b, startsector %u >>>>>>>>>>>>490 ulelong x \b, %u sectors # >>>>>>>>>494 ubyte <0x81 >>>>>>>>>>494 ubyte&0x7F 0 >>>>>>>>>>>498 ubyte >0 \b; partition 4: ID=0x%x >>>>>>>>>>>>494 ubyte 0x80 \b, active >>>>>>>>>>>>495 ubyte x \b, starthead %u #>>>>>>>>>>>>496 ubyte x \b, start C_S: 0x%x #>>>>>>>>>>>>496 ubeshort&1023 x \b, startcylinder? %d >>>>>>>>>>>>502 ulelong x \b, startsector %u >>>>>>>>>>>>506 ulelong x \b, %u sectors # mbr partion table entries end # http://www.acronis.de/ #FAT label=ACRONIS\ SZ #OEM-ID=BOOTWIZ0 >442 string Non-system\ disk,\ >>459 string press\ any\ key...\x7\0 \b, Acronis Startup Recovery Loader # DOS names like F11.SYS are 8 right space padded bytes+3 bytes >>>477 ubyte&0xDF >0 >>>>477 string x \b %-.3s >>>>>480 ubyte&0xDF >0 >>>>>>480 string x \b%-.5s >>>>485 ubyte&0xDF >0 >>>>>485 string x \b.%-.3s # >185 string FDBOOT\ Version\ >>204 string \rNo\ Systemdisk.\ >>>220 string Booting\ from\ harddisk.\n\r >>>245 string Cannot\ load\ from\ harddisk.\n\r >>>>273 string Insert\ Systemdisk\ >>>>>291 string and\ press\ any\ key.\n\r \b, FDBOOT harddisk Bootloader >>>>>>200 string >\0 \b, version %-3s >242 string Bootsector\ from\ C.H.\ Hochst\204 >>278 string No\ Systemdisk.\ >>>293 string Booting\ from\ harddisk.\n\r >>>441 string Cannot\ load\ from\ harddisk.\n\r >>>>469 string Insert\ Systemdisk\ >>>>>487 string and\ press\ any\ key.\n\r \b, WinImage harddisk Bootloader >>>>>>209 string >\0 \b, version %-4.4s >(1.b+2) ubyte 0xe >>(1.b+3) ubyte 0x1f >>>(1.b+4) ubyte 0xbe >>>>(1.b+5) ubyte 0x77 >>>>(1.b+6) ubyte 0x7c >>>>>(1.b+7) ubyte 0xac >>>>>>(1.b+8) ubyte 0x22 >>>>>>>(1.b+9) ubyte 0xc0 >>>>>>>>(1.b+10) ubyte 0x74 >>>>>>>>>(1.b+11) ubyte 0xb >>>>>>>>>>(1.b+12) ubyte 0x56 >>>>>>>>>>(1.b+13) ubyte 0xb4 \b, mkdosfs boot message display >214 string Please\ try\ to\ install\ FreeDOS\ \b, DOS Emulator boot message display #>>244 string from\ dosemu-freedos-*-bin.tgz\r #>>>170 string Sorry,\ could\ not\ load\ an\ #>>>>195 string operating\ system.\r\n # >103 string This\ is\ not\ a\ bootable\ disk.\ >>132 string Please\ insert\ a\ bootable\ >>>157 string floppy\ and\r\n >>>>169 string press\ any\ key\ to\ try\ again...\r \b, FREE-DOS message display # >66 string Solaris\ Boot\ Sector >>99 string Incomplete\ MDBoot\ load. >>>89 string Version \b, Sun Solaris Bootloader >>>>97 byte x version %c # >408 string OS/2\ !!\ SYS01475\r\0 >>429 string OS/2\ !!\ SYS02025\r\0 >>>450 string OS/2\ !!\ SYS02027\r\0 >>>469 string OS2BOOT\ \ \ \ \b, IBM OS/2 Warp bootloader # >409 string OS/2\ !!\ SYS01475\r\0 >>430 string OS/2\ !!\ SYS02025\r\0 >>>451 string OS/2\ !!\ SYS02027\r\0 >>>470 string OS2BOOT\ \ \ \ \b, IBM OS/2 Warp Bootloader >112 string This\ disk\ is\ not\ bootable\r >>142 string If\ you\ wish\ to\ make\ it\ bootable >>>176 string run\ the\ DOS\ program\ SYS\ >>>200 string after\ the\r >>>>216 string system\ has\ been\ loaded\r\n >>>>>242 string Please\ insert\ a\ DOS\ diskette\ >>>>>271 string into\r\n\ the\ drive\ and\ >>>>>>292 string strike\ any\ key...\0 \b, IBM OS/2 Warp message display # XP >430 string NTLDR\ is\ missing\xFF\r\n >>449 string Disk\ error\xFF\r\n >>>462 string Press\ any\ key\ to\ restart\r \b, Microsoft Windows XP Bootloader # DOS names like NTLDR,CMLDR,$LDR$ are 8 right space padded bytes+3 bytes >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # >430 string NTLDR\ nicht\ gefunden\xFF\r\n >>453 string Datentr\204gerfehler\xFF\r\n >>>473 string Neustart\ mit\ beliebiger\ Taste\r \b, Microsoft Windows XP Bootloader (german) >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # offset variant >>>>379 string \0 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s # >430 string NTLDR\ fehlt\xFF\r\n >>444 string Datentr\204gerfehler\xFF\r\n >>>464 string Neustart\ mit\ beliebiger\ Taste\r \b, Microsoft Windows XP Bootloader (2.german) >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # variant >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # >430 string NTLDR\ fehlt\xFF\r\n >>444 string Medienfehler\xFF\r\n >>>459 string Neustart:\ Taste\ dr\201cken\r \b, Microsoft Windows XP Bootloader (3.german) >>>>371 ubyte >0x20 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # variant >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # >430 string Datentr\204ger\ entfernen\xFF\r\n >>454 string Medienfehler\xFF\r\n >>>469 string Neustart:\ Taste\ dr\201cken\r \b, Microsoft Windows XP Bootloader (4.german) >>>>379 string \0 >>>>>368 ubyte&0xDF >0 >>>>>>368 string x %-.5s >>>>>>>373 ubyte&0xDF >0 >>>>>>>>373 string x \b%-.3s >>>>>>376 ubyte&0xDF >0 >>>>>>>376 string x \b.%-.3s # variant >>>>417 ubyte&0xDF >0 >>>>>417 string x %-.5s >>>>>>422 ubyte&0xDF >0 >>>>>>>422 string x \b%-.3s >>>>>425 ubyte&0xDF >0 >>>>>>425 string >\ \b.%-.3s # #>3 string NTFS\ \ \ \ >389 string Fehler\ beim\ Lesen\ >>407 string des\ Datentr\204gers >>>426 string NTLDR\ fehlt >>>>440 string NTLDR\ ist\ komprimiert >>>>>464 string Neustart\ mit\ Strg+Alt+Entf\r \b, Microsoft Windows XP Bootloader NTFS (german) #>3 string NTFS\ \ \ \ >313 string A\ disk\ read\ error\ occurred.\r >>345 string A\ kernel\ file\ is\ missing\ >>>370 string from\ the\ disk.\r >>>>484 string NTLDR\ is\ compressed >>>>>429 string Insert\ a\ system\ diskette\ >>>>>>454 string and\ restart\r\nthe\ system.\r \b, Microsoft Windows XP Bootloader NTFS # DOS loader variants different languages,offsets >472 ubyte&0xDF >0 >>389 string Invalid\ system\ disk\xFF\r\n >>>411 string Disk\ I/O\ error >>>>428 string Replace\ the\ disk,\ and\ >>>>>455 string press\ any\ key \b, Microsoft Windows 98 Bootloader #IO.SYS >>>>>>472 ubyte&0xDF >0 >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.5s >>>>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>>>479 string x \b%-.1s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>390 string Invalid\ system\ disk\xFF\r\n >>>412 string Disk\ I/O\ error\xFF\r\n >>>>429 string Replace\ the\ disk,\ and\ >>>>>451 string then\ press\ any\ key\r \b, Microsoft Windows 98 Bootloader >>388 string Ungueltiges\ System\ \xFF\r\n >>>410 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>427 string Datentraeger\ wechseln\ und\ >>>>>453 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (german) #WINBOOT.SYS only not spaces (0xDF) >>>>>>497 ubyte&0xDF >0 >>>>>>>497 string x %-.5s >>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>502 string x \b%-.1s >>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>504 string x \b%-.1s >>>>>>505 ubyte&0xDF >0 >>>>>>>505 string x \b.%-.3s #IO.SYS >>>>>>472 ubyte&0xDF >0 or >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.5s >>>>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>>>479 string x \b%-.1s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>390 string Ungueltiges\ System\ \xFF\r\n >>>412 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>429 string Datentraeger\ wechseln\ und\ >>>>>455 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (German) #WINBOOT.SYS only not spaces (0xDF) >>>>>>497 ubyte&0xDF >0 >>>>>>>497 string x %-.7s >>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>504 string x \b%-.1s >>>>>>505 ubyte&0xDF >0 >>>>>>>505 string x \b.%-.3s #IO.SYS >>>>>>472 ubyte&0xDF >0 or >>>>>>>472 string x \b %-.2s >>>>>>>>474 ubyte&0xDF >0 >>>>>>>>>474 string x \b%-.6s >>>>>>>480 ubyte&0xDF >0 >>>>>>>>480 string x \b.%-.3s #MSDOS.SYS >>>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>>483 string x \b%-.5s >>>>>>>>>488 ubyte&0xDF >0 >>>>>>>>>>488 string x \b%-.3s >>>>>>>>491 ubyte&0xDF >0 >>>>>>>>>491 string x \b.%-.3s # >>389 string Ungueltiges\ System\ \xFF\r\n >>>411 string E/A-Fehler\ \ \ \ \xFF\r\n >>>>428 string Datentraeger\ wechseln\ und\ >>>>>454 string Taste\ druecken\r \b, Microsoft Windows 95/98/ME Bootloader (GERMAN) # DOS names like IO.SYS,WINBOOT.SYS,MSDOS.SYS,WINBOOT.INI are 8 right space padded bytes+3 bytes >>>>>>472 string x %-.2s >>>>>>>474 ubyte&0xDF >0 >>>>>>>>474 string x \b%-.5s >>>>>>>>479 ubyte&0xDF >0 >>>>>>>>>479 string x \b%-.1s >>>>>>480 ubyte&0xDF >0 >>>>>>>480 string x \b.%-.3s >>>>>>483 ubyte&0xDF >0 \b+ >>>>>>>483 string x \b%-.5s >>>>>>>488 ubyte&0xDF >0 >>>>>>>>488 string x \b%-.2s >>>>>>>>490 ubyte&0xDF >0 >>>>>>>>>490 string x \b%-.1s >>>>>>>491 ubyte&0xDF >0 >>>>>>>>491 string x \b.%-.3s >479 ubyte&0xDF >0 >>416 string Kein\ System\ oder\ >>>433 string Laufwerksfehler >>>>450 string Wechseln\ und\ Taste\ dr\201cken \b, Microsoft DOS Bootloader (german) #IO.SYS >>>>>479 string x \b %-.2s >>>>>>481 ubyte&0xDF >0 >>>>>>>481 string x \b%-.6s >>>>>487 ubyte&0xDF >0 >>>>>>487 string x \b.%-.3s #MSDOS.SYS >>>>>>490 ubyte&0xDF >0 \b+ >>>>>>>490 string x \b%-.5s >>>>>>>>495 ubyte&0xDF >0 >>>>>>>>>495 string x \b%-.3s >>>>>>>498 ubyte&0xDF >0 >>>>>>>>498 string x \b.%-.3s # >376 search/41 Non-System\ disk\ or\ >>395 search/41 disk\ error\r >>>407 search/41 Replace\ and\ >>>>419 search/41 press\ \b, >>>>419 search/41 strike\ \b, old >>>>426 search/41 any\ key\ when\ ready\r MS or PC-DOS bootloader #449 Disk\ Boot\ failure\r MS 3.21 #466 Boot\ Failure\r MS 3.30 >>>>>468 search/18 \0 #IO.SYS,IBMBIO.COM >>>>>>&0 string x \b %-.2s >>>>>>>&-20 ubyte&0xDF >0 >>>>>>>>&-1 string x \b%-.4s >>>>>>>>>&-16 ubyte&0xDF >0 >>>>>>>>>>&-1 string x \b%-.2s >>>>>>&8 ubyte&0xDF >0 \b. >>>>>>>&-1 string x \b%-.3s #MSDOS.SYS,IBMDOS.COM >>>>>>&11 ubyte&0xDF >0 \b+ >>>>>>>&-1 string x \b%-.5s >>>>>>>>&-6 ubyte&0xDF >0 >>>>>>>>>&-1 string x \b%-.1s >>>>>>>>>>&-5 ubyte&0xDF >0 >>>>>>>>>>>&-1 string x \b%-.2s >>>>>>>&7 ubyte&0xDF >0 \b. >>>>>>>>&-1 string x \b%-.3s >441 string Cannot\ load\ from\ harddisk.\n\r >>469 string Insert\ Systemdisk\ >>>487 string and\ press\ any\ key.\n\r \b, MS (2.11) DOS bootloader #>43 string \224R-LOADER\ \ SYS =label >54 string SYS >>324 string VASKK >>>495 string NEWLDR\0 \b, DR-DOS Bootloader (LOADER.SYS) # >98 string Press\ a\ key\ to\ retry\0\r >>120 string Cannot\ find\ file\ \0\r >>>139 string Disk\ read\ error\0\r >>>>156 string Loading\ ...\0 \b, DR-DOS (3.41) Bootloader #DRBIOS.SYS >>>>>44 ubyte&0xDF >0 >>>>>>44 string x \b %-.6s >>>>>>>50 ubyte&0xDF >0 >>>>>>>>50 string x \b%-.2s >>>>>>52 ubyte&0xDF >0 >>>>>>>52 string x \b.%-.3s # >70 string IBMBIO\ \ COM >>472 string Cannot\ load\ DOS!\ >>>489 string Any\ key\ to\ retry \b, DR-DOS Bootloader >>471 string Cannot\ load\ DOS\ >>487 string press\ key\ to\ retry \b, Open-DOS Bootloader #?? >444 string KERNEL\ \ SYS >>314 string BOOT\ error! \b, FREE-DOS Bootloader >499 string KERNEL\ \ SYS >>305 string BOOT\ err!\0 \b, Free-DOS Bootloader >449 string KERNEL\ \ SYS >>319 string BOOT\ error! \b, FREE-DOS 0.5 Bootloader # >449 string Loading\ FreeDOS >>0x1AF ulelong >0 \b, FREE-DOS 0.95,1.0 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s # >331 string Error!.0 \b, FREE-DOS 1.0 bootloader # >125 string Loading\ FreeDOS...\r >>311 string BOOT\ error!\r \b, FREE-DOS bootloader >>>441 ubyte&0xDF >0 >>>>441 string x \b %-.6s >>>>>447 ubyte&0xDF >0 >>>>>>447 string x \b%-.1s >>>>>>>448 ubyte&0xDF >0 >>>>>>>>448 string x \b%-.1s >>>>449 ubyte&0xDF >0 >>>>>449 string x \b.%-.3s >124 string FreeDOS\0 >>331 string \ err\0 \b, FREE-DOS BETa 0.9 Bootloader # DOS names like KERNEL.SYS,KERNEL16.SYS,KERNEL32.SYS,METAKERN.SYS are 8 right space padded bytes+3 bytes >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >>333 string \ err\0 \b, FREE-DOS BEta 0.9 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >>334 string \ err\0 \b, FREE-DOS Beta 0.9 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s >336 string Error!\ >>343 string Hit\ a\ key\ to\ reboot. \b, FREE-DOS Beta 0.9sr1 Bootloader >>>497 ubyte&0xDF >0 >>>>497 string x \b %-.6s >>>>>503 ubyte&0xDF >0 >>>>>>503 string x \b%-.1s >>>>>>>504 ubyte&0xDF >0 >>>>>>>>504 string x \b%-.1s >>>>505 ubyte&0xDF >0 >>>>>505 string x \b.%-.3s # added by Joerg Jenderek # http://www.visopsys.org/ # http://partitionlogic.org.uk/ # OEM-ID=Visopsys >478 ulelong 0 >>(1.b+326) string I/O\ Error\ reading\ >>>(1.b+344) string Visopsys\ loader\r >>>>(1.b+361) string Press\ any\ key\ to\ continue.\r \b, Visopsys loader # http://alexfru.chat.ru/epm.html#bootprog >494 ubyte >0x4D >>495 string >E >>>495 string >>>3 string BootProg # It just looks for a program file name at the root directory # and loads corresponding file with following execution. # DOS names like STARTUP.BIN,STARTUPC.COM,STARTUPE.EXE are 8 right space padded bytes+3 bytes >>>>499 ubyte&0xDF >0 \b, COM/EXE Bootloader >>>>>499 string x \b %-.1s >>>>>>500 ubyte&0xDF >0 >>>>>>>500 string x \b%-.1s >>>>>>>>501 ubyte&0xDF >0 >>>>>>>>>501 string x \b%-.1s >>>>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>>>502 string x \b%-.1s >>>>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>>>504 string x \b%-.1s >>>>>>>>>>>>>>>>505 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>505 string x \b%-.1s >>>>>>>>>>>>>>>>>>506 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>>>506 string x \b%-.1s #name extension >>>>>507 ubyte&0xDF >0 \b. >>>>>>507 string x \b%-.1s >>>>>>>508 ubyte&0xDF >0 >>>>>>>>508 string x \b%-.1s >>>>>>>>>509 ubyte&0xDF >0 >>>>>>>>>>509 string x \b%-.1s #If the boot sector fails to read any other sector, #it prints a very short message ("RE") to the screen and hangs the computer. #If the boot sector fails to find needed program in the root directory, #it also hangs with another message ("NF"). >>>>>492 string RENF \b, FAT (12 bit) >>>>>495 string RENF \b, FAT (16 bit) # http://alexfru.chat.ru/epm.html#bootprog >494 ubyte >0x4D >>495 string >E >>>495 string >>>3 string BootProg # It just looks for a program file name at the root directory # and loads corresponding file with following execution. # DOS names like STARTUP.BIN,STARTUPC.COM,STARTUPE.EXE are 8 right space padded bytes+3 bytes >>>>499 ubyte&0xDF >0 \b, COM/EXE Bootloader >>>>>499 string x \b %-.1s >>>>>>500 ubyte&0xDF >0 >>>>>>>500 string x \b%-.1s >>>>>>>>501 ubyte&0xDF >0 >>>>>>>>>501 string x \b%-.1s >>>>>>>>>>502 ubyte&0xDF >0 >>>>>>>>>>>502 string x \b%-.1s >>>>>>>>>>>>503 ubyte&0xDF >0 >>>>>>>>>>>>>503 string x \b%-.1s >>>>>>>>>>>>>>504 ubyte&0xDF >0 >>>>>>>>>>>>>>>504 string x \b%-.1s >>>>>>>>>>>>>>>>505 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>505 string x \b%-.1s >>>>>>>>>>>>>>>>>>506 ubyte&0xDF >0 >>>>>>>>>>>>>>>>>>>506 string x \b%-.1s #name extension >>>>>507 ubyte&0xDF >0 \b. >>>>>>507 string x \b%-.1s >>>>>>>508 ubyte&0xDF >0 >>>>>>>>508 string x \b%-.1s >>>>>>>>>509 ubyte&0xDF >0 >>>>>>>>>>509 string x \b%-.1s #If the boot sector fails to read any other sector, #it prints a very short message ("RE") to the screen and hangs the computer. #If the boot sector fails to find needed program in the root directory, #it also hangs with another message ("NF"). >>>>>492 string RENF \b, FAT (12 bit) >>>>>495 string RENF \b, FAT (16 bit) # x86 bootloader end # updated by Joerg Jenderek at Sep 2007 >3 ubyte 0 #no active flag >>446 ubyte 0 # partition 1 not empty >>>450 ubyte >0 # partitions 3,4 empty >>>>482 ubyte 0 >>>>>498 ubyte 0 # partition 2 ID=0,5,15 >>>>>>466 ubyte <0x10 >>>>>>>466 ubyte 0x05 \b, extended partition table >>>>>>>466 ubyte 0x0F \b, extended partition table (LBA) >>>>>>>466 ubyte 0x0 \b, extended partition table (last) # JuMP short bootcodeoffset NOP assembler instructions will usually be EB xx 90 # http://mirror.href.com/thestarman/asm/2bytejumps.htmm#FWD # older drives may use Near JuMP instruction E9 xx xx >0 lelong&0x009000EB 0x009000EB >0 lelong&0x000000E9 0x000000E9 # minimal short forward jump found 03cx?? # maximal short forward jump is 07fx >1 ubyte <0xff \b, code offset 0x%x # mtools-3.9.8/msdos.h # usual values are marked with comments to get only informations of strange FAT systems # valid sectorsize must be a power of 2 from 32 to 32768 >>11 uleshort&0x000f x >>>11 uleshort <32769 >>>>11 uleshort >31 >>>>>21 ubyte&0xf0 0xF0 >>>>>>3 string >\0 \b, OEM-ID "%8.8s" #http://mirror.href.com/thestarman/asm/debug/debug2.htm#IHC >>>>>>>8 string IHC \b cached by Windows 9M >>>>>>11 uleshort >512 \b, Bytes/sector %u #>>>>>>11 uleshort =512 \b, Bytes/sector %u=512 (usual) >>>>>>11 uleshort <512 \b, Bytes/sector %u >>>>>>13 ubyte >1 \b, sectors/cluster %u #>>>>>>13 ubyte =1 \b, sectors/cluster %u (usual on Floppies) >>>>>>14 uleshort >32 \b, reserved sectors %u #>>>>>>14 uleshort =32 \b, reserved sectors %u (usual Fat32) #>>>>>>14 uleshort >1 \b, reserved sectors %u #>>>>>>14 uleshort =1 \b, reserved sectors %u (usual FAT12,FAT16) >>>>>>14 uleshort <1 \b, reserved sectors %u >>>>>>16 ubyte >2 \b, FATs %u #>>>>>>16 ubyte =2 \b, FATs %u (usual) >>>>>>16 ubyte =1 \b, FAT %u >>>>>>16 ubyte >0 >>>>>>17 uleshort >0 \b, root entries %u #>>>>>>17 uleshort =0 \b, root entries %u=0 (usual Fat32) >>>>>>19 uleshort >0 \b, sectors %u (volumes <=32 MB) #>>>>>>19 uleshort =0 \b, sectors %u=0 (usual Fat32) >>>>>>21 ubyte >0xF0 \b, Media descriptor 0x%x #>>>>>>21 ubyte =0xF0 \b, Media descriptor 0x%x (usual floppy) >>>>>>21 ubyte <0xF0 \b, Media descriptor 0x%x >>>>>>22 uleshort >0 \b, sectors/FAT %u #>>>>>>22 uleshort =0 \b, sectors/FAT %u=0 (usual Fat32) >>>>>>26 ubyte >2 \b, heads %u #>>>>>>26 ubyte =2 \b, heads %u (usual floppy) >>>>>>26 ubyte =1 \b, heads %u #skip for Digital Research DOS (version 3.41) 1440 kB Bootdisk >>>>>>38 ubyte !0x70 >>>>>>>28 ulelong >0 \b, hidden sectors %u #>>>>>>>28 ulelong =0 \b, hidden sectors %u (usual floppy) >>>>>>>32 ulelong >0 \b, sectors %u (volumes > 32 MB) #>>>>>>>32 ulelong =0 \b, sectors %u (volumes > 32 MB) # FAT<32 specific >>>>>>82 string !FAT32 #>>>>>>>36 ubyte 0x80 \b, physical drive 0x%x=0x80 (usual harddisk) #>>>>>>>36 ubyte 0 \b, physical drive 0x%x=0 (usual floppy) >>>>>>>36 ubyte !0x80 >>>>>>>>36 ubyte !0 \b, physical drive 0x%x >>>>>>>37 ubyte >0 \b, reserved 0x%x #>>>>>>>37 ubyte =0 \b, reserved 0x%x >>>>>>>38 ubyte >0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>38 ubyte <0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>38 ubyte =0x29 >>>>>>>>39 ulelong x \b, serial number 0x%x >>>>>>>>43 string >>>>>>>43 string >NO\ NAME \b, label: "%11.11s" >>>>>>>>43 string =NO\ NAME \b, unlabeled >>>>>>>54 string FAT \b, FAT >>>>>>>>54 string FAT12 \b (12 bit) >>>>>>>>54 string FAT16 \b (16 bit) # FAT32 specific >>>>>>82 string FAT32 \b, FAT (32 bit) >>>>>>>36 ulelong x \b, sectors/FAT %u >>>>>>>40 uleshort >0 \b, extension flags %u #>>>>>>>40 uleshort =0 \b, extension flags %u >>>>>>>42 uleshort >0 \b, fsVersion %u #>>>>>>>42 uleshort =0 \b, fsVersion %u (usual) >>>>>>>44 ulelong >2 \b, rootdir cluster %u #>>>>>>>44 ulelong =2 \b, rootdir cluster %u #>>>>>>>44 ulelong =1 \b, rootdir cluster %u >>>>>>>48 uleshort >1 \b, infoSector %u #>>>>>>>48 uleshort =1 \b, infoSector %u (usual) >>>>>>>48 uleshort <1 \b, infoSector %u >>>>>>>50 uleshort >6 \b, Backup boot sector %u #>>>>>>>50 uleshort =6 \b, Backup boot sector %u (usual) >>>>>>>50 uleshort <6 \b, Backup boot sector %u >>>>>>>54 ulelong >0 \b, reserved1 0x%x >>>>>>>58 ulelong >0 \b, reserved2 0x%x >>>>>>>62 ulelong >0 \b, reserved3 0x%x # same structure as FAT1X >>>>>>>64 ubyte >0x80 \b, physical drive 0x%x #>>>>>>>64 ubyte =0x80 \b, physical drive 0x%x=80 (usual harddisk) >>>>>>>64 ubyte&0x7F >0 \b, physical drive 0x%x #>>>>>>>64 ubyte =0 \b, physical drive 0x%x=0 (usual floppy) >>>>>>>65 ubyte >0 \b, reserved 0x%x >>>>>>>66 ubyte >0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>66 ubyte <0x29 \b, dos < 4.0 BootSector (0x%x) >>>>>>>66 ubyte =0x29 >>>>>>>>67 ulelong x \b, serial number 0x%x >>>>>>>>71 string >>>>>>71 string >NO\ NAME \b, label: "%11.11s" >>>>>>>71 string =NO\ NAME \b, unlabeled ### FATs end >0x200 lelong 0x82564557 \b, BSD disklabel #--------------------------Firmware Formats--------------------------- # uImage file # From: Craig Heffner, U-Boot image.h header definitions file 0 belong 0x27051956 uImage header, header size: 64 bytes, >4 belong x header CRC: 0x%X, >8 bedate x created: %s, >12 belong x image size: %d bytes, >16 belong x Data Address: 0x%X, >20 belong x Entry Point: 0x%X, >24 belong x data CRC: 0x%X, #>28 byte x OS type: %d, >28 byte 0 OS: Invalid OS, >28 byte 1 OS: OpenBSD, >28 byte 2 OS: NetBSD, >28 byte 3 OS: FreeBSD, >28 byte 4 OS: 4.4BSD, >28 byte 5 OS: Linux, >28 byte 6 OS: SVR4, >28 byte 7 OS: Esix, >28 byte 8 OS: Solaris, >28 byte 9 OS: Irix, >28 byte 10 OS: SCO, >28 byte 11 OS: Dell, >28 byte 12 OS: NCR, >28 byte 13 OS: LynxOS, >28 byte 14 OS: VxWorks, >28 byte 15 OS: pSOS, >28 byte 16 OS: QNX, >28 byte 17 OS: Firmware, >28 byte 18 OS: RTEMS, >28 byte 19 OS: ARTOS, >28 byte 20 OS: Unity OS, #>29 byte x CPU arch: %d, >29 byte 0 CPU: Invalid OS, >29 byte 1 CPU: Alpha, >29 byte 2 CPU: ARM, >29 byte 3 CPU: Intel x86, >29 byte 4 CPU: IA64, >29 byte 5 CPU: MIPS, >29 byte 6 CPU: MIPS 64 bit, >29 byte 7 CPU: PowerPC, >29 byte 8 CPU: IBM S390, >29 byte 9 CPU: SuperH, >29 byte 10 CPU: Sparc, >29 byte 11 CPU: Sparc 64 bit, >29 byte 12 CPU: M68K, >29 byte 13 CPU: Nios-32, >29 byte 14 CPU: MicroBlaze, >29 byte 15 CPU: Nios-II, >29 byte 16 CPU: Blackfin, >29 byte 17 CPU: AVR, >29 byte 18 CPU: STMicroelectronics ST200, #>30 byte x image type: %d, >30 byte 0 image type: Invalid Image, >30 byte 1 image type: Standalone Program, >30 byte 2 image type: OS Kernel Image, >30 byte 3 image type: RAMDisk Image, >30 byte 4 image type: Multi-File Image, >30 byte 5 image type: Firmware Image, >30 byte 6 image type: Script file, >30 byte 7 image type: Filesystem Image, >30 byte 8 image type: Binary Flat Device Tree Blob #>31 byte x compression type: %d, >31 byte 0 compression type: none, >31 byte 1 compression type: gzip, >31 byte 2 compression type: bzip2, >31 byte 3 compression type: lzma, >32 string x image name: %s #IMG0 header, found in VxWorks-based Mercury router firmware 0 string IMG0 IMG0 (VxWorks) header, >4 belong x size: %d #Mediatek bootloader signature #From xp-dev.com 0 string BOOTLOADER! Mediatek bootloader #CSYS header formats 0 string CSYS\x00 CSYS header, little endian, >8 lelong x size: %d 0 string CSYS\x80 CSYS header, big endian, >8 belong x size: %d # wrgg firmware image 0 string wrgg02 WRGG firmware header, >6 string x name: %s, >48 string x root device: %s # trx image file 0 string HDR0 TRX firmware header, little endian, header size: 28 bytes, >4 lelong x image size: %d bytes, >8 lelong x CRC32: 0x%X >12 lelong x flags/version: 0x%X 0 string 0RDH TRX firmware header, big endian, header size: 28 bytes, >4 belong x image size: %d bytes, >8 belong x CRC32: 0x%X >12 belong x flags/version: 0x%X # Ubicom firmware image 0 belong 0xFA320080 Ubicom firmware header, >12 belong x checksum: 0x%X, >24 belong x image size: %d # The ROME bootloader is used by several RealTek-based products. # Unfortunately, the magic bytes are specific to each product, so # separate signatures must be created for each one. # Netgear KWGR614 ROME image 0 string G614 Realtek firmware header (ROME bootloader), >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # Linksys WRT54GX ROME image 0 belong 0x59a0e842 Realtek firmware header (ROME bootloader) >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # PackImg tag, somtimes used as a delimiter between the kernel and rootfs in firmware images. 0 string --PaCkImGs-- PackImg Tag, >16 lelong x little endian size: %d bytes; >16 belong x big endian size: %d bytes #------------------------------------------------------------------------------ # Broadcom header format # 0 string BCRM Broadcom header, >4 lelong x number of sections: %d, >>8 lelong 18 first section type: flash >>8 lelong 19 first section type: disk >>8 lelong 21 first section type: tag # Berkeley Lab Checkpoint Restart (BLCR) checkpoint context files # http://ftg.lbl.gov/checkpoint 0 string Ck0\0\0R\0\0\0 BLCR >16 lelong 1 x86 >16 lelong 3 alpha >16 lelong 5 x86-64 >16 lelong 7 ARM >8 lelong x context data (little endian, version %d) 0 string \0\0\0C\0\0\0R BLCR >16 belong 2 SPARC >16 belong 4 ppc >16 belong 6 ppc64 >16 belong 7 ARMEB >16 belong 8 SPARC64 >8 belong x context data (big endian, version %d) # Aculab VoIP firmware # From: Mark Brown 0 string VoIP\ Startup\ and Aculab VoIP firmware >35 string x format %s #------------------------------------------------------------------------------ # HP LaserJet 1000 series downloadable firmware file 0 string \xbe\xefABCDEFGH HP LaserJet 1000 series downloadable firmware # From Albert Cahalan # really le32 operation,destination,payloadsize (but quite predictable) # 01 00 00 00 00 00 00 c0 00 02 00 00 0 string \1\0\0\0\0\0\0\300\0\2\0\0 Marvell Libertas firmware #--------------------------------------------------------------------------- # The following entries have been tested by Duncan Laurie (a # lead Sun/Cobalt developer) who agrees that they are good and worthy of # inclusion. # Boot ROM images for Sun/Cobalt Linux server appliances 0 string Cobalt\ Networks\ Inc.\nFirmware\ v Paged COBALT boot rom >38 string x V%.4s # New format for Sun/Cobalt boot ROMs is annoying, it stores the version code # at the very end where file(1) can't get it. 0 string CRfs COBALT boot rom data (Flat boot rom or file system) # # Motorola S-Records, from Gerd Truschinski 0 string S0 Motorola S-Record; binary data in text format # -------------------------------- # Microsoft Xbox data file formats 0 string XIP0 XIP, Microsoft Xbox data 0 string XTF0 XTF, Microsoft Xbox data #Windows CE 64 string CECE Windows CE RTOS # -------------------------------- # ZynOS ROM header format # From openwrt zynos.h. 6 string SIG ZynOS header, header size: 48 bytes, >0 belong x load address 0x%X, >9 byte <0x7F rom image type: >>9 byte <1 invalid, >>9 byte >7 invalid, >>9 byte 1 ROMIMG, >>9 byte 2 ROMBOOT, >>9 byte 3 BOOTEXT, >>9 byte 4 ROMBIN, >>9 byte 5 ROMDIR, >>9 byte 6 6, >>9 byte 7 ROMMAP, >9 byte >0x7F ram image type: >>9 byte >0x82 invalid, >>9 byte 0x80 RAM, >>9 byte 0x81 RAMCODE, >>9 byte 0x82 RAMBOOT, >10 belong >0x40000000 invalid >10 belong <0 invalid >10 belong 0 invalid >10 belong x uncompressed size: %d, >14 belong >0x40000000 invalid >14 belong <0 invalid >14 belong 0 invalid >14 belong x compressed size: %d, >20 beshort x uncompressed checksum: 0x%X, >22 beshort x compressed checksum: 0x%X, >18 byte x flags: 0x%X, >18 byte &0x40 uncompressed checksum is valid, >18 byte &0x80 the binary is compressed, >>18 byte &0x20 compressed checksum is valid, >41 belong x memory map table address: 0x%X # Firmware header used by some VxWorks-based Cisco products 0 string CI032.00 Cisco VxWorks firmware header, >8 lelong >1024 invalid >8 lelong <0 invalid >8 lelong x header size: %d bytes, >32 lelong >1024 invalid >32 lelong <0 invalid >32 lelong x number of files: %d, >48 lelong <0 invalid >48 lelong x image size: %d, >64 string x firmware version: %s # Firmware header used by some TV's 0 string FNIB ZBOOT firmware header, header size: 32 bytes, >8 lelong x load address: 0x%.8X, >12 lelong x start address: 0x%.8X, >16 lelong x checksum: 0x%.8X, >20 lelong x version: 0x%.8X, >24 lelong <1 invalid >24 lelong x image size: %d bytes # Firmware header used by several D-Link routers (and probably others) 0 string \x5e\xa3\xa4\x17 >(7.b+12) string \x5e\xa3\xa4\x17 DLOB firmware header, >>12 string x %s, >>(7.b+40) string x %s #-------------------------Kernels------------------------------------- # Linux kernel boot images, from Albert Cahalan # and others such as Axel Kohlmeyer # and Nicolás Lichtmaier # All known start with: b8 c0 07 8e d8 b8 00 90 8e c0 b9 00 01 29 f6 29 514 string HdrS Linux kernel ================================================ FILE: src/binwalk-0.4.1/src/md5.c ================================================ /* * Added md5_string function for ease of use with Binwalk. * * Original file obtained from: http://cr.yp.to/2004-494/gaim/0.81-src/md5.c * * Craig Heffner */ /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321. It is derived directly from the text of the RFC and not from the reference implementation. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include "md5.h" #include #include /* Needed for snprintf call in md5_string() */ #ifdef TEST /* * Compile with -DTEST to create a self-contained executable test program. * The test program should print out the same values as given in section * A.5 of RFC 1321, reproduced below. */ #include main() { static const char *const test[7] = { "", /*d41d8cd98f00b204e9800998ecf8427e*/ "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ "abc", /*900150983cd24fb0d6963f7d28e17f72*/ "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", /*d174ab98d277d9f5a5611c2c9f419d9f*/ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ }; int i; for (i = 0; i < 7; ++i) { md5_state_t state; md5_byte_t digest[16]; int di; md5_init(&state); md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); md5_finish(&state, digest); printf("MD5 (\"%s\") = ", test[i]); for (di = 0; di < 16; ++di) printf("%02x", digest[di]); printf(" :: MD5 string: %s", md5_string((void *) test[i],strlen(test[i]))); printf("\n"); } return 0; } #endif /* TEST */ /* Returns the MD5 checksum string of a given file */ char *md5_string(void *data, size_t data_size) { int i = 0; int byte_str_size = 2; int md5_hash_length = 16; int str_size = ((md5_hash_length*byte_str_size)+1); /* MD5 is 16 bytes at 2 characters per byte, plus trailing NULL */ char *md5str = NULL; md5_state_t state; md5_byte_t digest[md5_hash_length]; md5str = malloc(str_size); if(!md5str) { perror("malloc"); } else { memset(md5str,0,str_size); md5_init(&state); md5_append(&state, (const md5_byte_t *) data, data_size); md5_finish(&state, digest); for(i = 0; i < md5_hash_length; i++) { snprintf(md5str+(byte_str_size*i),byte_str_size+1,"%02x",digest[i]); } } return md5str; } /* * For reference, here is the program that computed the T values. */ #if 0 #include main() { int i; for (i = 1; i <= 64; ++i) { unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); printf("#define T%d 0x%08lx\n", i, v); } return 0; } #endif /* * End of T computation program. */ #define T1 0xd76aa478 #define T2 0xe8c7b756 #define T3 0x242070db #define T4 0xc1bdceee #define T5 0xf57c0faf #define T6 0x4787c62a #define T7 0xa8304613 #define T8 0xfd469501 #define T9 0x698098d8 #define T10 0x8b44f7af #define T11 0xffff5bb1 #define T12 0x895cd7be #define T13 0x6b901122 #define T14 0xfd987193 #define T15 0xa679438e #define T16 0x49b40821 #define T17 0xf61e2562 #define T18 0xc040b340 #define T19 0x265e5a51 #define T20 0xe9b6c7aa #define T21 0xd62f105d #define T22 0x02441453 #define T23 0xd8a1e681 #define T24 0xe7d3fbc8 #define T25 0x21e1cde6 #define T26 0xc33707d6 #define T27 0xf4d50d87 #define T28 0x455a14ed #define T29 0xa9e3e905 #define T30 0xfcefa3f8 #define T31 0x676f02d9 #define T32 0x8d2a4c8a #define T33 0xfffa3942 #define T34 0x8771f681 #define T35 0x6d9d6122 #define T36 0xfde5380c #define T37 0xa4beea44 #define T38 0x4bdecfa9 #define T39 0xf6bb4b60 #define T40 0xbebfbc70 #define T41 0x289b7ec6 #define T42 0xeaa127fa #define T43 0xd4ef3085 #define T44 0x04881d05 #define T45 0xd9d4d039 #define T46 0xe6db99e5 #define T47 0x1fa27cf8 #define T48 0xc4ac5665 #define T49 0xf4292244 #define T50 0x432aff97 #define T51 0xab9423a7 #define T52 0xfc93a039 #define T53 0x655b59c3 #define T54 0x8f0ccc92 #define T55 0xffeff47d #define T56 0x85845dd1 #define T57 0x6fa87e4f #define T58 0xfe2ce6e0 #define T59 0xa3014314 #define T60 0x4e0811a1 #define T61 0xf7537e82 #define T62 0xbd3af235 #define T63 0x2ad7d2bb #define T64 0xeb86d391 static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #ifndef ARCH_IS_BIG_ENDIAN # define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ #endif #if ARCH_IS_BIG_ENDIAN /* * On big-endian machines, we must arrange the bytes in the right * order. (This also works on machines of unknown byte order.) */ md5_word_t X[16]; const md5_byte_t *xp = data; int i; for (i = 0; i < 16; ++i, xp += 4) X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); #else /* !ARCH_IS_BIG_ENDIAN */ /* * On little-endian machines, we can process properly aligned data * without copying it. */ md5_word_t xbuf[16]; const md5_word_t *X; if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } #endif #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = 0xefcdab89; pms->abcd[2] = 0x98badcfe; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } ================================================ FILE: src/binwalk-0.4.1/src/md5.h ================================================ /* * Added md5_string function prototype for ease of use with Binwalk. * * Original file obtained from: http://cr.yp.to/2004-494/gaim/0.81-src/md5.h * * Craig Heffner */ /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321. It is derived directly from the text of the RFC and not from the reference implementation. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED # define md5_INCLUDED /* * This code has some adaptations for the Ghostscript environment, but it * will compile and run correctly in any environment with 8-bit chars and * 32-bit ints. Specifically, it assumes that if the following are * defined, they have the same meaning as in Ghostscript: P1, P2, P3, * ARCH_IS_BIG_ENDIAN. */ #include typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #ifdef __cplusplus extern "C" { #endif /* Initialize the algorithm. */ #ifdef P1 void md5_init(P1(md5_state_t *pms)); #else void md5_init(md5_state_t *pms); #endif /* Append a string to the message. */ #ifdef P3 void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); #else void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); #endif /* Finish the message and return the digest. */ #ifdef P2 void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); #else void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); #endif /* Returns the MD5 checksum string of a given file */ char *md5_string(void *data, size_t data_size); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ ================================================ FILE: src/binwalk-0.4.1/src/mparse.c ================================================ /* Provides minimal magic file parsing capabilities */ #include #include #include #include #include #include #include #include "mparse.h" /* Parse out only the signatures entry from a magic file. 'Row' must point to the beginning of a magic signature line. */ char *parse_magic(char *row, int *offset, int *magic_size, int *wildcard, struct magic_filter *filters[], int filter_count, int ignore_short, int fast_filter) { char *offset_str = NULL, *type = NULL, *magic_str = NULL, *magic_literal = NULL, *magic = NULL, *description = NULL; long long_val = 0; short short_val = 0; int literal_size = 0, base = 0; /* Get the offset, type and magic values from the row entry */ offset_str = get_column(row, 0); type = get_column(row, 1); magic_str = get_column(row, 2); description = get_column(row, 3); if(!offset_str || !type || !magic_str || !description) { goto end; } /* * If the magic signature is just the magic wildcard character, treat it as a string. * Likewise, binwalk itself doesn't have support for type masking, so treat masked types * (such as 'belong&0xF0FFFF00') as strings and just pass them off to libmagic. */ if((strcmp(magic_str, MAGIC_WILDCARD) == 0) || (strstr(type, AMPERSAND))) { *wildcard = 1; ignore_short = 0; free(type); type = strdup(STRING); } else { *wildcard = 0; } /* * Two byte signatures result in lots of false positives. If ignore_short is non-zero, then ignore * all signatures that are of type beshort or leshort, or strings that are two bytes or less in length. * But only if this signature has not been explicitly marked for inclusion! */ if(ignore_short && filter_check(filters, filter_count, description) != RESULT_INCLUDE) { if(strncmp(type, HOST_SHORT, HOST_SHORT_SIZE) == 0 || strncmp(type, LESHORT, LESHORT_SIZE) == 0 || strncmp(type, BESHORT, BESHORT_SIZE) == 0) { goto end; } else if(strncmp(type, STRING, STRING_SIZE) == 0) { magic_literal = string_literal(magic_str, &literal_size); if(magic_literal) free(magic_literal); if(literal_size <= SHORT_SIZE) { goto end; } } } /* * If fast filtering has been enabled and the signature description is not in our include list, * then completely ignore the signature. */ if(fast_filter) { if(description && strlen(description) > 0) { if(filter_check(filters, filter_count, description) != RESULT_INCLUDE) { goto end; } } } /* Offsets can be specified in hex or decimal */ if(strstr(offset_str, "0x") == offset_str) { *offset = strtol(offset_str, NULL, 16); } else { *offset = strtol(offset_str, NULL, 10); } /* Convert the magic value to a string, long or short value */ if(memcmp(type, STRING, STRING_SIZE) == 0) { magic = string_literal(magic_str, magic_size); } else { /* Numeric magic strings can be specified in hex or decimal */ if(strstr(magic_str, "0x") == magic_str) { base = 16; } else { base = 10; } if(memcmp(type, LELONG, LELONG_SIZE) == 0 || memcmp(type, HOST_LONG, HOST_LONG_SIZE) == 0) { long_val = strtol(magic_str, NULL, base); *magic_size = LONG_SIZE; } else if(memcmp(type, LESHORT, LESHORT_SIZE) == 0 || memcmp(type, HOST_SHORT, HOST_SHORT_SIZE) == 0) { short_val = (short) strtol(magic_str, NULL, base); *magic_size = SHORT_SIZE; } else if(memcmp(type, BELONG, BELONG_SIZE) == 0) { long_val = strtol(magic_str, NULL, base); long_val = htonl(long_val); *magic_size = LONG_SIZE; } else if(memcmp(type, BESHORT, BESHORT_SIZE) == 0) { short_val = (short) strtol(magic_str, NULL, base); short_val = htons(short_val); *magic_size = SHORT_SIZE; } if(*magic_size == SHORT_SIZE) { magic = malloc(SHORT_SIZE); if(!magic) { *magic_size = 0; goto end; } memcpy(magic, (void *) &short_val, SHORT_SIZE); } else if(*magic_size == LONG_SIZE) { magic = malloc(LONG_SIZE); if(!magic) { *magic_size = 0; goto end; } memcpy(magic, (void *) &long_val, LONG_SIZE); } } end: if(offset_str) free(offset_str); if(type) free(type); if(magic_str) free(magic_str); if(description) free(description); return magic; } /* Converts escaped hex or octal bytes to their respective values in the string */ char *string_literal(char *string, int *literal_size) { char *literal = NULL; char sbyte[4] = { 0 }; char byte = 0; int str_size = 0; int lsize = 0, i = 0; if(string != NULL && literal_size != NULL) { str_size = strlen(string); /* The converted string will be as big or smaller than the original string */ literal = malloc(str_size+1); if(!literal) { perror("malloc"); } else { memset(literal, 0, str_size+1); /* Loop through each byte of the original string */ for(i=0; i #ifndef NOCURL #include #include #endif #include "update.h" size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *fp) { size_t written = 0; written = fwrite(ptr, size, nmemb, fp); return written; } int update_magic_file(char *url, char *outfile) { int retval = 0; #ifndef NOCURL CURL *curl = NULL; FILE *fp = NULL; curl = curl_easy_init(); if(curl) { fp = fopen(outfile,"wb"); if(fp) { curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); if(curl_easy_perform(curl) == 0) { retval = 1; } fclose(fp); } else { perror(outfile); } curl_easy_cleanup(curl); } #else fprintf(stderr, "Sorry, this feature has been disabled!\n"); #endif return retval; } ================================================ FILE: src/binwalk-0.4.1/src/update.h ================================================ #ifndef UPDATE_H #define UPDATE_H #define BINWALK_UPDATE_URL "http://binwalk.googlecode.com/svn/trunk/src/magic.binwalk" #define BINCAST_UPDATE_URL "http://binwalk.googlecode.com/svn/trunk/src/magic.bincast" #define BINARCH_UPDATE_URL "http://binwalk.googlecode.com/svn/trunk/src/magic.binarch" int update_magic_file(char *url, char *outfile); size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *fp); #endif ================================================ FILE: src/binwalk-1.0/docs/API ================================================ DESCRIPTION The binwalk python module can be used by any python script to programatically perform binwalk scans and obtain the results of those scans. The classes, methods and objects in the binwalk modules are documented via pydoc, including examples, so those interested in using the binwalk module are encouraged to look there. However, several common usage examples are provided here to help jump-start development efforts. BASIC SCAN This is the simplest scan, and is equivalent to running binwalk on the command line with no additional arguments. Note the use of the cleanup() method, which will ensure all temporary files generated by binwalk are cleaned up: from binwalk import Binwalk binwalk = Binwalk() results = binwalk.scan('firmware.bin') binwalk.cleanup() The scan() method will return a list of tuples, one tuple for each offset in the target file where a matching signature was found. The first element of each tuple is the offset into the file at which the match was found. The second tuple is a list of dictionaries (depending on the binwalk options, there may be more than one match for a given offset); each dictionary describes a matching signature: results = [ (0, [{description : "LZMA compressed data..."}]), (112, [{description : "gzip compressed data..."}]), ] A callback function may also be specified. The callback function is called as soon as a match is identified. It is passed two arguments: the offset at which the match was found, and a list of dictionaries as described above: from binwalk import Binwalk def my_callback(offset, results): print "Found %d results at offset %d:" % (len(results), offset) for result in results: print " %s" % result['description'] binwalk = Binwalk(callback=my_callback) binwalk.scan('firmware.bin') binwalk.cleanup() ADDING FILTERS Include and exclude filters may be specified which operate identically to the --include, --exclude and --search binwalk command line options: from binwalk import Binwalk binwalk = Binwalk() # Adds a normally excluded signature to the existing list of signatures (same as --include) binwalk.filter.include('minix', exclusive=False) # Exclusively filters out all signatures except those containing the string 'filesystem' (same as --search) binwalk.filter.include('filesystem') # Excludes all results that contain the string 'jffs2' (same as --exclude) binwalk.filter.exclude('jffs2') binwalk.scan('firmware') EXTRACTING FILES Extract rules may be specified which operate identically to the --dd and --extract binwalk command line options. To add a custom extract rule, or a list of extract rules (such as with the --dd option): from binwalk import Binwalk binwalk = Binwalk() # Extract results containing the string 'gzip' with a file extension of 'gz' and run the gunzip command binwalk.extractor.add_rule('gzip:gz:gunzip %e') # Extract 'gzip' and 'filesystem' results binwalk.extractor.add_rule(['gzip:gz', 'filesystem:fs']) binwalk.scan('firmware') To load the default extraction rules from the extract.conf file (such as with the --extract option): from binwalk import Binwalk binwalk = Binwalk() binwalk.extractor.load_defaults() binwalk.Scan('firmware.bin') To enabled delayed file extraction (such as with the --delay option): from binwalk import Binwalk binwalk = Binwalk() binwalk.extractor.enable_delayed_extract(True) binwalk.Scan('firmware.bin') To enable file cleanup after extraction (such as with the --rm option): from binwalk import Binwalk binwalk = Binwalk() binwalk.extractor.cleanup_extracted_files(True) binwalk.Scan('firmware.bin') ================================================ FILE: src/binwalk-1.0/docs/COPYING ================================================ The MIT License Copyright (c) 2010 Craig Heffner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: src/binwalk-1.0/docs/README ================================================ DESCRIPTION Binwalk is a tool for searching a given binary image for embedded file types. Specifically, it was designed for identifying files embedded inside of firmware images. Binwalk file signatures are compatible with the magic signatures used by the Unix file utility. Binwalk includes customized/improved signatures for files that are commonly found in firmware images such as compressed/archived files, firmware headers, Linux kernels, bootloaders, filesystems, etc. Binwalk can scan for executable code by searching for opcodes associated with the function prologues/epiloges of various architectures. Binwalk can display the value of each file offset in various data types (long, short, date, etc). This is useful for identifying unknown firmware header fields such as date and length values. Binwalk can extract embedded files from firmware images and invoke external applications for further analysis, decompression or extraction. INSTALLATION To install binwalk, run the following command from the src directory: # python setup.py install DEPENDENCIES Binwalk is currently supported on the Linux and Mac OSX platforms. Binwalk depends on the libmagic library (version 5.05 or newer) and its corresponding magic Python module. Debian users can install these dependencies via apt-get: $ sudo apt-get install libmagic1 python-magic Note that some distributions/platforms may not have libmagic readily available, or may use an older version of libmagic that is incompatible with binwalk. In this case, you may download the source code for the file utility at: ftp://ftp.astron.com/pub/file/ Follow the file utility's documentation to build and install both libmagic and the Python magic module. BASIC USAGE The only required options to binwalk are the file(s) that you want to search: $ binwalk firmware1.bin firmware2.bin firmware3.bin Binwalk signatures and system-wide configuration files can be updated to the latest from the SVN trunk with the --update option (this likely will need to be run as root): # binwalk --update To see more verbose information about the file being scanned, specify the --verbose option. This option is automatically enabled if more than one target file is specified on the command line: $ binwalk --verbose firmware.bin Output can be logged to a file with the --file option: $ binwalk --file=binwalk.log firmware.bin Output to stdout can be suppressed with the --quiet option: $ binwalk --file=binwalk.log --quiet firmware.bin By default, scans start at the first byte of the specified file (offset 0) and end at the end of the specified file. These settings can be controlled with the --offset and --length options, respectively. For example, the following command will scan 128 bytes starting at offset 64: $ binwalk --offset=64 --length=128 firmware.bin By default, binwalk will scan every byte for possible signatures. To scan every 2 bytes, 4 bytes, 8 bytes, etc, use the --align option: $ binwalk --align=4 firmware.bin By default binwalk will use the signatures from the magic.binwalk file, but you may specify an alternate signature file with the --magic option: $ binwalk --magic=/usr/share/misc/magic firmware.bin To search for a sequence of bytes without creating a signature file, use the --raw-bytes option: $ binwalk --raw-bytes="\x00\x01\x02\x03" firmware.bin TYPES OF SCANS By default binwalk will scan for file signatures inside the specified target file(s), however, other types of scans are also supported. To scan for known x86/MIPS/ARM/PPC opcodes, use the --opcodes option: $ binwalk --opcodes firmware.bin To cast each offset in the file as various data types (big/little endian shorts/longs, date fields, etc), use the --cast option (best used with the --length / --offset options): $ binwalk --cast --length=64 firmware.bin CONTROLLING SCAN BEHAVIOR Some signatures - notably those whose magic signatures are less than 3 bytes - are excluded by default from binwalk scans. These can be individually included with the --include option, or globally with --all (multiple --include options may be specified): $ binwalk --include=minix firmware.bin $ binwalk --all firmware.bin By default results marked as invalid are not displayed. They can be displayed by specifying the --show-invalid option: $ binwalk --show-invalid firmware.bin By default binwalk will stop scanning for signatures at any given offset once a valid signature has been found at that offset. To display all signatures that match at all offsets, use the --keep-going option: $ binwalk --keep-going firmware.bin FILTERING SCAN RESULTS It may at times be desirable to exclude certian signatures from the scan results. This can be done with the --exclude option (multiple --exclude options may be specified): $ binwalk --exclude='lzma compressed data' firmware.bin It may at times be desirable to only search for a certian signature or group of signatures. This can be done with the --search option (multiple --search options may be specified): $ binwalk --search=filesystem firmware.bin The --grep option is useful for filtering output that contains multiple results per line, such as occurs with the --cast option: $ binwalk --cast --grep=2012 firmware.bin EXTRACTING FILES Binwalk can extract matches found inside the target file(s), and optionally execute an external command each time a file is extracted using the --dd option. At a minimum, a string to search for in the output description and a file extension must be specified. A command to execute may also be specified. These three fields are colon delimited. To extract all matches that contain the text 'gzip compressed data' and save them with a file extension of 'gz': $ binwalk --dd='gzip compressed data:gz' firmware.bin To extract all matches that contain the text 'gzip compressed data', save them with a file extension of 'gz' and execute the 'gunzip' command against the extracted file (note the use of the %e place holder for the path to the extracted file): $ binwalk --dd='gzip compressed data:gz:gunzip %e' firmware.bin There are some file types that are commonly extracted, and specifying a --dd option for each one is tiresome. The -e option will load extract rules from the system/user extract.conf file (see the CONFIGURATION FILES section below): $ binwalk -e firmware.bin To specify a different extraction rule file, use --extract: $ binwalk --extract=./my_extract.conf firmware.bin Extracting files with --dd or --extract can leave a lot of uneccessary files laying around. These can be automatically cleaned up with the --rm option. If specified, any extracted file that had a command run against it will be deleted after the command has finished execution. Additionally, if files created by the executed command are 0 bytes in size, they will also be removed: $ binwalk --rm firmware.bin Some file types do not specify their file size in their header, but rather rely on a footer or delimiter to signify the end of the file. When extracted these files will by default be copied from the start of the header to the end of the target file. If there are many of these files, this can take up unecessary disk space. For those files which are supported, specifying the --delay option will delay the extraction of these files until the end of the file can be found: $ binwalk --delay firmware.bin DISPLAYING SCAN PROGRESS Some scans can take some time to complete and may not display many results during this time. You can press the enter key at any time to force binwalk to display its current scan progress: $ binwalk -v firmware.bin DECIMAL HEX DESCRIPTION ------------------------------------------------------------------------------------------ Progress: 1595 / 12074736 (0.01%) Progress: 8015 / 12074736 (0.07%) Progress: 12424 / 12074736 (0.10%) SIGNATURE FILES There are three signature files used by binwalk: o magic/binwalk - The default signature file. o magic/binarch - The signature file used with --opcodes. o magic/bincast - The signature file used with --cast. Users may create their own signatures that will be added to the respective system-wide files when performing a scan. This is as easy as editing the following files in the user home directory: o .binwalk/magic/binwalk o .binwalk/magic/binarch o .binwalk/magic/bincast Although the system-wide signature files can also be altered, the system-wide signature files will be overwritten when upgrading binwalk, or using the --update option. The user files will not be touched however, and will survive these updates. CONFIGURATION FILES There is one configuration file used by binwalk only when the --extract option is specified: o config/extract.conf This file contains a list of extract rules, identical to the arguments that would be passed to the --dd option. Users can override and add to this list of extract rules by adding their own rules to the following file in the user home directory: o .binwalk/config/extract.conf Note that when overriding a system-wide extract rule, the 'type' field in the user extract rule must exactly match the 'type' field in the system-wide extract rule. Although the system-wide extract.conf file can also be altered, this file will be overwritten when upgrading binwalk or using the --update option. The user extract.conf file will not be touched however, and will survive these updates. MORE INFORMATION For more detailed and up to date information, visit the binwalk wiki page at: http://code.google.com/p/binwalk/wiki/TableOfContents ================================================ FILE: src/binwalk-1.0/src/bin/binwalk-script ================================================ #!/usr/bin/env python import sys import os.path import binwalk from threading import Thread from binwalk.common import str2int from getopt import GetoptError, getopt as GetOpt def display_status(bwalk): while True: # Display the current scan progress when the enter key is pressed. raw_input() print "Progress: %.2f%% (%d / %d)\n" % (((float(bwalk.total_scanned) / float(bwalk.scan_length)) * 100), bwalk.total_scanned, bwalk.scan_length) def usage(fd): fd.write("\n") fd.write("Binwalk v%s\n" % binwalk.Config.VERSION) fd.write("Craig Heffner, http://www.devttys0.com\n") fd.write("\n") fd.write("Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n" % os.path.basename(sys.argv[0])) fd.write("\n") fd.write("\t-o, --offset= Start scan at this file offset\n") fd.write("\t-l, --length= Number of bytes to scan\n") fd.write("\t-b, --align= Set byte alignment [default: 1]\n") fd.write("\t-m, --magic= Specify an alternate magic file to use\n") fd.write("\t-i, --include= Include matches that are normally excluded and that have in their description\n") fd.write("\t-x, --exclude= Exclude matches that have in their description\n") fd.write("\t-y, --search= Only search for matches that have in their description\n") fd.write("\t-g, --grep= Grep results for the specified text\n") fd.write("\t-R, --raw-bytes= Search for a sequence of raw bytes instead of using the default magic signatures\n") fd.write("\t-f, --file= Log results to file\n") fd.write("\t-D, --dd= Extract entries whose descriptions match , give them file extension , and execute \n") fd.write("\t-e, --extract=[file] Automatically extract known file types. Load rules from file, if specified.\n") fd.write("\t-r, --rm Cleanup extracted files and zero-size files\n") fd.write("\t-d, --delay Delay file extraction for files with known footers\n") fd.write("\t-a, --all Include all short signatures\n") fd.write("\t-I, --show-invalid Show results marked as invalid\n") fd.write("\t-A, --opcodes Scan for executable code\n") fd.write("\t-C, --cast Cast file contents as various data types\n") fd.write("\t-k, --keep-going Show all matching results at a given offset, not just the first one\n") fd.write("\t-q, --quiet Supress output to stdout\n") fd.write("\t-v, --verbose Be verbose (specify twice for very verbose)\n") fd.write("\t-u, --update Update magic signature files\n") fd.write("\t-h, --help Show help output\n") fd.write("\n") if fd == sys.stderr: sys.exit(1) else: sys.exit(0) def main(): MIN_ARGC = 2 align = 1 offset = 0 length = 0 quiet = False pre_filter = True verbose = 0 log_file = None show_invalid = False short_sig = True custom_signature = None delay_extraction = False extract_rules_file = None extract_from_config = False cleanup_after_extract = False magic_flags = binwalk.magic.MAGIC_NONE options = [] magic_files = [] target_files = [] greps = [] includes = [] excludes = [] searches = [] extracts = [] config = binwalk.Config() short_options = "aACdhkeqruvPIf:o:l:b:i:x:y:D:m:R:g:" long_options = [ "rm", "all", "help", "quiet", "verbose", "opcodes", "cast", "update", "keep-going", "show-invalid", "profile", "delay", "file=", "offset=", "length=", "align=", "include=", "exclude=", "extract=", "search=", "dd=", "grep=", "magic=", "raw-bytes=", ] # Require at least one argument (the target file) if len(sys.argv) < MIN_ARGC: usage(sys.stderr) try: opts, args = GetOpt(sys.argv[1:], short_options, long_options) except GetoptError, e: sys.stderr.write("%s\n" % str(e)) usage(sys.stderr) for opt, arg in opts: if opt in ("-h", "--help"): usage(sys.stdout) elif opt in ("-d", "--delay"): delay_extraction = True elif opt in ("-f", "--file"): log_file = arg elif opt in ("-q", "--quiet"): quiet = True elif opt in ("-v", "--verbose"): verbose += 1 elif opt in ("-o", "--offset"): offset = str2int(arg) elif opt in ("-l", "--length"): length = str2int(arg) elif opt in ("-b", "--align"): align = str2int(arg) elif opt in ("-i", "--include"): includes.append(arg) elif opt in ("-y", "--search"): searches.append(arg) elif opt in ("-x", "--exclude"): excludes.append(arg) elif opt in ("-D", "--dd"): extracts.append(arg) elif opt in ("-g", "--grep"): greps.append(arg) elif opt in ("-e", "--extract"): if arg: extract_rules_file = arg else: extract_from_config = True elif opt in ("-r", "--rm"): cleanup_after_extract = True elif opt in ("-m", "--magic"): magic_files.append(arg) elif opt in ("-a", "--all"): short_sig = False elif opt in ("-k", "--keep-going"): magic_flags |= binwalk.magic.MAGIC_CONTINUE elif opt in ("-I", "--show-invalid"): show_invalid = True elif opt in ("-A", "--opcodes"): # Check every single offset align = 1 # Don't filter out short signatures as some opcode sigs are only 2 bytes short_sig = False # Load user file first so its signatures take precedence magic_files.append(config.paths['user'][config.BINARCH_MAGIC_FILE]) magic_files.append(config.paths['system'][config.BINARCH_MAGIC_FILE]) elif opt in ("-C", "--cast"): # Check every single offset align = 1 # Don't stop at the first match (everything matches everything in this scan) magic_flags |= binwalk.magic.MAGIC_CONTINUE # Disable all pre filtering; we want to check everything for this scan pre_filter = False # Don't filter shot signatures, or else some casts won't be displayed short_sig = False # Load user file first so its signatures take precedence magic_files.append(config.paths['user'][config.BINCAST_MAGIC_FILE]) magic_files.append(config.paths['system'][config.BINCAST_MAGIC_FILE]) elif opt in ("-R", "--raw-bytes"): # Disable short signature filtering, as the supplied string may be short short_sig = False custom_signature = arg elif opt in ("-u", "--update"): try: sys.stdout.write("Updating signatures...") sys.stdout.flush() binwalk.Update().update() sys.stdout.write("done.\n") sys.exit(0) except Exception, e: if 'Permission denied' in str(e): sys.stderr.write("failed (permission denied). Check your user permissions, or run the update as root.\n") else: sys.stderr.write('\n' + str(e) + '\n') sys.exit(1) # The --profile option is handled prior to calling main() elif opt not in ('-P', '--profile'): usage(sys.stderr) # Append the option and argument to the list of processed options # This is used later to determine which argv entries are file names options.append(opt) options.append(arg) options.append("%s%s" % (opt, arg)) options.append("%s=%s" % (opt, arg)) # Treat any command line options not processed by getopt as target file paths for opt in sys.argv[1:]: #TODO: Do we really want to not process valid files that start with a '-'? # This is probably OK, and ensures that no options are treated as target files. if opt not in options and not opt.startswith('-'): target_files.append(opt) # If more than one target file was specified, enable verbose mode; else, there is # nothing in the output to indicate which scan corresponds to which file. if len(target_files) > 1: verbose = True # Instantiate the Binwalk class bwalk = binwalk.Binwalk(flags=magic_flags, verbose=verbose, log=log_file, quiet=quiet) # If a custom signature was specified, create a temporary magic file containing the custom signature # and ensure that it is the only magic file that will be loaded when Binwalk.scan() is called. if custom_signature is not None: magic_files = bwalk.parser.file_from_string(custom_signature) # Set any specified filters bwalk.filter.include(includes, exclusive=False) bwalk.filter.exclude(excludes) bwalk.filter.include(searches) bwalk.filter.grep(filters=greps) # Add any specified extract rules bwalk.extractor.add_rule(extracts) # If -e was specified, load the default extract rules if extract_from_config: bwalk.extractor.load_defaults() # If --extract was specified, load the specified extraction rules file if extract_rules_file is not None: bwalk.extractor.load_from_file(extract_rules_file) # Set the extractor cleanup value (True to clean up files, False to leave them on disk) bwalk.extractor.cleanup_extracted_files(cleanup_after_extract) # Enable delayed extraction, which will prevent supported file types from having trailing data when extracted bwalk.extractor.enable_delayed_extract(delay_extraction) # Load the magic file(s) bwalk.load_signatures(magic_files=magic_files, pre_filter_signatures=pre_filter, filter_short_signatures=short_sig) # Scan each target file for target_file in target_files: bwalk.display.header(target_file) # Start the display_status function as a daemon thread t = Thread(target=display_status, args=(bwalk,)) t.setDaemon(True) t.start() # Catch keyboard interrupts so that we can properly clean up after the scan try: bwalk.scan(target_file, offset=offset, length=length, align=align, show_invalid_results=show_invalid, callback=bwalk.display.results) except KeyboardInterrupt: pass bwalk.display.footer() # Be sure to drink your ovaltine. # And also to clean up any temporary magic files. bwalk.cleanup() try: # Special options for profiling the code. For debug use only. if '--profile' in sys.argv or '-P' in sys.argv: import cProfile cProfile.run('main()') else: main() except KeyboardInterrupt: pass ================================================ FILE: src/binwalk-1.0/src/binwalk/__init__.py ================================================ import os import magic from config import * from update import * from filter import * from parser import * from smartsig import * from extractor import * from prettyprint import * from common import file_size class Binwalk: ''' Primary Binwalk class. Interesting class objects: self.filter - An instance of the MagicFilter class. self.extractor - An instance of the Extractor class. self.parser - An instance of the MagicParser class. self.display - An instance of the PrettyPrint class. self.magic_files - A list of magic file path strings to use whenever the scan() method is invoked. self.scan_length - The total number of bytes to be scanned. self.total_scanned - The number of bytes that have already been scanned. ''' # Default libmagic flags. Basically disable anything we don't need in the name of speed. DEFAULT_FLAGS = magic.MAGIC_NO_CHECK_TEXT | magic.MAGIC_NO_CHECK_ENCODING | magic.MAGIC_NO_CHECK_APPTYPE | magic.MAGIC_NO_CHECK_TOKENS # The MAX_SIGNATURE_SIZE limits the amount of data available to a signature. # While most headers/signatures are far less than this value, some may reference # pointers in the header structure which may point well beyond the header itself. # Passing the entire remaining buffer to libmagic is resource intensive and will # significantly slow the scan; this value represents a reasonable buffer size to # pass to libmagic which will not drastically affect scan time. MAX_SIGNATURE_SIZE = 8092 # Max number of bytes to process at one time. Everyone should have 50MB of memory, right? READ_BLOCK_SIZE = 50 * 1024 * 1024 # Minimum verbosity level at which to enable extractor verbosity. VERY_VERBOSE = 2 # Scan every byte by default. DEFAULT_BYTE_ALIGNMENT = 1 def __init__(self, magic_files=[], flags=magic.MAGIC_NONE, log=None, quiet=False, verbose=0): ''' Class constructor. @magic_files - A list of magic files to use. @flags - Flags to pass to magic_open. [TODO: Might this be more appropriate as an argument to load_signaures?] @log - Output PrettyPrint data to log file as well as to stdout. @quiet - If set to True, supress PrettyPrint output to stdout. @verbose - Verbosity level. Returns None. ''' self.flags = self.DEFAULT_FLAGS | flags self.magic_files = magic_files self.verbose = verbose self.total_scanned = 0 self.scan_length = 0 self.total_read = 0 self.magic = None self.mfile = None # Instantiate the config class so we can access file/directory paths self.config = Config() # Use the system default magic file if no other was specified if not self.magic_files or self.magic_files is None: # Append the user's magic file first so that those signatures take precedence self.magic_files = [ self.config.paths['user'][self.config.BINWALK_MAGIC_FILE], self.config.paths['system'][self.config.BINWALK_MAGIC_FILE], ] # Only set the extractor verbosity if told to be very verbose if self.verbose >= self.VERY_VERBOSE: extractor_verbose = True else: extractor_verbose = False # Create an instance of the PrettyPrint class, which can be used to print results to screen/file. self.display = PrettyPrint(log=log, quiet=quiet, verbose=verbose, bwalk=self) # Create MagicFilter and Extractor class instances. These can be used to: # # o Create include/exclude filters # o Specify file extraction rules to be applied during a scan # self.filter = MagicFilter() self.extractor = Extractor(verbose=extractor_verbose) # Create SmartSignature and MagicParser class instances. These are mostly for internal use. self.smart = SmartSignature(self.filter) self.parser = MagicParser(self.filter, self.smart) def __del__(self): ''' Class deconstructor. ''' self.cleanup() def cleanup(self): ''' Cleanup any temporary files generated by the internal instance of MagicParser. Returns None. ''' try: self.parser.cleanup() except: pass def load_signatures(self, magic_files=[], pre_filter_signatures=True, filter_short_signatures=True): ''' Load signatures from magic file(s). Called automatically by Binwalk.scan() with all defaults, if not already called manually. @magic_files - A list of magic files to use (default: self.magic_files). @pre_filter_signatures - Set to False to disable pre-filtering of signatures before invoking libmagic. @filter_short_signatures - Set to True to include signatures with short (<= 2 byte) magic strings. Returns None. ''' # Disable pre filtering in the smart signature class instance. # This is also checked by Binwalk.scan() before performing pre-filtering. self.smart.pre_filter = pre_filter_signatures # The magic files specified here override any already set if magic_files and magic_files is not None: self.magic_files = magic_files # Parse the magic file(s) and initialize libmagic self.mfile = self.parser.parse(self.magic_files, filter_short_signatures=filter_short_signatures, pre_filter_signatures=pre_filter_signatures) self.magic = magic.open(self.flags) self.magic.load(self.mfile) def scan(self, target_file, offset=0, length=0, align=DEFAULT_BYTE_ALIGNMENT, show_invalid_results=False, callback=None): ''' Performs a Binwalk scan on the target file. @target_file - File to scan. @offset - Starting offset at which to start the scan. @length - Number of bytes to scan. @align - Look for signatures every align bytes. @show_invalid_results - Set to True to display invalid results. @callback - Callback function to be invoked when matches are found. The callback function is passed two arguments: a list of result dictionaries containing the scan results (one result per dict), and the offset at which those results were identified. Example callback function: def my_callback(offset, results): print "Found %d results at offset %d:" % (len(results), offset) for result in results: print "\t%s" % result['description'] binwalk.Binwalk(callback=my_callback).scan("firmware.bin") Upon completion, the scan method returns a sorted list of tuples containing a list of results dictionaries and the offsets at which those results were identified: scan_items = [ (0, [{description : "LZMA compressed data..."}]), (112, [{description : "gzip compressed data..."}]) ] See SmartSignature.parse for a more detailed description of the results dictionary structure. ''' scan_results = {} self.total_read = 0 self.total_scanned = 0 self.scan_length = length self.filter.show_invalid_results = show_invalid_results # Load the default signatures if self.load_signatures has not already been invoked if self.magic is None: self.load_signatures() # Get a local copy of the signature sets generated by self.parser.build_signature_set. # This is accessed heavily throughout the scan, and there is less overhead for accessing local variables in Python. signature_set = self.parser.build_signature_set() # Need the total size of the target file, even if we aren't scanning the whole thing fsize = file_size(target_file) # Open the target file and seek to the specified start offset fd = open(target_file) fd.seek(offset) # If no length was specified, make the length the size of the target file minus the starting offset if self.scan_length == 0: self.scan_length = fsize - offset # Sanity check on the byte alignment; default to 1 if align <= 0: align = 1 # Main loop, scan through all the data while True: i = 0 # Read in the next block of data from the target file and make sure it's valid (data, dlen) = self._read_block(fd) if data is None or dlen == 0: break # The total number of bytes scanned could be bigger than the total number # of bytes read from the file under the following circumstances: # # o The previous dlen was not a multiple of align # o A previous result specified a jump offset that was beyond the end of the # then current data block # # If this is the case, we need to index into this data block appropriately in order to # resume the scan from the appropriate offset, and adjust dlen accordingly. bufindex = self.total_scanned - self.total_read if bufindex > 0: # If the total_scanned > total_read, then the total_scanned offset is in a subsequent block. # Set i to bufindex, which will cause i to be greater than dlen and this block will be skipped. i = bufindex elif bufindex < 0: # If the total_scanned offset is less than total_read, then the total_scanned offset is # somewhere inside this block. Set i to index into the block appropriately. i = dlen + bufindex else: # If the total_scanned offset ends at the end of this block, don't scan any of this block i = dlen # Scan through each block of data looking for signatures while i < dlen: smart = {} results = [] results_offset = -1 pre_filter_ok = False smart_jump_done = False # Pre-filter data by checking to see if the parser thinks this might be a valid match. # This eliminates unnecessary calls into libmagic, which are very expensive. # # Ideally, this should be done in the MagicParser class, but function calls are expensive. # Doing it here greatly decreases the scan time. if self.smart.pre_filter: for (sig_offset, sigset) in signature_set: if data[i+sig_offset:i+sig_offset+self.parser.MATCH_INDEX_SIZE] in sigset: pre_filter_ok = True break else: pre_filter_ok = True if pre_filter_ok: # Pass the data to libmagic, and split out multiple results into a list for magic_result in self.parser.split(self.magic.buffer(data[i:i+self.MAX_SIGNATURE_SIZE])): # Some file names are not NULL byte terminated, but rather their length is # specified in a size field. To ensure these are not marked as invalid due to # non-printable characters existing in the file name, parse the filename(s) and # trim them to the specified filename length, if one was specified. magic_result = self.smart._parse_raw_strings(magic_result) # Make sure this is a valid result before further processing if not self.filter.invalid(magic_result): # The smart filter parser returns a dictionary of keyword values and the signature description. smart = self.smart.parse(magic_result) # Validate the jump value and check if the response description should be displayed if smart['jump'] > -1 and self._should_display(smart['description']): # If multiple results are returned and one of them has smart['jump'] set to a non-zero value, # the calculated results offset will be wrong since i will have been incremented. Only set the # results_offset value when the first match is encountered. if results_offset < 0: results_offset = offset + smart['adjust'] + self.total_scanned # Double check to make sure the smart['adjust'] value is sane. # If it makes results_offset negative, then it is not sane. if results_offset >= 0: # Extract the result, if it matches one of the extract rules and is not a delayed extract. if self.extractor.enabled and not (self.extractor.delayed and smart['delay']): # If the signature did not specify a size, extract to the end of the file. if smart['size'] == 0: smart['size'] = fsize-results_offset smart['extract'] = self.extractor.extract( results_offset, smart['description'], target_file, smart['size'], name=smart['name']) # This appears to be a valid result, so append it to the results list. results.append(smart) # Jump to the offset specified by jump. Only do this once, so that if multiple results # are returned each of which specify a jump offset, only the first will be honored. if smart['jump'] > 0 and not smart_jump_done: # Once a jump offset has been honored, we need to start scanning every byte since the # jump offset may have thrown off the original alignment. In terms of speed this is fine, # since the jump offset usually saves more time anyway. If this is not what the user # wanted/intended, disabling pre filtering will disable jump offset processing completely. align = self.DEFAULT_BYTE_ALIGNMENT smart_jump_done = True i += (smart['jump'] - align) self.total_scanned += (smart['jump'] - align) # Did we find any valid results? if results_offset >= 0: scan_results[results_offset] = results if callback is not None: callback(results_offset, results) # Track the number of bytes scanned in this block, and the total number of bytes scanned. i += align self.total_scanned += align # Sort the results before returning them scan_items = scan_results.items() scan_items.sort() # Do delayed extraction, if specified. if self.extractor.enabled and self.extractor.delayed: scan_items = self.extractor.delayed_extract(scan_items, target_file, fsize) return scan_items def _should_display(self, data): ''' Determines if a result string should be displayed to the user or not. @data - Display string. Returns True if the string should be displayed. Returns False if the string should not be displayed. ''' return (data and data is not None and not self.filter.invalid(data) and self.filter.filter(data) != self.filter.FILTER_EXCLUDE) def _read_block(self, fd): ''' Reads in a block of data from the target file. @fd - File object for the target file. Returns a tuple of (file block data, block data length). ''' dlen = 0 data = None # Read in READ_BLOCK_SIZE plus MAX_SIGNATURE_SIZE bytes, but return a max dlen value # of READ_BLOCK_SIZE. This ensures that there is a MAX_SIGNATURE_SIZE buffer at the # end of the returned data in case a signature is found at or near data[dlen]. rlen = self.READ_BLOCK_SIZE + self.MAX_SIGNATURE_SIZE if self.total_read < self.scan_length: data = fd.read(rlen) if data and data is not None: # Get the actual length of the read in data dlen = len(data) # If we've read in more data than the scan length, truncate the dlen value if (self.total_read + dlen) >= self.scan_length: dlen = self.scan_length - self.total_read # If dlen is the expected rlen size, it should be set to READ_BLOCK_SIZE elif dlen == rlen: dlen = self.READ_BLOCK_SIZE # Increment self.total_read to reflect the amount of data that has been read # for processing (actual read size is larger of course, due to the MAX_SIGNATURE_SIZE # buffer of data at the end of each block). self.total_read += dlen # Seek to the self.total_read offset so the next read can pick up where this one left off fd.seek(self.total_read) return (data, dlen) ================================================ FILE: src/binwalk-1.0/src/binwalk/common.py ================================================ # Common functions. import os import re def file_size(filename): ''' Obtains the size of a given file. @filename - Path to the file. Returns the size of the file. ''' # Using open/lseek works on both regular files and block devices fd = os.open(filename, os.O_RDONLY) try: return os.lseek(fd, 0, os.SEEK_END) except Exception, e: raise Exception("file_size failed to obtain the size of '%s': %s" % (filename, str(e))) finally: os.close(fd) def str2int(string): ''' Attempts to convert string to a base 10 integer; if that fails, then base 16. @string - String to convert to an integer. Returns the integer value on success. Throws an exception if the string cannot be converted into either a base 10 or base 16 integer value. ''' try: return int(string) except: return int(string, 16) def strip_quoted_strings(string): ''' Strips out data in between double quotes. @string - String to strip. Returns a sanitized string. ''' # This regex removes all quoted data from string. # Note that this removes everything in between the first and last double quote. # This is intentional, as printed (and quoted) strings from a target file may contain # double quotes, and this function should ignore those. However, it also means that any # data between two quoted strings (ex: '"quote 1" you won't see me "quote 2"') will also be stripped. return re.sub(r'\"(.*)\"', "", string) def get_quoted_strings(string): ''' Returns a string comprised of all data in between double quotes. @string - String to get quoted data from. Returns a string of quoted data on success. Returns a blank string if no quoted data is present. ''' try: # This regex grabs all quoted data from string. # Note that this gets everything in between the first and last double quote. # This is intentional, as printed (and quoted) strings from a target file may contain # double quotes, and this function should ignore those. However, it also means that any # data between two quoted strings (ex: '"quote 1" non-quoted data "quote 2"') will also be included. return re.findall(r'\"(.*)\"', string)[0] except: return '' ================================================ FILE: src/binwalk-1.0/src/binwalk/config/extract.conf ================================================ ################################################################################################################# # Default extract rules loaded when --extract is specified. # # :: # # Note that %e is a place holder for the extracted file name. ################################################################################################################# # Assumes these utilities are installed in $PATH. gzip compressed data:gz:gzip -d -f '%e' lzma compressed data:7z:7zr e -y '%e' bzip2 compressed data:bz2:bzip2 -d -f '%e' zip archive data:zip:jar xf '%e' # jar does a better job of unzipping than unzip does... posix tar archive:tar:tar xvf '%e' # These assume the firmware-mod-kit is installed to /opt/firmware-mod-kit. # If not, change the file paths appropriately. squashfs filesystem:squashfs:/opt/firmware-mod-kit/trunk/unsquashfs_all.sh '%e' jffs2 filesystem:jffs2:/opt/firmware-mod-kit/trunk/src/jffs2/unjffs2 '%e' # requires root cpio archive:cpio:/opt/firmware-mod-kit/trunk/uncpio.sh '%e' # Extract, but don't run anything ext2 filesystem:ext2 romfs filesystem:romfs cramfs filesystem:cramfs private key:key ================================================ FILE: src/binwalk-1.0/src/binwalk/config.py ================================================ import os class Config: ''' Binwalk configuration class, used for accessing user and system file paths. After instatiating the class, file paths can be accessed via the self.paths dictionary. System file paths are listed under the 'system' key, user file paths under the 'user' key. For example, to get the path to both the user and system binwalk magic files: from binwalk import Config conf = Config() user_binwalk_file = conf.paths['user'][conf.BINWALK_MAGIC_FILE] system_binwalk_file = conf.paths['system'][conf.BINWALK_MAGIC_FILE] There is also an instance of this class available via the Binwalk.config object: import binwalk bw = binwalk.Binwalk() user_binwalk_file = bw.config.paths['user'][conf.BINWALK_MAGIC_FILE] system_binwalk_file = bw.config.paths['system'][conf.BINWALK_MAGIC_FILE] Valid file names under both the 'user' and 'system' keys are as follows: o BINWALK_MAGIC_FILE - Path to the default binwalk magic file. o BINCAST_MAGIC_FILE - Path to the bincast magic file (used when -C is specified with the command line binwalk script) o BINARCH_MAGIC_FILE - Path to the binarch magic file (used when -A is specified with the command line binwalk script) o EXTRACT_FILE - Path to the extract configuration file (used when -e is specified with the command line binwalk script) ''' # Release version VERSION = "1.0" # Sub directories BINWALK_USER_DIR = ".binwalk" BINWALK_MAGIC_DIR = "magic" BINWALK_CONFIG_DIR = "config" # File names EXTRACT_FILE = "extract.conf" BINWALK_MAGIC_FILE = "binwalk" BINCAST_MAGIC_FILE = "bincast" BINARCH_MAGIC_FILE = "binarch" def __init__(self): ''' Class constructor. Enumerates file paths and populates self.paths. ''' # Path to the user binwalk directory self.user_dir = self._get_user_dir() # Path to the system wide binwalk directory self.system_dir = self._get_system_dir() # Dictionary of all absolute user/system file paths self.paths = { 'user' : {}, 'system' : {}, } # Build the paths to all user-specific files self.paths['user'][self.BINWALK_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINWALK_MAGIC_FILE) self.paths['user'][self.BINCAST_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINCAST_MAGIC_FILE) self.paths['user'][self.BINARCH_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINARCH_MAGIC_FILE) self.paths['user'][self.EXTRACT_FILE] = self._user_file(self.BINWALK_CONFIG_DIR, self.EXTRACT_FILE) # Build the paths to all system-wide files self.paths['system'][self.BINWALK_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINWALK_MAGIC_FILE) self.paths['system'][self.BINCAST_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINCAST_MAGIC_FILE) self.paths['system'][self.BINARCH_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINARCH_MAGIC_FILE) self.paths['system'][self.EXTRACT_FILE] = self._system_file(self.BINWALK_CONFIG_DIR, self.EXTRACT_FILE) def _get_system_dir(self): ''' Find the directory where the binwalk module is installed on the system. ''' try: root = __file__ if os.path.islink(root): root = os.path.realpath(root) return os.path.dirname(os.path.abspath(root)) except: return '' def _get_user_dir(self): ''' Get the user's home directory. ''' try: # This should work in both Windows and Unix environments return os.getenv('USERPROFILE') or os.getenv('HOME') except: return '' def _file_path(self, dirname, filename): ''' Builds an absolute path and creates the directory and file if they don't already exist. @dirname - Directory path. @filename - File name. Returns a full path of 'dirname/filename'. ''' if not os.path.exists(dirname): try: os.makedirs(dirname) except: pass fpath = os.path.join(dirname, filename) if not os.path.exists(fpath): try: open(fpath, "w").close() except: pass return fpath def _user_file(self, subdir, basename): ''' Gets the full path to the 'subdir/basename' file in the user binwalk directory. @subdir - Subdirectory inside the user binwalk directory. @basename - File name inside the subdirectory. Returns the full path to the 'subdir/basename' file. ''' return self._file_path(os.path.join(self.user_dir, self.BINWALK_USER_DIR, subdir), basename) def _system_file(self, subdir, basename): ''' Gets the full path to the 'subdir/basename' file in the system binwalk directory. @subdir - Subdirectory inside the system binwalk directory. @basename - File name inside the subdirectory. Returns the full path to the 'subdir/basename' file. ''' return self._file_path(os.path.join(self.system_dir, subdir), basename) ================================================ FILE: src/binwalk-1.0/src/binwalk/extractor.py ================================================ import os import sys import shlex import tempfile import subprocess from config import * from common import file_size class Extractor: ''' Extractor class, responsible for extracting files from the target file and executing external applications, if requested. An instance of this class is accessible via the Binwalk.extractor object. Example usage: import binwalk bw = binwalk.Binwalk() # Create extraction rules for scan results containing the string 'gzip compressed data' and 'filesystem'. # The former will be saved to disk with a file extension of 'gz' and the command 'gunzip ' will be executed (note the %e placeholder). # The latter will be saved to disk with a file extension of 'fs' and no command will be executed. # These rules will take precedence over subsequent rules with the same match string. bw.extractor.add_rule(['gzip compressed data:gz:gunzip %e', 'filesystem:fs']) # Load the extraction rules from the default extract.conf file(s). bw.extractor.load_defaults() # Run the binwalk scan. bw.scan('firmware.bin') ''' # Extract rules are delimited with a colon. # :[:] RULE_DELIM = ':' # Comments in the extract.conf files start with a pound COMMENT_DELIM ='#' # Place holder for the extracted file name in the command FILE_NAME_PLACEHOLDER = '%e' def __init__(self, verbose=False): ''' Class constructor. @verbose - Set to True to display the output from any executed external applications. Returns None. ''' self.config = Config() self.enabled = False self.delayed = False self.verbose = verbose self.extract_rules = {} self.remove_after_execute = False def add_rule(self, rule): ''' Adds a set of rules to the extraction rule list. @rule - Rule string, or list of rule strings, in the format :[:] Returns None. ''' r = { 'extension' : '', 'cmd' : '' } if type(rule) != type([]): rules = [rule] else: rules = rule for rule in rules: r['cmd'] = '' r['extension'] = '' try: values = self._parse_rule(rule) match = values[0].lower() r['extension'] = values[1] r['cmd'] = values[2] except: pass # Verify that the match string and file extension were retrieved. # Only add the rule if it is a new one (first come, first served). if match and r['extension'] and not self.extract_rules.has_key(match): self.extract_rules[match] = {} self.extract_rules[match]['cmd'] = r['cmd'] self.extract_rules[match]['extension'] = r['extension'] # Once any rule is added, set self.enabled to True self.enabled = True def enable_delayed_extract(self, tf=None): ''' Enables / disables the delayed extraction feature. This feature ensures that certian supported file types will not contain extra data at the end of the file when they are extracted, but also means that these files will not be extracted until the end of the scan. @tf - Set to True to enable, False to disable. Returns the current delayed extraction setting. ''' if tf is not None: self.delayed = tf return self.delayed def load_from_file(self, fname): ''' Loads extraction rules from the specified file. @fname - Path to the extraction rule file. Returns None. ''' try: # Process each line from the extract file, ignoring comments for rule in open(fname).readlines(): self.add_rule(rule.split(self.COMMENT_DELIM, 1)[0]) except Exception, e: raise Exception("Extractor.load_from_file failed to load file '%s': %s" % (fname, str(e))) def load_defaults(self): ''' Loads default extraction rules from the user and system extract.conf files. Returns None. ''' # Load the user extract file first to ensure its rules take precedence. extract_files = [ self.config.paths['user'][self.config.EXTRACT_FILE], self.config.paths['system'][self.config.EXTRACT_FILE], ] for extract_file in extract_files: try: self.load_from_file(extract_file) except Exception, e: if self.verbose: raise Exception("Extractor.load_defaults failed to load file '%s': %s" % (extract_file, str(e))) def cleanup_extracted_files(self, tf=None): ''' Set the action to take after a file is extracted. @tf - If set to True, extracted files will be cleaned up after running a command against them. If set to False, extracted files will not be cleaned up after running a command against them. If set to None or not specified, the current setting will not be changed. Returns the current cleanup status (True/False). ''' if tf is not None: self.remove_after_execute = tf return self.remove_after_execute def extract(self, offset, description, file_name, size, name=None): ''' Extract an embedded file from the target file, if it matches an extract rule. Called automatically by Binwalk.scan(). @offset - Offset inside the target file to begin the extraction. @description - Description of the embedded file to extract, as returned by libmagic. @file_name - Path to the target file. @size - Number of bytes to extract. @name - Name to save the file as. Returns the name of the extracted file (blank string if nothing was extracted). ''' cleanup_extracted_fname = True rule = self._match(description) if rule is not None: fname = self._dd(file_name, offset, size, rule['extension'], output_file_name=name) if rule['cmd']: # Many extraction utilities will extract the file to a new file, just without # the file extension (i.e., myfile.7z => myfile). If the presumed resulting # file name already exists before executing the extract command, do not attempt # to clean it up even if its resulting file size is 0. if self.remove_after_execute: extracted_fname = os.path.splitext(fname)[0] if os.path.exists(extracted_fname): cleanup_extracted_fname = False # Execute the specified command against the extracted file self._execute(rule['cmd'], fname) # Only clean up files if remove_after_execute was specified if self.remove_after_execute: # Remove the original file that we extracted try: os.unlink(fname) except: pass # If the command worked, assume it removed the file extension from the extracted file # If the extracted file name file exists and is empty, remove it if cleanup_extracted_fname and os.path.exists(extracted_fname) and file_size(extracted_fname) == 0: try: os.unlink(extracted_fname) except: pass else: fname = '' return fname def delayed_extract(self, results, file_name, size): ''' Performs a delayed extraction (see self.enable_delayed_extract). Called internally by Binwalk.Scan(). @results - A list of dictionaries of all the scan results. @file_name - The path to the scanned file. @size - The size of the scanned file. Returns an updated results list containing the names of the newly extracted files. ''' index = 0 info_count = 0 nresults = results for (offset, infos) in results: info_count = 0 for info in infos: ninfos = infos if info['delay']: end_offset = self._entry_offset(index, results, info['delay']) if end_offset == -1: extract_size = size else: extract_size = (end_offset - offset) ninfos[info_count]['extract'] = self.extract(offset, info['description'], file_name, extract_size, info['name']) nresults[index] = (offset, ninfos) info_count += 1 index += 1 return nresults def _entry_offset(self, index, entries, description): ''' Gets the offset of the first entry that matches the description. @index - Index into the entries list to begin searching. @entries - Dictionary of result entries. @description - Case insensitive description. Returns the offset, if a matching description is found. Returns -1 if a matching description is not found. ''' description = description.lower() for (offset, infos) in entries[index:]: for info in infos: if info['description'].lower().startswith(description): return offset return -1 def _match(self, description): ''' Check to see if the provided description string matches an extract rule. Called internally by self.extract(). @description - Description string to check. Returns the associated rule dictionary if a match is found. Returns None if no match is found. ''' description = description.lower() for (m, rule) in self.extract_rules.iteritems(): if m in description: return rule return None def _parse_rule(self, rule): ''' Parses an extraction rule. @rule - Rule string. Returns an array of ['', '', '']. ''' return rule.strip().split(self.RULE_DELIM, 2) def _dd(self, file_name, offset, size, extension, output_file_name=None): ''' Extracts a file embedded inside the target file. @file_name - Path to the target file. @offset - Offset inside the target file where the embedded file begins. @size - Number of bytes to extract. @extension - The file exension to assign to the extracted file on disk. @output_file_name - The requested name of the output file. Returns the extracted file name. ''' # Default extracted file name is . altname = "%X.%s" % (offset, extension) if not output_file_name or output_file_name is None: fname = altname else: fname = "%s.%s" % (output_file_name, extension) # Sanitize output file name of invalid/dangerous characters (like file paths) fname = os.path.basename(fname) try: # Open the target file and seek to the offset fdin = open(file_name, "rb") fdin.seek(offset) # Open the extracted file try: fdout = open(fname, "wb") except: # Fall back to the alternate name if the requested name fails fname = altname fdout = open(fname, "wb") # Read size bytes from target file and write it to the extracted file fdout.write(fdin.read(size)) # Cleanup fdout.close() fdin.close() except Exception, e: raise Exception("Extractor.dd failed to extract data from '%s' to '%s': %s" % (file_name, fname, str(e))) return fname def _execute(self, cmd, fname): ''' Execute a command against the specified file. @cmd - Command to execute. @fname - File to run command against. Returns None. ''' tmp = None # If not in verbose mode, create a temporary file to redirect stdout and stderr to if not self.verbose: tmp = tempfile.TemporaryFile() try: # Replace all instances of FILE_NAME_PLACEHOLDER in the command with fname cmd = cmd.replace(self.FILE_NAME_PLACEHOLDER, fname) # Execute. subprocess.call(shlex.split(cmd), stdout=tmp, stderr=tmp) except Exception, e: sys.stderr.write("WARNING: Extractor.execute failed to run '%s': %s\n" % (cmd, str(e))) if tmp is not None: tmp.close() ================================================ FILE: src/binwalk-1.0/src/binwalk/filter.py ================================================ import common from smartsig import SmartSignature class MagicFilter: ''' Class to filter libmagic results based on include/exclude rules and false positive detection. An instance of this class is available via the Binwalk.filter object. Example code which creates include, exclude, and grep filters before running a Binwalk scan: import binwalk bw = binwalk.Binwalk() # Include all signatures whose descriptions contain the string 'filesystem' in the first line of the signature, even if those signatures are normally excluded. # Note that if exclusive=False was specified, this would merely add these signatures to the default signatures. # Since exclusive=True (the default) has been specified, ONLY those matching signatures will be loaded; all others will be ignored. bw.filter.include('filesystem') # Exclude all signatures whose descriptions contain the string 'jffs2', even if those signatures are normally included. # In this case, we are now searching for all filesystem signatures, except JFFS2. bw.filter.exclude('jffs2') # Add a grep filter. Unlike the include and exclude filters, it does not affect which results are returned by Binwalk.scan(), but it does affect which results # are printed by Binwalk.display.results(). This is particularly useful for cases like the bincast scan, where multiple lines of results are returned per offset, # but you only want certian ones displayed. In this case, only file systems whose description contain the string '2012' will be displayed. bw.filter.grep(filters=['2012']) bw.scan('firmware.bin') ''' # If the result returned by libmagic is "data" or contains the text # 'invalid' or a backslash are known to be invalid/false positives. DATA_RESULT = "data" INVALID_RESULTS = ["invalid", "\\"] INVALID_RESULT = "invalid" NON_PRINTABLE_RESULT = "\\" FILTER_INCLUDE = 0 FILTER_EXCLUDE = 1 def __init__(self, show_invalid_results=False): ''' Class constructor. @show_invalid_results - Set to True to display results marked as invalid. Returns None. ''' self.filters = [] self.grep_filters = [] self.show_invalid_results = show_invalid_results self.exclusive_filter = False self.smart = SmartSignature(self) def include(self, match, exclusive=True): ''' Adds a new filter which explicitly includes results that contain the specified matching text. @match - Case insensitive text, or list of texts, to match. @exclusive - If True, then results that do not explicitly contain a FILTER_INCLUDE match will be excluded. If False, signatures that contain the FILTER_INCLUDE match will be included in the scan, but will not cause non-matching results to be excluded. Returns None. ''' include_filter = { 'type' : self.FILTER_INCLUDE, 'filter' : '' } if type(match) != type([]): matches = [match] else: matches = match for m in matches: if m: if exclusive and not self.exclusive_filter: self.exclusive_filter = True include_filter['filter'] = m.lower() self.filters.append(include_filter) def exclude(self, match): ''' Adds a new filter which explicitly excludes results that contain the specified matching text. @match - Case insensitive text, or list of texts, to match. Returns None. ''' exclude_filter = { 'type' : self.FILTER_EXCLUDE, 'filter' : '' } if type(match) != type([]): matches = [match] else: matches = match for m in matches: if m: exclude_filter['filter'] = m.lower() self.filters.append(exclude_filter) def filter(self, data): ''' Checks to see if a given string should be excluded from or included in the results. Called internally by Binwalk.scan(). @data - String to check. Returns FILTER_INCLUDE if the string should be included. Returns FILTER_EXCLUDE if the string should be excluded. ''' data = data.lower() # Loop through the filters to see if any of them are a match. # If so, return the registered type for the matching filter (FILTER_INCLUDE | FILTER_EXCLUDE). for f in self.filters: if f['filter'] in data: return f['type'] # If there was not explicit match and exclusive filtering is enabled, return FILTER_EXCLUDE. if self.exclusive_filter: return self.FILTER_EXCLUDE return self.FILTER_INCLUDE def invalid(self, data): ''' Checks if the given string contains invalid data. Called internally by Binwalk.scan(). @data - String to validate. Returns True if data is invalid, False if valid. ''' # A result of 'data' is never ever valid. if data == self.DATA_RESULT: return True # If showing invalid results, just return False. if self.show_invalid_results: return False # Don't include quoted strings or keyword arguments in this search, as # strings from the target file may legitimately contain the INVALID_RESULT text. if self.INVALID_RESULT in common.strip_quoted_strings(self.smart._strip_tags(data)): return True # There should be no non-printable data in any of the data if self.NON_PRINTABLE_RESULT in data: return True return False def grep(self, data=None, filters=[]): ''' Add or check case-insensitive grep filters against the supplied data string. @data - Data string to check grep filters against. Not required if filters is specified. @filters - Filter, or list of filters, to add to the grep filters list. Not required if data is specified. Returns None if data is not specified. If data is specified, returns True if the data contains a grep filter, or if no grep filters exist. If data is specified, returns False if the data does not contain any grep filters. ''' # Add any specified filters to self.grep_filters if filters: if type(filters) != type([]): gfilters = [filters] else: gfilters = filters for gfilter in gfilters: # Filters are case insensitive self.grep_filters.append(gfilter.lower()) # Check the data against all grep filters until one is found if data is not None: # If no grep filters have been created, always return True if not self.grep_filters: return True # Filters are case insensitive data = data.lower() # If a filter exists in data, return True for gfilter in self.grep_filters: if gfilter in data: return True # Else, return False return False return None def clear(self): ''' Clears all include, exclude and grep filters. Retruns None. ''' self.filters = [] self.grep_filters = [] ================================================ FILE: src/binwalk-1.0/src/binwalk/magic/binarch ================================================ # MIPS prologue # addiu $sp, -XX # 27 BD FF XX 1 string \377\275\47 MIPSEL function prologue 0 string \47\275\377 MIPS function prologue # MIPS epilogue # jr $ra 0 belong 0x03e00008 MIPS function epilogue 0 lelong 0x03e00008 MIPSEL function epilogue # PowerPC epilogue # blr 0 belong 0x4E800020 PowerPC big endian function epilogue 0 lelong 0x4E800020 PowerPC little endian function epilogue # ARM prologue # STMFD SP!, {XX} 0 beshort 0xE92D ARMEB function prologue 2 leshort 0xE92D ARM function prologue # ARM epilogue # LDMFD SP!, {XX} 0 beshort 0xE8BD ARMEB function epilogue 2 leshort 0xE8BD ARM function epilogue # x86 epilogue # push ebp # move ebp, esp 0 string \x55\x89\xE5 Intel x86 function epilogue ================================================ FILE: src/binwalk-1.0/src/binwalk/magic/bincast ================================================ 0 belong x Hex: 0x%.8X #0 string x String: %s 0 lelong x Little Endian Long: %d 0 belong x Big Endian Long: %d 0 leshort x Little Endian Short: %d 0 beshort x Big Endian Short: %d 0 ledate x Little Endian Date: %s 0 bedate x Big Endian Date: %s ================================================ FILE: src/binwalk-1.0/src/binwalk/magic/binwalk ================================================ # ----------------------------Archive Formats-------------------------------------- # POSIX tar archives 0 string ustar\000 POSIX tar archive{offset-adjust:-257} 0 string ustar\040\040\000 POSIX tar archive (GNU){offset-adjust:-257} # JAR archiver (.j), this is the successor to ARJ, not Java's JAR (which is essentially ZIP) 0 string \x1aJar\x1b JAR (ARJ Software, Inc.) archive data{offset-adjust:-14} 0 string JARCS JAR (ARJ Software, Inc.) archive data # ARJ archiver (jason@jarthur.Claremont.EDU) 0 leshort 0xea60 ARJ archive data >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: "%s", >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # RAR archiver (Greg Roelofs, newt@uchicago.edu) 0 string Rar! RAR archive data # HPACK archiver (Peter Gutmann, pgut1@cs.aukuni.ac.nz) 0 string HPAK HPACK archive data # JAM Archive volume format, by Dmitry.Kohmanyuk@UA.net 0 string \351,\001JAM JAM archive # LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) 0 string -lzs- LHa 2.x? archive data [lzs] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh\40- LHa 2.x? archive data [lh ] [NSRL|LHA2]{offset-adjust:-2} 0 string -lhd- LHa 2.x? archive data [lhd] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh2- LHa 2.x? archive data [lh2] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh3- LHa 2.x? archive data [lh3] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh4- LHa (2.x) archive data [lh4] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh5- LHa (2.x) archive data [lh5] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh6- LHa (2.x) archive data [lh6] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh7- LHa (2.x) archive data [lh7] [NSRL|LHA2]{offset-adjust:-2} # cpio archives # # The SVR4 "cpio(4)" hints that there are additional formats, but they # are defined as "short"s; I think all the new formats are # character-header formats and thus are strings, not numbers. #0 string 070707 ASCII cpio archive (pre-SVR4 or odc) 0 string 070701 ASCII cpio archive (SVR4 with no CRC), >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} 0 string 070702 ASCII cpio archive (SVR4 with CRC) >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} # HP Printer Job Language # The header found on Win95 HP plot files is the "Silliest Thing possible" # (TM) # Every driver puts the language at some random position, with random case # (LANGUAGE and Language) # For example the LaserJet 5L driver puts the "PJL ENTER LANGUAGE" in line 10 # From: Uwe Bonnes # 0 string \033%-12345X@PJL HP Printer Job Language data >&0 string >\0 "%s" >>&0 string >\0 "%s" >>>&0 string >\0 "%s" >>>>&0 string >\0 "%s" #------------------------------------------------------------------------------ # # RPM: file(1) magic for Red Hat Packages Erik Troan (ewt@redhat.com) # 0 belong 0xedabeedb RPM >4 byte x v%d >6 beshort 0 bin >6 beshort 1 src >8 beshort 1 i386 >8 beshort 2 Alpha >8 beshort 3 Sparc >8 beshort 4 MIPS >8 beshort 5 PowerPC >8 beshort 6 68000 >8 beshort 7 SGI >8 beshort 8 RS6000 >8 beshort 9 IA64 >8 beshort 10 Sparc64 >8 beshort 11 MIPSel >8 beshort 12 ARM >10 string x "%s" #---------------------------Bootloaders-------------------------------- # CFE bootloader 0 string CFE1CFE1 CFE boot loader, little endian 0 string 1EFC1EFC CFE boot loader, big endian #------------------Compression Formats----------------------------- # AFX compressed files (Wolfram Kleff) 0 string -afx- AFX compressed file data{offset-adjust:-2} # bzip2 0 string BZh91AY&SY bzip2 compressed data, block size = 900k 0 string BZh81AY&SY bzip2 compressed data, block size = 800k 0 string BZh71AY&SY bzip2 compressed data, block size = 700k 0 string BZh61AY&SY bzip2 compressed data, block size = 600k 0 string BZh51AY&SY bzip2 compressed data, block size = 500k 0 string BZh41AY&SY bzip2 compressed data, block size = 400k 0 string BZh31AY&SY bzip2 compressed data, block size = 300k 0 string BZh21AY&SY bzip2 compressed data, block size = 200k 0 string BZh11AY&SY bzip2 compressed data, block size = 100k # lzop from 0 string \x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a lzop compressed data >9 beshort <0x0940 >>9 byte&0xf0 =0x00 - version 0. >>9 beshort&0x0fff x \b%03x, >>13 byte 1 LZO1X-1, >>13 byte 2 LZO1X-1(15), >>13 byte 3 LZO1X-999, ## >>22 bedate >0 last modified: %s, >>14 byte =0x00 os: MS-DOS >>14 byte =0x01 os: Amiga >>14 byte =0x02 os: VMS >>14 byte =0x03 os: Unix >>14 byte =0x05 os: Atari >>14 byte =0x06 os: OS/2 >>14 byte =0x07 os: MacOS >>14 byte =0x0A os: Tops/20 >>14 byte =0x0B os: WinNT >>14 byte =0x0E os: Win32 >9 beshort >0x0939 >>9 byte&0xf0 =0x00 - version 0. >>9 byte&0xf0 =0x10 - version 1. >>9 byte&0xf0 =0x20 - version 2. >>9 beshort&0x0fff x \b%03x, >>15 byte 1 LZO1X-1, >>15 byte 2 LZO1X-1(15), >>15 byte 3 LZO1X-999, ## >>25 bedate >0 last modified: %s, >>17 byte =0x00 os: MS-DOS >>17 byte =0x01 os: Amiga >>17 byte =0x02 os: VMS >>17 byte =0x03 os: Unix >>17 byte =0x05 os: Atari >>17 byte =0x06 os: OS/2 >>17 byte =0x07 os: MacOS >>17 byte =0x0A os: Tops/20 >>17 byte =0x0B os: WinNT >>17 byte =0x0E os: Win32 # lzip 0 string LZIP lzip compressed data >4 byte x \b, version: %d # LZO 0 string \211LZO\000\015\012\032\012 LZO compressed data # 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) # http://www.7-zip.org or DOC/7zFormat.txt # 0 string 7z\274\257\047\034 7-zip archive data, >6 byte x version %d >7 byte x \b.%d # standard unix compress 0 beshort 0x1f9d compress'd data >2 byte&0x80 >0 block compressed >2 byte&0x1f !16 invalid >2 byte&0x1f x %d bits # http://tukaani.org/xz/xz-file-format.txt 0 string \xFD\x37\x7a\x58\x5a\x00 xz compressed data # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) # Edited by Chris Chittleborough , March 2002 # * Original filename is only at offset 10 if "extra field" absent # * Produce shorter output - notably, only report compression methods # other than 8 ("deflate", the only method defined in RFC 1952). 0 string \037\213\x08 gzip compressed data >3 byte &0x01 \b, ASCII >3 byte &0x02 \b, has CRC >3 byte &0x04 \b, extra field >3 byte&0xC =0x08 >>10 string x \b{file-name:%s} >>10 string x \b, was "%s" >3 byte &0x10 \b, has comment >9 byte =0x00 \b, from FAT filesystem (MS-DOS, OS/2, NT) >9 byte =0x01 \b, from Amiga >9 byte =0x02 \b, from VMS >9 byte =0x03 \b, from Unix >9 byte =0x04 \b, from VM/CMS >9 byte =0x05 \b, from Atari >9 byte =0x06 \b, from HPFS filesystem (OS/2, NT) >9 byte =0x07 \b, from MacOS >9 byte =0x08 \b, from Z-System >9 byte =0x09 \b, from CP/M >9 byte =0x0A \b, from TOPS/20 >9 byte =0x0B \b, from NTFS filesystem (NT) >9 byte =0x0C \b, from QDOS >9 byte =0x0D \b, from Acorn RISCOS >9 byte >0x0D \b, invalid source >9 byte <0 \b, invalid source >3 byte &0x20 \b, encrypted (invalid) # Dates before 1992 are invalid, unless of course you're DD-WRT in which # case you don't know how to set a date in your gzip files. Brilliant. >4 lelong =0 \b, NULL date: >4 lelong <0 \b, invalid date: >4 lelong >0 >>4 lelong <694224000 \b, invalid date: >>4 lelong =694224000 \b, invalid date: >>4 lelong >694224000 \b, last modified: >4 ledate x %s >8 byte 2 \b, max compression >8 byte 4 \b, max speed # Zlib signatures 0 beshort 0x789C zlib compressed data 0 beshort 0x78DA zlib compressed data 0 beshort 0x7801 zlib compressed data # Supplementary magic data for the file(1) command to support # rzip(1). The format is described in magic(5). # # Copyright (C) 2003 by Andrew Tridgell. You may do whatever you want with # this file. # 0 string RZIP rzip compressed data >4 byte x - version %d >5 byte x \b.%d >6 belong x (%d bytes) # ZIP compression (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) 0 string PK\003\004 Zip archive data, >4 byte 0x00 v0.0 >4 byte 0x09 at least v0.9 to extract, >4 byte 0x0a at least v1.0 to extract, >4 byte 0x0b at least v1.1 to extract, >0x161 string WINZIP WinZIP self-extracting, >4 byte 0x14 >>30 ubelong !0x6d696d65 at least v2.0 to extract, >18 lelong !0 >>18 lelong <0 invalid >>18 lelong x compressed size: %d, >22 lelong !0 >>22 lelong <0 invalid >>22 lelong x uncompressed size: %d,{extract-delay:end of zip archive} >30 string x {file-name:{raw-replace}}name: {raw-replace} >26 leshort x {raw-string-length:%d} >30 string x {raw-string:%s >61 string x \b%s >92 string x \b%s >123 string x \b%s >154 string x \b%s} # ZIP footer 0 string PK\x05\x06 End of Zip archive >20 leshort x {offset-adjust:22+%d} >20 leshort >0 >>20 leshort x \b, comment: {raw-replace} >>20 leshort x {raw-string-length:%d} >>22 string x {raw-string:%s} # New LZMA format signature 0 string \xFFLZMA\x00 LZMA compressed data (new), >6 byte&0x10 0 single-block stream >6 byte&0x10 0x10 multi-block stream # See lzma file for LZMA signatures # Type: OpenSSL certificates/key files # From: Nicolas Collignon 0 string -----BEGIN\x20CERTIFICATE----- PEM certificate 0 string -----BEGIN\x20CERTIFICATE\x20REQ PEM certificate request 0 string -----BEGIN\x20RSA\x20PRIVATE PEM RSA private key 0 string -----BEGIN\x20DSA\x20PRIVATE PEM DSA private key # Type: OpenSSH key files # From: Nicolas Collignon 0 string SSH\x20PRIVATE\x20KEY OpenSSH RSA1 private key, >28 string >\0 version "%s" 0 string ssh-dss\x20 OpenSSH DSA public key 0 string ssh-rsa\x20 OpenSSH RSA public key # Type: Certificates/key files in DER format # From: Gert Hulselmans 0 string \x30\x82 Private key in DER format (PKCS#8), >4 string !\x02\x01\x00 invalid, >>2 beshort x header length: 4, sequence length: %d 0 string \x30\x82 Certificate in DER format (x509 v3), >4 string !\x30\x82 invalid, >>2 beshort x header length: 4, sequence length: %d # GnuPG # The format is very similar to pgp 0 string \001gpg GPG key trust database >4 byte x version %d 0 beshort 0x9901 GPG key public ring # This magic is not particularly good, as the keyrings don't have true # magic. Nevertheless, it covers many keyrings. #------------------------------------------------------------------------------ # Mavroyanopoulos Nikos # mcrypt: file(1) magic for mcrypt 2.2.x; 0 string \0m\3 mcrypt 2.5 encrypted data, >4 byte 0 invalid >4 string >\0 algorithm: "%s", >>&1 leshort <1 invalid >>&1 leshort >0 keysize: %d bytes, >>>&0 byte 0 invalid >>>&0 string >\0 mode: "%s", 0 string \0m\2 mcrypt 2.2 encrypted data, >3 byte 0 algorithm: blowfish-448, >3 byte 1 algorithm: DES, >3 byte 2 algorithm: 3DES, >3 byte 3 algorithm: 3-WAY, >3 byte 4 algorithm: GOST, >3 byte 6 algorithm: SAFER-SK64, >3 byte 7 algorithm: SAFER-SK128, >3 byte 8 algorithm: CAST-128, >3 byte 9 algorithm: xTEA, >3 byte 10 algorithm: TWOFISH-128, >3 byte 11 algorithm: RC2, >3 byte 12 algorithm: TWOFISH-192, >3 byte 13 algorithm: TWOFISH-256, >3 byte 14 algorithm: blowfish-128, >3 byte 15 algorithm: blowfish-192, >3 byte 16 algorithm: blowfish-256, >3 byte 100 algorithm: RC6, >3 byte 101 algorithm: IDEA, >3 byte <0 invalid algorithm >3 byte >101 invalid algorithm, >3 byte >16 >>3 byte <100 invalid algorithm, >4 byte 0 mode: CBC, >4 byte 1 mode: ECB, >4 byte 2 mode: CFB, >4 byte 3 mode: OFB, >4 byte 4 mode: nOFB, >4 byte <0 invalid mode, >4 byte >4 invalid mode, >5 byte 0 keymode: 8bit >5 byte 1 keymode: 4bit >5 byte 2 keymode: SHA-1 hash >5 byte 3 keymode: MD5 hash >5 byte <0 invalid keymode >5 byte >3 invalid keymode #------------------------------------------------------------------------------ # pgp: file(1) magic for Pretty Good Privacy # #0 beshort 0x9900 PGP key public ring #0 beshort 0x9501 PGP key security ring #0 beshort 0x9500 PGP key security ring #0 beshort 0xa600 PGP encrypted data 0 string -----BEGIN\040PGP PGP armored data >15 string PUBLIC\040KEY\040BLOCK- public key block >15 string MESSAGE- message >15 string SIGNED\040MESSAGE- signed message >15 string PGP\040SIGNATURE- signature #------------------Standard file formats------------------------------------ #------------------------------------------------------------------------------ # elf: file(1) magic for ELF executables # # We have to check the byte order flag to see what byte order all the # other stuff in the header is in. # # What're the correct byte orders for the nCUBE and the Fujitsu VPP500? # # updated by Daniel Quinlan (quinlan@yggdrasil.com) 0 string \177ELF ELF >4 byte 0 invalid class >4 byte 1 32-bit # only for MIPS - in the future, the ABI field of e_flags should be used. >>18 leshort 8 >>>36 lelong &0x20 N32 >>18 leshort 10 >>>36 lelong &0x20 N32 >>18 beshort 8 >>>36 belong &0x20 N32 >>18 beshort 10 >>>36 belong &0x20 N32 >4 byte 2 64-bit >5 byte 0 invalid byte order >5 byte 1 LSB # The official e_machine number for MIPS is now #8, regardless of endianness. # The second number (#10) will be deprecated later. For now, we still # say something if #10 is encountered, but only gory details for #8. >>18 leshort 8 # only for 32-bit >>>4 byte 1 >>>>36 lelong&0xf0000000 0x00000000 MIPS-I >>>>36 lelong&0xf0000000 0x10000000 MIPS-II >>>>36 lelong&0xf0000000 0x20000000 MIPS-III >>>>36 lelong&0xf0000000 0x30000000 MIPS-IV >>>>36 lelong&0xf0000000 0x40000000 MIPS-V >>>>36 lelong&0xf0000000 0x60000000 MIPS32 >>>>36 lelong&0xf0000000 0x70000000 MIPS64 >>>>36 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 lelong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 lelong&0xf0000000 0x00000000 MIPS-I >>>>48 lelong&0xf0000000 0x10000000 MIPS-II >>>>48 lelong&0xf0000000 0x20000000 MIPS-III >>>>48 lelong&0xf0000000 0x30000000 MIPS-IV >>>>48 lelong&0xf0000000 0x40000000 MIPS-V >>>>48 lelong&0xf0000000 0x60000000 MIPS32 >>>>48 lelong&0xf0000000 0x70000000 MIPS64 >>>>48 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 lelong&0xf0000000 0x90000000 MIPS64 rel2 >>16 leshort 0 no file type, >>16 leshort 1 relocatable, >>16 leshort 2 executable, >>16 leshort 3 shared object, # Core handling from Peter Tobias # corrections by Christian 'Dr. Disk' Hechelmann >>16 leshort 4 core file # Core file detection is not reliable. #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, >>18 leshort 4 Motorola >>>36 lelong &0x01000000 68000 - invalid byte order, >>>36 lelong &0x00810000 CPU32 - invalid byte order, >>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, >>18 leshort 8 MIPS, >>18 leshort 9 Amdahl - invalid byte order, >>18 leshort 10 MIPS (deprecated), >>18 leshort 11 RS6000 - invalid byte order, >>18 leshort 15 PA-RISC - invalid byte order, >>>50 leshort 0x0214 2.0 >>>48 leshort &0x0008 (LP64), >>18 leshort 16 nCUBE, >>18 leshort 17 Fujitsu VPP500, >>18 leshort 18 SPARC32PLUS, >>18 leshort 20 PowerPC, >>18 leshort 22 IBM S/390, >>18 leshort 36 NEC V800, >>18 leshort 37 Fujitsu FR20, >>18 leshort 38 TRW RH-32, >>18 leshort 39 Motorola RCE, >>18 leshort 40 ARM, >>18 leshort 41 Alpha, >>18 leshort 0xa390 IBM S/390 (obsolete), >>18 leshort 42 Hitachi SH, >>18 leshort 43 SPARC V9 - invalid byte order, >>18 leshort 44 Siemens Tricore Embedded Processor, >>18 leshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 leshort 46 Hitachi H8/300, >>18 leshort 47 Hitachi H8/300H, >>18 leshort 48 Hitachi H8S, >>18 leshort 49 Hitachi H8/500, >>18 leshort 50 IA-64 (Intel 64 bit architecture) >>18 leshort 51 Stanford MIPS-X, >>18 leshort 52 Motorola Coldfire, >>18 leshort 53 Motorola M68HC12, >>18 leshort 62 AMD x86-64, >>18 leshort 75 Digital VAX, >>18 leshort 97 NatSemi 32k, >>18 leshort 0x9026 Alpha (unofficial), >>20 lelong 0 invalid version >>20 lelong 1 version 1 >>36 lelong 1 MathCoPro/FPU/MAU Required >5 byte 2 MSB # only for MIPS - see comment in little-endian section above. >>18 beshort 8 # only for 32-bit >>>4 byte 1 >>>>36 belong&0xf0000000 0x00000000 MIPS-I >>>>36 belong&0xf0000000 0x10000000 MIPS-II >>>>36 belong&0xf0000000 0x20000000 MIPS-III >>>>36 belong&0xf0000000 0x30000000 MIPS-IV >>>>36 belong&0xf0000000 0x40000000 MIPS-V >>>>36 belong&0xf0000000 0x60000000 MIPS32 >>>>36 belong&0xf0000000 0x70000000 MIPS64 >>>>36 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 belong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 belong&0xf0000000 0x00000000 MIPS-I >>>>48 belong&0xf0000000 0x10000000 MIPS-II >>>>48 belong&0xf0000000 0x20000000 MIPS-III >>>>48 belong&0xf0000000 0x30000000 MIPS-IV >>>>48 belong&0xf0000000 0x40000000 MIPS-V >>>>48 belong&0xf0000000 0x60000000 MIPS32 >>>>48 belong&0xf0000000 0x70000000 MIPS64 >>>>48 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 belong&0xf0000000 0x90000000 MIPS64 rel2 >>16 beshort 0 no file type, >>16 beshort 1 relocatable, >>16 beshort 2 executable, >>16 beshort 3 shared object, >>16 beshort 4 core file, #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) belong >0 (signal %d), >>16 beshort &0xff00 processor-specific, >>18 beshort 0 no machine, >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, >>18 beshort 4 Motorola >>>36 belong &0x01000000 68000, >>>36 belong &0x00810000 CPU32, >>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, >>18 beshort 8 MIPS, >>18 beshort 9 Amdahl, >>18 beshort 10 MIPS (deprecated), >>18 beshort 11 RS6000, >>18 beshort 15 PA-RISC >>>50 beshort 0x0214 2.0 >>>48 beshort &0x0008 (LP64) >>18 beshort 16 nCUBE, >>18 beshort 17 Fujitsu VPP500, >>18 beshort 18 SPARC32PLUS, >>>36 belong&0xffff00 &0x000100 V8+ Required, >>>36 belong&0xffff00 &0x000200 Sun UltraSPARC1 Extensions Required, >>>36 belong&0xffff00 &0x000400 HaL R1 Extensions Required, >>>36 belong&0xffff00 &0x000800 Sun UltraSPARC3 Extensions Required, >>18 beshort 20 PowerPC or cisco 4500, >>18 beshort 21 cisco 7500, >>18 beshort 22 IBM S/390, >>18 beshort 24 cisco SVIP, >>18 beshort 25 cisco 7200, >>18 beshort 36 NEC V800 or cisco 12000, >>18 beshort 37 Fujitsu FR20, >>18 beshort 38 TRW RH-32, >>18 beshort 39 Motorola RCE, >>18 beshort 40 ARM, >>18 beshort 41 Alpha, >>18 beshort 42 Hitachi SH, >>18 beshort 43 SPARC V9, >>18 beshort 44 Siemens Tricore Embedded Processor, >>18 beshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 beshort 46 Hitachi H8/300, >>18 beshort 47 Hitachi H8/300H, >>18 beshort 48 Hitachi H8S, >>18 beshort 49 Hitachi H8/500, >>18 beshort 50 Intel Merced Processor, >>18 beshort 51 Stanford MIPS-X, >>18 beshort 52 Motorola Coldfire, >>18 beshort 53 Motorola M68HC12, >>18 beshort 73 Cray NV1, >>18 beshort 75 Digital VAX, >>18 beshort 97 NatSemi 32k, >>18 beshort 0x9026 Alpha (unofficial), >>18 beshort 0xa390 IBM S/390 (obsolete), >>18 beshort 0xde3d Ubicom32, >>20 belong 0 invalid version >>20 belong 1 version 1 >>36 belong 1 MathCoPro/FPU/MAU Required # Up to now only 0, 1 and 2 are defined; I've seen a file with 0x83, it seemed # like proper ELF, but extracting the string had bad results. >4 byte <0x80 >>8 string >\0 ("%s") >8 string \0 >>7 byte 0 (SYSV) >>7 byte 1 (HP-UX) >>7 byte 2 (NetBSD) >>7 byte 3 (GNU/Linux) >>7 byte 4 (GNU/Hurd) >>7 byte 5 (86Open) >>7 byte 6 (Solaris) >>7 byte 7 (Monterey) >>7 byte 8 (IRIX) >>7 byte 9 (FreeBSD) >>7 byte 10 (Tru64) >>7 byte 11 (Novell Modesto) >>7 byte 12 (OpenBSD) >>7 byte 97 (ARM) >>7 byte 255 (embedded) # XXX - according to Microsoft's spec, at an offset of 0x3c in a # PE-format executable is the offset in the file of the PE header; # unfortunately, that's a little-endian offset, and there's no way # to specify an indirect offset with a specified byte order. # So, for now, we assume the standard MS-DOS stub, which puts the # PE header at 0x80 = 128. # # Required OS version and subsystem version were 4.0 on some NT 3.51 # executables built with Visual C++ 4.0, so it's not clear that # they're interesting. The user version was 0.0, but there's # probably some linker directive to set it. The linker version was # 3.0, except for one ".exe" which had it as 4.20 (same damn linker!). # # many of the compressed formats were extraced from IDARC 1.23 source code # 0 string MZ Microsoft >0x18 leshort <0x40 MS-DOS executable >0 string MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b, PE for MS Windows >>&18 leshort&0x2000 >0 (DLL) >>&88 leshort 0 (unknown subsystem) >>&88 leshort 1 (native) >>&88 leshort 2 (GUI) >>&88 leshort 3 (console) >>&88 leshort 7 (POSIX) >>&0 leshort 0x0 unknown processor >>&0 leshort 0x14c Intel 80386 >>&0 leshort 0x166 MIPS R4000 >>&0 leshort 0x184 Alpha >>&0 leshort 0x268 Motorola 68000 >>&0 leshort 0x1f0 PowerPC >>&0 leshort 0x290 PA-RISC >>&18 leshort&0x0100 >0 32-bit >>&18 leshort&0x1000 >0 system file >>&228 lelong >0 \b, Mono/.Net assembly >>&0xf4 search/0x140 \x0\x40\x1\x0 >>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive >30 string Copyright\x201989-1990\x20PKWARE\x20Inc. Self-extracting PKZIP archive # Is next line correct? One might expect "Corp." not "Copr." If it is right, add a note to that effect. >30 string PKLITE\x20Copr. Self-extracting PKZIP archive >0x18 leshort >0x3f >>(0x3c.l) string PE\0\0 PE >>>(0x3c.l+25) byte 1 \b32 executable >>>(0x3c.l+25) byte 2 \b32+ executable # hooray, there's a DOS extender using the PE format, with a valid PE # executable inside (which just prints a message and exits if run in win) >>>(0x3c.l+92) leshort <10 >>>>(8.s*16) string 32STUB for MS-DOS, 32rtm DOS extender >>>>(8.s*16) string !32STUB for MS Windows >>>>>(0x3c.l+22) leshort&0x2000 >0 (DLL) >>>>>(0x3c.l+92) leshort 0 (unknown subsystem) >>>>>(0x3c.l+92) leshort 1 (native) >>>>>(0x3c.l+92) leshort 2 (GUI) >>>>>(0x3c.l+92) leshort 3 (console) >>>>>(0x3c.l+92) leshort 7 (POSIX) >>>(0x3c.l+92) leshort 10 (EFI application) >>>(0x3c.l+92) leshort 11 (EFI boot service driver) >>>(0x3c.l+92) leshort 12 (EFI runtime driver) >>>(0x3c.l+92) leshort 13 (XBOX) >>>(0x3c.l+4) leshort 0x0 unknown processor >>>(0x3c.l+4) leshort 0x14c Intel 80386 >>>(0x3c.l+4) leshort 0x166 MIPS R4000 >>>(0x3c.l+4) leshort 0x184 Alpha >>>(0x3c.l+4) leshort 0x268 Motorola 68000 >>>(0x3c.l+4) leshort 0x1f0 PowerPC >>>(0x3c.l+4) leshort 0x290 PA-RISC >>>(0x3c.l+4) leshort 0x200 Intel Itanium >>>(0x3c.l+22) leshort&0x0100 >0 32-bit >>>(0x3c.l+22) leshort&0x1000 >0 system file >>>(0x3c.l+232) lelong >0 Mono/.Net assembly >>>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed >>>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed >>>>(0x3c.l+0xf8) search/0x140 UPX2 >>>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>(0x3c.l+0xf8) search/0x140 .idata >>>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive >>>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .rsrc >>>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive >>>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive >>>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive >>>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .data >>>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed >>>>>(0x3c.l+0xf7) byte x >>>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .reloc >>>>>(&0xe.l+(-4)) search/0x180 PK\3\4 \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive >>>>0x30 string Inno \b, InnoSetup self-extracting archive >>(0x3c.l) string !PE\0\0 MS-DOS executable >>(0x3c.l) string NE \b, NE >>>(0x3c.l+0x36) byte 0 (unknown OS) >>>(0x3c.l+0x36) byte 1 for OS/2 1.x >>>(0x3c.l+0x36) byte 2 for MS Windows 3.x >>>(0x3c.l+0x36) byte 3 for MS-DOS >>>(0x3c.l+0x36) byte >3 (unknown OS) >>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender >>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) >>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) >>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive >>>(0x3c.l+0x70) search/0x80 WinZip(R)\x20Self-Extractor \b, ZIP self-extracting archive (WinZip) >>(0x3c.l) string LX\0\0 \b, LX >>>(0x3c.l+0x0a) leshort <1 (unknown OS) >>>(0x3c.l+0x0a) leshort 1 for OS/2 >>>(0x3c.l+0x0a) leshort 2 for MS Windows >>>(0x3c.l+0x0a) leshort 3 for DOS >>>(0x3c.l+0x0a) leshort >3 (unknown OS) >>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) >>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) >>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) >>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) >>>(0x3c.l+0x08) leshort 1 i80286 >>>(0x3c.l+0x08) leshort 2 i80386 >>>(0x3c.l+0x08) leshort 3 i80486 >>>(8.s*16) string emx \b, emx >>>>&1 string x "%s" >>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive #------------------------------------------------------------------------------ # bFLT: file(1) magic for BFLT uclinux binary files # # From Philippe De Muyter # # Additional fields added by Craig Heffner # 0 string bFLT BFLT executable >4 belong x version %ld, >4 belong 4 >8 belong x code offset: 0x%.8X, >12 belong x data segment starts at: 0x%.8X, >16 belong x bss segment starts at: 0x%.8X, >20 belong x bss segment ends at: 0x%.8X, >24 belong x stack size: %d bytes, >28 belong x relocation records start at: 0x%.8X, >32 belong x number of reolcation records: %d, >>36 belong&0x1 0x1 ram >>36 belong&0x2 0x2 gotpic >>36 belong&0x4 0x4 gzip >>36 belong&0x8 0x8 gzdata #----------------------------------------------------------------- # MIPS COFF file formats # 0 beshort 0x0160 MIPSEB ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0162 MIPSEL-BE ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6001 MIPSEB-LE ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6201 MIPSEL ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 2 additions # 0 beshort 0x0163 MIPSEB MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0166 MIPSEL-BE MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x6301 MIPSEB-LE MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x6601 MIPSEL MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 3 additions # 0 beshort 0x0140 MIPSEB MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0142 MIPSEL-BE MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x4001 MIPSEB-LE MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x4201 MIPSEL MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x180 MIPSEB Ucode 0 beshort 0x182 MIPSEL-BE Ucode # Windows CE package files 0 string MSCE\0\0\0\0 Microsoft WinCE installer >20 lelong 0 \b, architecture-independent >20 lelong 103 \b, Hitachi SH3 >20 lelong 104 \b, Hitachi SH4 >20 lelong 0xA11 \b, StrongARM >20 lelong 4000 \b, MIPS R4000 >20 lelong 10003 \b, Hitachi SH3 >20 lelong 10004 \b, Hitachi SH3E >20 lelong 10005 \b, Hitachi SH4 >20 lelong 70001 \b, ARM 7TDMI >52 leshort 1 \b, 1 file >52 leshort >1 \b, %u files >56 leshort 1 \b, 1 registry entry >56 leshort >1 \b, %u registry entries #------------------------------------------------------------------------------ # Microsoft Xbox executables .xbe (Esa Hyytiä ) 0 string XBEH XBE, Microsoft Xbox executable # probabilistic checks whether signed or not >0x0004 ulelong =0x0 >>&2 ulelong =0x0 >>>&2 ulelong =0x0 \b, not signed >0x0004 ulelong >0 >>&2 ulelong >0 >>>&2 ulelong >0 \b, signed # expect base address of 0x10000 >0x0104 ulelong =0x10000 >>(0x0118-0x0FF60) ulelong&0x80000007 0x80000007 \b, all regions >>(0x0118-0x0FF60) ulelong&0x80000007 !0x80000007 >>>(0x0118-0x0FF60) ulelong >0 (regions: >>>>(0x0118-0x0FF60) ulelong &0x00000001 NA >>>>(0x0118-0x0FF60) ulelong &0x00000002 Japan >>>>(0x0118-0x0FF60) ulelong &0x00000004 Rest_of_World >>>>(0x0118-0x0FF60) ulelong &0x80000000 Manufacturer >>>(0x0118-0x0FF60) ulelong >0 \b) #------------------------------------------------------------------------------ # motorola: file(1) magic for Motorola 68K and 88K binaries # # 68K # 0 beshort 0x0208 mc68k COFF >18 beshort ^00000020 object >18 beshort &00000020 executable >12 belong >0 not stripped >168 string .lowmem Apple toolbox >20 beshort 0407 (impure) >20 beshort 0410 (pure) >20 beshort 0413 (demand paged) >20 beshort 0421 (standalone) 0 beshort 0x0209 mc68k executable (shared) >12 belong >0 not stripped 0 beshort 0x020A mc68k executable (shared demand paged) >12 belong >0 not stripped # # Motorola/UniSoft 68K Binary Compatibility Standard (BCS) # 0 beshort 0x022A 68K BCS executable # # 88K # # Motorola/88Open BCS # 0 beshort 0x022B 88K BCS executable #------------------------------------------------------------------------------ # Sony Playstation executables (Adam Sjoegren ) : 0 string PS-X\x20EXE Sony Playstation executable # Area: >113 string x ("%s") #------------------------------------------------------------------------------ # cisco: file(1) magic for cisco Systems routers # # Most cisco file-formats are covered by the generic elf code # # Microcode files are non-ELF, 0x8501 conflicts with NetBSD/alpha. 0 beshort 0x8501 cisco IOS >0 belong&0xffffff00 0x85011400 microcode >0 belong&0xffffff00 0x8501cb00 experimental microcode >7 string >\0 for "%s" # EST flat binary format (which isn't, but anyway) # From: Mark Brown 0 string ESTFBINR EST flat binary # These are not the binaries themselves, but string references to them # are a strong indication that they exist elsewhere... #0 string /bin/busybox Busybox string reference: "%s"{one-of-many} #0 string /bin/sh Shell string reference: "%s"{one-of-many} #--------------------File Systems--------------------- # Minix filesystems - Juan Cespedes 0x410 leshort 0x137f Minix filesystem >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 leshort 0x138f Minix filesystem, 30 char names 0x410 leshort 0x2468 Minix filesystem, version 2 0x410 leshort 0x2478 Minix filesystem, version 2, 30 char names 0x410 leshort 0x4d5a Minix filesystem, version 3 0x410 leshort 0x4d6a Minix filesystem, version 3, 30 char names 0x410 beshort 0x137f Minix filesystem (big endian) >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 beshort 0x138f Minix filesystem (big endian), 30 char names 0x410 beshort 0x2468 Minix filesystem (big endian), version 2 0x410 beshort 0x2478 Minix filesystem (big endian), version 2, 30 char names 0x410 beshort 0x4d5a Minix filesystem (big endian), version 3 0x410 beshort 0x4d6a Minix filesystem (big endian), version 3, 30 char names # YAFFS 0 string \x03\x00\x00\x00\x01\x00\x00\x00\xFF\xFF YAFFS filesystem # EFS2 file system - jojo@utulsa.edu 0 lelong 0x53000000 EFS2 Qualcomm filesystem super block, little endian, >8 string !EFSSuper invalid, >4 leshort &1 NAND >4 leshort ^1 NOR >4 leshort x version 0x%x, >24 lelong x %d blocks, >16 lelong x 0x%x pages per block, >20 lelong x 0x%x bytes per page 0 belong 0x53000000 EFS2 Qualcomm filesystem super block, big endian, >8 string !SSFErepu invalid, >4 beshort &1 NAND >4 beshort ^1 NOR >4 beshort x version 0x%x, >24 belong x %d blocks, >16 belong x 0x%x pages per block, >20 belong x 0x%x bytes per page # TROC file system 0 string TROC TROC filesystem, >4 lelong x %d file entries # PFS file system 0 string PFS/ PFS filesystem, >4 string x version "%s", >14 leshort x %d files # MPFS file system 0 string MPFS MPFS (Microchip) filesystem, >4 byte x version %d. >5 byte x \b%d, >6 leshort x %d file entries # cramfs filesystem - russell@coker.com.au 0 lelong 0x28cd3d45 CramFS filesystem, little endian >4 lelong <0 invalid >4 lelong x size %lu >8 lelong &1 version #2 >8 lelong &2 sorted_dirs >8 lelong &4 hole_support >32 lelong x CRC 0x%x, >36 lelong x edition %lu, >40 lelong <0 invalid >40 lelong x %lu blocks, >44 lelong <0 invalid >44 lelong x %lu files >4 lelong x {jump-to-offset:%lu} >4 lelong x {file-size:%lu} 0 belong 0x28cd3d45 CramFS filesystem, big endian >4 belong <0 invalid >4 belong x size %lu >8 belong &1 version #2 >8 belong &2 sorted_dirs >8 belong &4 hole_support >32 belong x CRC 0x%x, >36 belong x edition %lu, >40 belong <0 invalid >40 belong x %lu blocks, >44 belong <0 invalid >44 belong x %lu files >4 belong x {jump-to-offset:%lu} >4 belong x {file-size:%lu} # JFFS2 file system # If used with binwalk's smart signature feature (on by default, -S to disable) # this signature can potentially lead to missing some JFFS2 file systems if there # are multiple JFFS2 file systems in a target file and there are no other identified # files in between the JFFS2 file systems. This is an unlikely scenario however, and # the below signatures are much improved in terms of readability and accuracy in the # vast majority of real world scenarios. 0 leshort 0x1985 JFFS2 filesystem, little endian{filter-include} >2 leshort !0xE001 >>2 leshort !0xE002 >>>2 leshort !0x2003 >>>>2 leshort !0x2004 >>>>>2 leshort !0x2006 >>>>>>2 leshort !0xE008 >>>>>>>2 leshort !0xE009 \b, invalid >(4.l) leshort !0x1985 >>(4.l+1) leshort !0x1985 >>>(4.l+2) leshort !0x1985 >>>>(4.l+3) leshort !0x1985 >>>>>(4.l) leshort !0xFFFF >>>>>>(4.l+1) leshort !0xFFFF >>>>>>>(4.l+2) leshort !0xFFFF >>>>>>>>(4.l+3) leshort !0xFFFF \b, invalid >4 lelong x {one-of-many}{jump-to-offset:%d} 0 beshort 0x1985 JFFS2 filesystem, big endian{filter-include} >2 beshort !0xE001 >>2 beshort !0xE002 >>>2 beshort !0x2003 >>>>2 beshort !0x2004 >>>>>2 beshort !0x2006 >>>>>>2 beshort !0xE008 >>>>>>>2 beshort !0xE009 \b, invalid >(4.L) beshort !0x1985 >>(4.L+1) beshort !0x1985 >>>(4.L+2) beshort !0x1985 >>>>(4.L+3) beshort !0x1985 >>>>>(4.L) beshort !0xFFFF >>>>>>(4.L+1) beshort !0xFFFF >>>>>>>(4.L+2) beshort !0xFFFF >>>>>>>>(4.L+3) beshort !0xFFFF \b, invalid >4 belong x {one-of-many}{jump-to-offset:%d} # Squashfs, big endian 0 string sqsh Squashfs filesystem, big endian, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort 3 >>63 bequad x size: %lld bytes, >28 beshort >3 >>40 bequad x size: %lld bytes, >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs, little endian 0 string hsqs Squashfs filesystem, little endian, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Squashfs with LZMA compression 0 string sqlz Squashfs filesystem, big endian, lzma compression, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs 3.3 LZMA signature 0 string qshs Squashfs filesystem, big endian, lzma signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string tqsh Squashfs filesystem, big endian, DD-WRT signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string hsqt Squashfs filesystem, little endian, DD-WRT signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Non-standard Squashfs signature found on some D-Link routers 0 string shsq Squashfs filesystem, little endian, non-standard signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # ext2/ext3 filesystems - Andreas Dilger # ext4 filesystem - Eric Sandeen # volume label and UUID Russell Coker # http://etbe.coker.com.au/2008/07/08/label-vs-uuid-vs-device/ 0 leshort 0xEF53 Linux EXT filesystem,{filter-include}{offset-adjust:-0x438} >2 leshort >4 invalid state >2 leshort 3 invalid state >2 leshort <0 invalid state >4 leshort >3 invalid error behavior >4 leshort <0 invalid error behavior >4 lelong >1 invalid major revision >4 lelong <0 invalid major revision >4 lelong x rev %d >6 leshort x \b.%d # No journal? ext2 >36 lelong ^0x0000004 ext2 filesystem data >>2 leshort ^0x0000001 (mounted or unclean) # Has a journal? ext3 or ext4 >36 lelong &0x0000004 # and small INCOMPAT? >>40 lelong <0x0000040 # and small RO_COMPAT? >>>44 lelong <0x0000008 ext3 filesystem data # else large RO_COMPAT? >>>44 lelong >0x0000007 ext4 filesystem data # else large INCOMPAT? >>40 lelong >0x000003f ext4 filesystem data >48 belong x \b, UUID=%08x >52 beshort x \b-%04x >54 beshort x \b-%04x >56 beshort x \b-%04x >58 belong x \b-%08x >60 beshort x \b%04x >64 string >0 \b, volume name "%s" #romfs filesystems - Juan Cespedes 0 string -rom1fs-\0 romfs filesystem, version 1 >8 belong >10000000 invalid >8 belong x size: %d bytes, >16 string x {file-name:%s} >16 string x named "%s" >8 belong x {file-size:%d} >8 belong x {jump-to-offset:%d} # Wind River MemFS file system, found in some VxWorks devices 0 string owowowowowowowowowowowowowowow Wind River management filesystem, >30 string !ow invalid, >32 belong 1 compressed, >32 belong 2 plain text, >36 belong x %d files # netboot image - Juan Cespedes 0 lelong 0x1b031336L Netboot image, >4 lelong&0xFFFFFF00 0 >>4 lelong&0x100 0x000 mode 2 >>4 lelong&0x100 0x100 mode 3 >4 lelong&0xFFFFFF00 !0 unknown mode (invalid) #--------------------------Firmware Formats--------------------------- # uImage file # From: Craig Heffner, U-Boot image.h header definitions file 0 belong 0x27051956 uImage header, header size: 64 bytes, >4 belong x header CRC: 0x%X, >8 bedate x created: %s, >12 belong x image size: %d bytes, >16 belong x Data Address: 0x%X, >20 belong x Entry Point: 0x%X, >24 belong x data CRC: 0x%X, #>28 byte x OS type: %d, >28 byte 0 OS: invalid OS, >28 byte 1 OS: OpenBSD, >28 byte 2 OS: NetBSD, >28 byte 3 OS: FreeBSD, >28 byte 4 OS: 4.4BSD, >28 byte 5 OS: Linux, >28 byte 6 OS: SVR4, >28 byte 7 OS: Esix, >28 byte 8 OS: Solaris, >28 byte 9 OS: Irix, >28 byte 10 OS: SCO, >28 byte 11 OS: Dell, >28 byte 12 OS: NCR, >28 byte 13 OS: LynxOS, >28 byte 14 OS: VxWorks, >28 byte 15 OS: pSOS, >28 byte 16 OS: QNX, >28 byte 17 OS: Firmware, >28 byte 18 OS: RTEMS, >28 byte 19 OS: ARTOS, >28 byte 20 OS: Unity OS, #>29 byte x CPU arch: %d, >29 byte 0 CPU: invalid OS, >29 byte 1 CPU: Alpha, >29 byte 2 CPU: ARM, >29 byte 3 CPU: Intel x86, >29 byte 4 CPU: IA64, >29 byte 5 CPU: MIPS, >29 byte 6 CPU: MIPS 64 bit, >29 byte 7 CPU: PowerPC, >29 byte 8 CPU: IBM S390, >29 byte 9 CPU: SuperH, >29 byte 10 CPU: Sparc, >29 byte 11 CPU: Sparc 64 bit, >29 byte 12 CPU: M68K, >29 byte 13 CPU: Nios-32, >29 byte 14 CPU: MicroBlaze, >29 byte 15 CPU: Nios-II, >29 byte 16 CPU: Blackfin, >29 byte 17 CPU: AVR, >29 byte 18 CPU: STMicroelectronics ST200, #>30 byte x image type: %d, >30 byte 0 image type: invalid Image, >30 byte 1 image type: Standalone Program, >30 byte 2 image type: OS Kernel Image, >30 byte 3 image type: RAMDisk Image, >30 byte 4 image type: Multi-File Image, >30 byte 5 image type: Firmware Image, >30 byte 6 image type: Script file, >30 byte 7 image type: Filesystem Image, >30 byte 8 image type: Binary Flat Device Tree Blob #>31 byte x compression type: %d, >31 byte 0 compression type: none, >31 byte 1 compression type: gzip, >31 byte 2 compression type: bzip2, >31 byte 3 compression type: lzma, >32 string x image name: "%s" #IMG0 header, found in VxWorks-based Mercury router firmware 0 string IMG0 IMG0 (VxWorks) header, >4 belong x size: %d #Mediatek bootloader signature #From xp-dev.com 0 string BOOTLOADER! Mediatek bootloader #CSYS header formats 0 string CSYS\x00 CSYS header, little endian, >8 lelong x size: %d 0 string CSYS\x80 CSYS header, big endian, >8 belong x size: %d # wrgg firmware image 0 string wrgg02 WRGG firmware header, >6 string x name: "%s", >48 string x root device: "%s" # trx image file 0 string HDR0 TRX firmware header, little endian, header size: 28 bytes, >4 lelong x image size: %d bytes, >8 lelong x CRC32: 0x%X >12 lelong x flags/version: 0x%X 0 string 0RDH TRX firmware header, big endian, header size: 28 bytes, >4 belong x image size: %d bytes, >8 belong x CRC32: 0x%X >12 belong x flags/version: 0x%X # Ubicom firmware image 0 belong 0xFA320080 Ubicom firmware header, >12 belong x checksum: 0x%X, >24 belong x image size: %d # The ROME bootloader is used by several RealTek-based products. # Unfortunately, the magic bytes are specific to each product, so # separate signatures must be created for each one. # Netgear KWGR614 ROME image 0 string G614 Realtek firmware header (ROME bootloader), >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # Linksys WRT54GX ROME image 0 belong 0x59a0e842 Realtek firmware header (ROME bootloader) >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # PackImg tag, somtimes used as a delimiter between the kernel and rootfs in firmware images. 0 string --PaCkImGs-- PackImg section delimiter tag, >16 lelong x little endian size: %d bytes; >16 belong x big endian size: %d bytes #------------------------------------------------------------------------------ # Broadcom header format # 0 string BCRM Broadcom header, >4 lelong x number of sections: %d, >>8 lelong 18 first section type: flash >>8 lelong 19 first section type: disk >>8 lelong 21 first section type: tag # Berkeley Lab Checkpoint Restart (BLCR) checkpoint context files # http://ftg.lbl.gov/checkpoint 0 string Ck0\0\0R\0\0\0 BLCR >16 lelong 1 x86 >16 lelong 3 alpha >16 lelong 5 x86-64 >16 lelong 7 ARM >8 lelong x context data (little endian, version %d) 0 string \0\0\0C\0\0\0R BLCR >16 belong 2 SPARC >16 belong 4 ppc >16 belong 6 ppc64 >16 belong 7 ARMEB >16 belong 8 SPARC64 >8 belong x context data (big endian, version %d) # Aculab VoIP firmware # From: Mark Brown 0 string VoIP\x20Startup\x20and Aculab VoIP firmware >35 string x format "%s" #------------------------------------------------------------------------------ # HP LaserJet 1000 series downloadable firmware file 0 string \xbe\xefABCDEFGH HP LaserJet 1000 series downloadable firmware # From Albert Cahalan # really le32 operation,destination,payloadsize (but quite predictable) # 01 00 00 00 00 00 00 c0 00 02 00 00 0 string \1\0\0\0\0\0\0\300\0\2\0\0 Marvell Libertas firmware #--------------------------------------------------------------------------- # The following entries have been tested by Duncan Laurie (a # lead Sun/Cobalt developer) who agrees that they are good and worthy of # inclusion. # Boot ROM images for Sun/Cobalt Linux server appliances 0 string Cobalt\x20Networks\x20Inc.\nFirmware\x20v Paged COBALT boot rom >38 string x V%.4s # New format for Sun/Cobalt boot ROMs is annoying, it stores the version code # at the very end where file(1) can't get it. 0 string CRfs COBALT boot rom data (Flat boot rom or file system) # # Motorola S-Records, from Gerd Truschinski 0 string S0 Motorola S-Record; binary data in text format # -------------------------------- # Microsoft Xbox data file formats 0 string XIP0 XIP, Microsoft Xbox data 0 string XTF0 XTF, Microsoft Xbox data #Windows CE 0 string CECE Windows CE RTOS{offset-adjust:-64} # -------------------------------- # ZynOS ROM header format # From openwrt zynos.h. 0 string SIG ZynOS header, header size: 48 bytes,{offset-adjust:-6} #>0 belong x load address 0x%X, >3 byte <0x7F rom image type: >>3 byte <1 invalid, >>3 byte >7 invalid, >>3 byte 1 ROMIMG, >>3 byte 2 ROMBOOT, >>3 byte 3 BOOTEXT, >>3 byte 4 ROMBIN, >>3 byte 5 ROMDIR, >>3 byte 6 6, >>3 byte 7 ROMMAP, >3 byte >0x7F ram image type: >>3 byte >0x82 invalid, >>3 byte 0x80 RAM, >>3 byte 0x81 RAMCODE, >>3 byte 0x82 RAMBOOT, >4 belong >0x40000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x uncompressed size: %d, >8 belong >0x40000000 invalid >8 belong <0 invalid >8 belong 0 invalid >8 belong x compressed size: %d, >14 beshort x uncompressed checksum: 0x%X, >16 beshort x compressed checksum: 0x%X, >12 byte x flags: 0x%X, >12 byte &0x40 uncompressed checksum is valid, >12 byte &0x80 the binary is compressed, >>12 byte &0x20 compressed checksum is valid, >35 belong x memory map table address: 0x%X # Firmware header used by some VxWorks-based Cisco products 0 string CI032.00 Cisco VxWorks firmware header, >8 lelong >1024 invalid >8 lelong <0 invalid >8 lelong x header size: %d bytes, >32 lelong >1024 invalid >32 lelong <0 invalid >32 lelong x number of files: %d, >48 lelong <0 invalid >48 lelong x image size: %d, >64 string x firmware version: "%s" # Firmware header used by some TV's 0 string FNIB ZBOOT firmware header, header size: 32 bytes, >8 lelong x load address: 0x%.8X, >12 lelong x start address: 0x%.8X, >16 lelong x checksum: 0x%.8X, >20 lelong x version: 0x%.8X, >24 lelong <1 invalid >24 lelong x image size: %d bytes # Firmware header used by several D-Link routers (and probably others) 0 string \x5e\xa3\xa4\x17 DLOB firmware header, >(7.b+12) string !\x5e\xa3\xa4\x17 invalid, #>>12 string x %s, >(7.b+40) string x boot partition: "%s" # TP-Link firmware header structure; thanks to Jonathan McGowan for reversing and documenting this format 0 string TP-LINK\x20Technologies TP-Link firmware header,{offset-adjust:-4} #>-4 lelong x header version: %d, >0x94 beshort x firmware version: %d. >0x96 beshort x \b%d. >0x98 beshort x \b%d, >0x18 string x image version: "%s", #>0x74 belong x image size: %d bytes, >0x3C belong x product ID: 0x%X, >0x40 belong x product version: %d, >0x70 belong x kernel load address: 0x%X, >0x74 belong x kernel entry point: 0x%X, >0x7C belong x kernel offset: %d, >0x80 belong x kernel length: %d, >0x84 belong x rootfs offset: %d, >0x88 belong x rootfs length: %d, >0x8C belong x bootloader offset: %d, >0x90 belong x bootloader length: %d # Tag Image File Format, from Daniel Quinlan (quinlan@yggdrasil.com) # The second word of TIFF files is the TIFF version number, 42, which has # never changed. The TIFF specification recommends testing for it. 0 string MM\x00\x2a TIFF image data, big-endian 0 string II\x2a\x00 TIFF image data, little-endian # PNG [Portable Network Graphics, or "PNG's Not GIF"] images # (Greg Roelofs, newt@uchicago.edu) # (Albert Cahalan, acahalan@cs.uml.edu) # # 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ... # 0 string \x89PNG\x0d\x0a\x1a\x0a PNG image >16 belong x \b, %ld x >20 belong x %ld, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, #>26 byte 0 deflate/32K, >28 byte 0 non-interlaced >28 byte 1 interlaced # GIF 0 string GIF8 GIF image data >4 string 7a \b, version 8"%s", >4 string 9a \b, version 8"%s", >6 leshort >0 %hd x >8 leshort >0 %hd #>10 byte &0x80 color mapped, #>10 byte&0x07 =0x00 2 colors #>10 byte&0x07 =0x01 4 colors #>10 byte&0x07 =0x02 8 colors #>10 byte&0x07 =0x03 16 colors #>10 byte&0x07 =0x04 32 colors #>10 byte&0x07 =0x05 64 colors #>10 byte&0x07 =0x06 128 colors #>10 byte&0x07 =0x07 256 colors # PC bitmaps (OS/2, Windows BMP files) (Greg Roelofs, newt@uchicago.edu) 0 string BM >14 leshort 12 PC bitmap, OS/2 1.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 64 PC bitmap, OS/2 2.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 40 PC bitmap, Windows 3.x format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d >14 leshort 128 PC bitmap, Windows NT/2000 format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d #------------------------------------------------------------------------------ # JPEG images # SunOS 5.5.1 had # # 0 string \377\330\377\340 JPEG file # 0 string \377\330\377\356 JPG file # # both of which turn into "JPEG image data" here. # 0 beshort 0xffd8 JPEG image data >6 string JFIF \b, JFIF standard # The following added by Erik Rossen 1999-09-06 # in a vain attempt to add image size reporting for JFIF. Note that these # tests are not fool-proof since some perfectly valid JPEGs are currently # impossible to specify in magic(4) format. # First, a little JFIF version info: >>11 byte x \b %d. >>12 byte x \b%02d # Next, the resolution or aspect ratio of the image: #>>13 byte 0 \b, aspect ratio #>>13 byte 1 \b, resolution (DPI) #>>13 byte 2 \b, resolution (DPCM) #>>4 beshort x \b, segment length %d # Next, show thumbnail info, if it exists: >>18 byte !0 \b, thumbnail %dx >>>19 byte x \b%d # EXIF moved down here to avoid reporting a bogus version number, # and EXIF version number printing added. # - Patrik R=E5dman >6 string Exif \b, EXIF standard # Look for EXIF IFD offset in IFD 0, and then look for EXIF version tag in EXIF IFD. # All possible combinations of entries have to be enumerated, since no looping # is possible. And both endians are possible... # The combinations included below are from real-world JPEGs. # Little-endian >>12 string II # IFD 0 Entry #5: >>>70 leshort 0x8769 # EXIF IFD Entry #1: >>>>(78.l+14) leshort 0x9000 >>>>>(78.l+23) byte x %c >>>>>(78.l+24) byte x \b.%c >>>>>(78.l+25) byte !0x30 \b%c # IFD 0 Entry #9: >>>118 leshort 0x8769 # EXIF IFD Entry #3: >>>>(126.l+38) leshort 0x9000 >>>>>(126.l+47) byte x %c >>>>>(126.l+48) byte x \b.%c >>>>>(126.l+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 leshort 0x8769 # EXIF IFD Entry #3: >>>>(138.l+38) leshort 0x9000 >>>>>(138.l+47) byte x %c >>>>>(138.l+48) byte x \b.%c >>>>>(138.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(138.l+50) leshort 0x9000 >>>>>(138.l+59) byte x %c >>>>>(138.l+60) byte x \b.%c >>>>>(138.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.l+62) leshort 0x9000 >>>>>(138.l+71) byte x %c >>>>>(138.l+72) byte x \b.%c >>>>>(138.l+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 leshort 0x8769 # EXIF IFD Entry #3: >>>>(150.l+38) leshort 0x9000 >>>>>(150.l+47) byte x %c >>>>>(150.l+48) byte x \b.%c >>>>>(150.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(150.l+50) leshort 0x9000 >>>>>(150.l+59) byte x %c >>>>>(150.l+60) byte x \b.%c >>>>>(150.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(150.l+62) leshort 0x9000 >>>>>(150.l+71) byte x %c >>>>>(150.l+72) byte x \b.%c >>>>>(150.l+73) byte !0x30 \b%c # Big-endian >>12 string MM # IFD 0 Entry #9: >>>118 beshort 0x8769 # EXIF IFD Entry #1: >>>>(126.L+14) beshort 0x9000 >>>>>(126.L+23) byte x %c >>>>>(126.L+24) byte x \b.%c >>>>>(126.L+25) byte !0x30 \b%c # EXIF IFD Entry #3: >>>>(126.L+38) beshort 0x9000 >>>>>(126.L+47) byte x %c >>>>>(126.L+48) byte x \b.%c >>>>>(126.L+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 beshort 0x8769 # EXIF IFD Entry #3: >>>>(138.L+38) beshort 0x9000 >>>>>(138.L+47) byte x %c >>>>>(138.L+48) byte x \b.%c >>>>>(138.L+49) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.L+62) beshort 0x9000 >>>>>(138.L+71) byte x %c >>>>>(138.L+72) byte x \b.%c >>>>>(138.L+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 beshort 0x8769 # EXIF IFD Entry #4: >>>>(150.L+50) beshort 0x9000 >>>>>(150.L+59) byte x %c >>>>>(150.L+60) byte x \b.%c >>>>>(150.L+61) byte !0x30 \b%c # Here things get sticky. We can do ONE MORE marker segment with # indirect addressing, and that's all. It would be great if we could # do pointer arithemetic like in an assembler language. Christos? # And if there was some sort of looping construct to do searches, plus a few # named accumulators, it would be even more effective... # At least we can show a comment if no other segments got inserted before: >(4.S+5) byte 0xFE >>(4.S+8) string >\0 \b, comment: "%s" # FIXME: When we can do non-byte counted strings, we can use that to get # the string's count, and fix Debian bug #283760 #>(4.S+5) byte 0xFE \b, comment #>>(4.S+6) beshort x \b length=%d #>>(4.S+8) string >\0 \b, "%s" # Or, we can show the encoding type (I've included only the three most common) # and image dimensions if we are lucky and the SOFn (image segment) is here: >(4.S+5) byte 0xC0 \b, baseline >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC1 \b, extended sequential >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC2 \b, progressive >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d # I've commented-out quantisation table reporting. I doubt anyone cares yet. #>(4.S+5) byte 0xDB \b, quantisation table #>>(4.S+6) beshort x \b length=%d #>14 beshort x \b, %d x #>16 beshort x \b %d #-------------------------Kernels------------------------------------- # Linux kernel boot images, from Albert Cahalan # and others such as Axel Kohlmeyer # and Nicolás Lichtmaier # All known start with: b8 c0 07 8e d8 b8 00 90 8e c0 b9 00 01 29 f6 29 0 string \xb8\xc0\x07\x8e\xd8\xb8\x00\x90\x8e\xc0\xb9\x00\x01\x29\xf6\x29 Linux kernel boot image >514 string !HdrS (invalid) # Finds and prints Linux kernel strings in raw Linux kernels (output like uname -a). # Commonly found in decompressed embedded kernel binaries. 0 string Linux\ version\ Linux kernel version >14 byte 0 invalid >14 byte !0 >>14 string x "%s >>45 string x \b%s >>76 string x \b%s >>107 string x \b%s" # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5D # ------------------------------------------------------------------ 0 string \x5D\x00\x00 LZMA compressed data, properties: 0x5D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x01 # ------------------------------------------------------------------ 0 string \x01\x00\x00 LZMA compressed data, properties: 0x01, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x02 # ------------------------------------------------------------------ 0 string \x02\x00\x00 LZMA compressed data, properties: 0x02, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x03 # ------------------------------------------------------------------ 0 string \x03\x00\x00 LZMA compressed data, properties: 0x03, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x04 # ------------------------------------------------------------------ 0 string \x04\x00\x00 LZMA compressed data, properties: 0x04, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x09 # ------------------------------------------------------------------ 0 string \x09\x00\x00 LZMA compressed data, properties: 0x09, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0A # ------------------------------------------------------------------ 0 string \x0A\x00\x00 LZMA compressed data, properties: 0x0A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0B # ------------------------------------------------------------------ 0 string \x0B\x00\x00 LZMA compressed data, properties: 0x0B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0C # ------------------------------------------------------------------ 0 string \x0C\x00\x00 LZMA compressed data, properties: 0x0C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x12 # ------------------------------------------------------------------ 0 string \x12\x00\x00 LZMA compressed data, properties: 0x12, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x13 # ------------------------------------------------------------------ 0 string \x13\x00\x00 LZMA compressed data, properties: 0x13, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x14 # ------------------------------------------------------------------ 0 string \x14\x00\x00 LZMA compressed data, properties: 0x14, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1B # ------------------------------------------------------------------ 0 string \x1B\x00\x00 LZMA compressed data, properties: 0x1B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1C # ------------------------------------------------------------------ 0 string \x1C\x00\x00 LZMA compressed data, properties: 0x1C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x24 # ------------------------------------------------------------------ 0 string \x24\x00\x00 LZMA compressed data, properties: 0x24, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2D # ------------------------------------------------------------------ 0 string \x2D\x00\x00 LZMA compressed data, properties: 0x2D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2E # ------------------------------------------------------------------ 0 string \x2E\x00\x00 LZMA compressed data, properties: 0x2E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2F # ------------------------------------------------------------------ 0 string \x2F\x00\x00 LZMA compressed data, properties: 0x2F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x30 # ------------------------------------------------------------------ 0 string \x30\x00\x00 LZMA compressed data, properties: 0x30, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x31 # ------------------------------------------------------------------ 0 string \x31\x00\x00 LZMA compressed data, properties: 0x31, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x36 # ------------------------------------------------------------------ 0 string \x36\x00\x00 LZMA compressed data, properties: 0x36, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x37 # ------------------------------------------------------------------ 0 string \x37\x00\x00 LZMA compressed data, properties: 0x37, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x38 # ------------------------------------------------------------------ 0 string \x38\x00\x00 LZMA compressed data, properties: 0x38, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x39 # ------------------------------------------------------------------ 0 string \x39\x00\x00 LZMA compressed data, properties: 0x39, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x3F # ------------------------------------------------------------------ 0 string \x3F\x00\x00 LZMA compressed data, properties: 0x3F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x40 # ------------------------------------------------------------------ 0 string \x40\x00\x00 LZMA compressed data, properties: 0x40, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x41 # ------------------------------------------------------------------ 0 string \x41\x00\x00 LZMA compressed data, properties: 0x41, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x48 # ------------------------------------------------------------------ 0 string \x48\x00\x00 LZMA compressed data, properties: 0x48, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x49 # ------------------------------------------------------------------ 0 string \x49\x00\x00 LZMA compressed data, properties: 0x49, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x51 # ------------------------------------------------------------------ 0 string \x51\x00\x00 LZMA compressed data, properties: 0x51, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5A # ------------------------------------------------------------------ 0 string \x5A\x00\x00 LZMA compressed data, properties: 0x5A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5B # ------------------------------------------------------------------ 0 string \x5B\x00\x00 LZMA compressed data, properties: 0x5B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5C # ------------------------------------------------------------------ 0 string \x5C\x00\x00 LZMA compressed data, properties: 0x5C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5E # ------------------------------------------------------------------ 0 string \x5E\x00\x00 LZMA compressed data, properties: 0x5E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x63 # ------------------------------------------------------------------ 0 string \x63\x00\x00 LZMA compressed data, properties: 0x63, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x64 # ------------------------------------------------------------------ 0 string \x64\x00\x00 LZMA compressed data, properties: 0x64, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x65 # ------------------------------------------------------------------ 0 string \x65\x00\x00 LZMA compressed data, properties: 0x65, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x66 # ------------------------------------------------------------------ 0 string \x66\x00\x00 LZMA compressed data, properties: 0x66, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6C # ------------------------------------------------------------------ 0 string \x6C\x00\x00 LZMA compressed data, properties: 0x6C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6D # ------------------------------------------------------------------ 0 string \x6D\x00\x00 LZMA compressed data, properties: 0x6D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6E # ------------------------------------------------------------------ 0 string \x6E\x00\x00 LZMA compressed data, properties: 0x6E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x75 # ------------------------------------------------------------------ 0 string \x75\x00\x00 LZMA compressed data, properties: 0x75, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x76 # ------------------------------------------------------------------ 0 string \x76\x00\x00 LZMA compressed data, properties: 0x76, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x7E # ------------------------------------------------------------------ 0 string \x7E\x00\x00 LZMA compressed data, properties: 0x7E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x87 # ------------------------------------------------------------------ 0 string \x87\x00\x00 LZMA compressed data, properties: 0x87, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x88 # ------------------------------------------------------------------ 0 string \x88\x00\x00 LZMA compressed data, properties: 0x88, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x89 # ------------------------------------------------------------------ 0 string \x89\x00\x00 LZMA compressed data, properties: 0x89, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8A # ------------------------------------------------------------------ 0 string \x8A\x00\x00 LZMA compressed data, properties: 0x8A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8B # ------------------------------------------------------------------ 0 string \x8B\x00\x00 LZMA compressed data, properties: 0x8B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x90 # ------------------------------------------------------------------ 0 string \x90\x00\x00 LZMA compressed data, properties: 0x90, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x91 # ------------------------------------------------------------------ 0 string \x91\x00\x00 LZMA compressed data, properties: 0x91, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x92 # ------------------------------------------------------------------ 0 string \x92\x00\x00 LZMA compressed data, properties: 0x92, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x93 # ------------------------------------------------------------------ 0 string \x93\x00\x00 LZMA compressed data, properties: 0x93, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x99 # ------------------------------------------------------------------ 0 string \x99\x00\x00 LZMA compressed data, properties: 0x99, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9A # ------------------------------------------------------------------ 0 string \x9A\x00\x00 LZMA compressed data, properties: 0x9A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9B # ------------------------------------------------------------------ 0 string \x9B\x00\x00 LZMA compressed data, properties: 0x9B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA2 # ------------------------------------------------------------------ 0 string \xA2\x00\x00 LZMA compressed data, properties: 0xA2, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA3 # ------------------------------------------------------------------ 0 string \xA3\x00\x00 LZMA compressed data, properties: 0xA3, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xAB # ------------------------------------------------------------------ 0 string \xAB\x00\x00 LZMA compressed data, properties: 0xAB, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB4 # ------------------------------------------------------------------ 0 string \xB4\x00\x00 LZMA compressed data, properties: 0xB4, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB5 # ------------------------------------------------------------------ 0 string \xB5\x00\x00 LZMA compressed data, properties: 0xB5, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB6 # ------------------------------------------------------------------ 0 string \xB6\x00\x00 LZMA compressed data, properties: 0xB6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB7 # ------------------------------------------------------------------ 0 string \xB7\x00\x00 LZMA compressed data, properties: 0xB7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB8 # ------------------------------------------------------------------ 0 string \xB8\x00\x00 LZMA compressed data, properties: 0xB8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBD # ------------------------------------------------------------------ 0 string \xBD\x00\x00 LZMA compressed data, properties: 0xBD, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBE # ------------------------------------------------------------------ 0 string \xBE\x00\x00 LZMA compressed data, properties: 0xBE, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBF # ------------------------------------------------------------------ 0 string \xBF\x00\x00 LZMA compressed data, properties: 0xBF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC0 # ------------------------------------------------------------------ 0 string \xC0\x00\x00 LZMA compressed data, properties: 0xC0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC6 # ------------------------------------------------------------------ 0 string \xC6\x00\x00 LZMA compressed data, properties: 0xC6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC7 # ------------------------------------------------------------------ 0 string \xC7\x00\x00 LZMA compressed data, properties: 0xC7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC8 # ------------------------------------------------------------------ 0 string \xC8\x00\x00 LZMA compressed data, properties: 0xC8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xCF # ------------------------------------------------------------------ 0 string \xCF\x00\x00 LZMA compressed data, properties: 0xCF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD0 # ------------------------------------------------------------------ 0 string \xD0\x00\x00 LZMA compressed data, properties: 0xD0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD8 # ------------------------------------------------------------------ 0 string \xD8\x00\x00 LZMA compressed data, properties: 0xD8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes #------------------------------------------------------------------------------ # $File: sql,v 1.6 2009/09/19 16:28:12 christos Exp $ # sql: file(1) magic for SQL files # # From: "Marty Leisner" # Recognize some MySQL files. # 0 beshort 0xfe01 MySQL table definition file >2 string <1 invalid >2 string >\11 invalid >2 byte x Version %d 0 string \xfe\xfe\x03 MySQL MISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x07 MySQL MISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x05 MySQL ISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x06 MySQL ISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \376bin MySQL replication log #------------------------------------------------------------------------------ # iRiver H Series database file # From Ken Guest # As observed from iRivNavi.iDB and unencoded firmware # 0 string iRivDB iRiver Database file >11 string >\0 Version "%s" >39 string iHP-100 [H Series] #------------------------------------------------------------------------------ # SQLite database files # Ken Guest , Ty Sarna, Zack Weinberg # # Version 1 used GDBM internally; its files cannot be distinguished # from other GDBM files. # # Version 2 used this format: 0 string **\x20This\x20file\x20contains\x20an\x20SQLite SQLite 2.x database # Version 3 of SQLite allows applications to embed their own "user version" # number in the database. Detect this and distinguish those files. 0 string SQLite\x20format\x203 >60 string _MTN Monotone source repository >60 belong !0 SQLite 3.x database, user version %u >60 belong 0 SQLite 3.x database ================================================ FILE: src/binwalk-1.0/src/binwalk/parser.py ================================================ import os.path import tempfile from common import str2int class MagicParser: ''' Class for loading, parsing and creating libmagic-compatible magic files. This class is primarily used internally by the Binwalk class, and a class instance of it is available via the Binwalk.parser object. One useful method however, is file_from_string(), which will generate a temporary magic file from a given signature string: import binwalk bw = binwalk.Binwalk() # Create a temporary magic file that contains a single entry with a signature of '\\x00FOOBAR\\xFF', and append the resulting # temporary file name to the list of magic files in the Binwalk class instance. bw.magic_files.append(bw.parser.file_from_string('\\x00FOOBAR\\xFF', display_name='My custom signature')) bw.scan('firmware.bin') All magic files generated by this class will be deleted when the class deconstructor is called. ''' SHORT_SIZE = 2 SHORTS = ['beshort', 'leshort', 'byte'] BIG_ENDIAN = 'big' LITTLE_ENDIAN = 'little' MAGIC_STRING_FORMAT = "%d\tstring\t%s\t%s\n" DEFAULT_DISPLAY_NAME = "Raw string signature" WILDCARD = 'x' # If libmagic returns multiple results, they are delimited with this string. RESULT_SEPERATOR = "\\012- " # Size of the keys used in the matches set. Limited to 2 # as the key is the magic signature of a given magic file entry. # Entries can have variable length signatures, but the lowest # common demonitor is 2, so the first two bytes of the signature # is used as the key. Does this result in collisions and false # positives? Yes. But false positives are filtered out by the # MagicFilter class. The main purpose of MagicParser.match is to # limit the number of calls to libmagic without itself incurring # large computational overhead. And for that purpose, this is # quite effective. MATCH_INDEX_SIZE = 2 def __init__(self, filter=None, smart=None): ''' Class constructor. @filter - Instance of the MagicFilter class. May be None if the parse/parse_file methods are not used. @smart - Instance of the SmartSignature class. May be None if the parse/parse_file methods are not used. Returns None. ''' self.matches = set([]) self.signatures = {} self.sigset = {} self.filter = filter self.smart = smart self.raw_fd = None self.signature_count = 0 self.fd = tempfile.NamedTemporaryFile() def __del__(self): ''' Class deconstructor. ''' self.cleanup() def cleanup(self): ''' Cleans up any tempfiles created by the class instance. Returns None. ''' # Clean up the tempfiles try: self.fd.close() except: pass try: self.raw_fd.close() except: pass def file_from_string(self, signature_string, offset=0, display_name=DEFAULT_DISPLAY_NAME): ''' Generates a magic file from a signature string. @signature_string - The string signature to search for. @offset - The offset at which the signature should occur. @display_name - The text to display when the signature is found. Returns the name of the generated temporary magic file. ''' self.raw_fd = tempfile.NamedTemporaryFile() self.raw_fd.write(self.MAGIC_STRING_FORMAT % (offset, signature_string, display_name)) self.raw_fd.seek(0) return self.raw_fd.name def parse(self, file_name, filter_short_signatures=True, pre_filter_signatures=True): ''' Parses magic file(s) and contatenates them into a single temporary magic file while simultaneously removing filtered signatures. @file_name - Magic file, or list of magic files, to parse. @filter_short_signatures - Set to False to include entries with short (2 byte) magic signatures. @pre_filter_signatures - Set to False to disable smart signature keywords. Returns the name of the generated temporary magic file, which will be automatically deleted when the class deconstructor is called. ''' if type(file_name) == type([]): files = file_name else: files = [file_name] for fname in files: if os.path.exists(fname): self.parse_file(fname, filter_short_signatures, pre_filter_signatures) self.fd.seek(0) return self.fd.name def parse_file(self, file_name, filter_short_signatures=True, pre_filter_signatures=True): ''' Parses a magic file and appends valid signatures to the temporary magic file, as allowed by the existing filter rules. @file_name - Magic file to parse. @filter_short_signatures - Set to False to include entries with short (2 byte) magic signatures. @pre_filter_signatures - Set to False to disable smart signature keywords. Returns None. ''' # Default to not including signature entries until we've # found what looks like a valid entry. include = False line_count = 0 try: for line in open(file_name).readlines(): line_count += 1 # Check if this is the first line of a signature entry entry = self._parse_line(line) if entry is not None: # Once an entry is identified, default to excluding the entry include = False if pre_filter_signatures: # If the smart signature include keyword is specified for this entry, # add an include filter for this signature description. if self.smart.include(entry['description']): self.filter.include(entry['description'], exclusive=False) include = True # If we haven't already explicitly included this entry, and we are # filtering out short signatures and this is a short signature, then # add an exclude filter for this signature description if not include and filter_short_signatures and self._is_short(entry): self.filter.exclude(entry['description']) # If this signature is marked for inclusion, include it. if self.filter.filter(entry['description']) == self.filter.FILTER_INCLUDE: include = True if include: self.signature_count += 1 if not self.signatures.has_key(entry['offset']): self.signatures[entry['offset']] = [] if entry['condition'][:self.MATCH_INDEX_SIZE] not in self.signatures[entry['offset']]: self.signatures[entry['offset']].append(entry['condition'][:self.MATCH_INDEX_SIZE]) # Keep writing lines of the signature to the temporary magic file until # we detect a signature that should not be included. if include: self.fd.write(line) except Exception, e: raise Exception("Error parsing magic file '%s' on line %d: %s" % (file_name, line_count, str(e))) # Generate a dictionary of offsets with a set of signatures for (offset, siglist) in self.signatures.iteritems(): self.sigset[offset] = set(siglist) def _is_short(self, entry): ''' Determines if a signature entry has a short (2 byte) signature or not. @entry - Entry dictionary, as returned by self._parse_line(). Returns True if the signature is short, False if not short. ''' if entry['type'] in self.SHORTS: return True elif 'string' in entry['type']: if len(entry['condition'].decode('string_escape')) <= self.SHORT_SIZE: return True return False def _parse_line(self, line): ''' Parses a signature line into its four parts (offset, type, condition and description), looking for the first line of a given signature. @line - The signature line to parse. Returns a dictionary with the respective line parts populated if the line is the first of a signature. Returns a dictionary with all parts set to None if the line is not the first of a signature. ''' entry = { 'offset' : '', 'type' : '', 'condition' : '', 'description' : '', 'length' : 0 } # Quick and dirty pre-filter. We are only concerned with the first line of a # signature, which will always start with a number. Make sure the first byte of # the line is a number; if not, don't process. if line[:1] < '0' or line[:1] > '9': return None try: # Split the line into white-space separated parts. # For this to work properly, replace escaped spaces ('\ ') with '\x20'. # This means the same thing, but doesn't confuse split(). line_parts = line.replace('\\ ', '\\x20').split() entry['offset'] = line_parts[0] entry['type'] = line_parts[1] # The condition line may contain escaped sequences, so be sure to decode it properly. entry['condition'] = line_parts[2].decode('string_escape') entry['description'] = ' '.join(line_parts[3:]) except Exception, e: raise Exception("%s :: %s", (str(e), line)) # We've already verified that the first character in this line is a number, so this *shouldn't* # throw an exception, but let's catch it just in case... try: entry['offset'] = str2int(entry['offset']) except Exception, e: raise Exception("%s :: %s", (str(e), line)) # If this is a string, get the length of the string if 'string' in entry['type']: entry['length'] = len(entry['condition']) # Else, we need to jump through a few more hoops... else: # Default to little endian, unless the type field starts with 'be'. # This assumes that we're running on a little endian system... if entry['type'].startswith('be'): endianess = self.BIG_ENDIAN else: endianess = self.LITTLE_ENDIAN # Try to convert the condition to an integer. This does not allow # for more advanced conditions for the first line of a signature, # but needing that is rare. if entry['condition'] != self.WILDCARD: try: intval = str2int(entry['condition'].strip('L')) except Exception, e: raise Exception("Failed to evaluate condition for '%s' type: '%s', condition: '%s', error: %s" % (entry['description'], entry['type'], entry['condition'], str(e))) else: intval = 0 entry['length'] = 1 # How long is the field type? if entry['type'] == 'byte': entry['length'] = 1 elif 'short' in entry['type']: entry['length'] = 2 elif 'long' in entry['type']: entry['length'] = 4 elif 'quad' in entry['type']: entry['length'] = 8 # Convert the integer value to a string of the appropriate endianess entry['condition'] = self._to_string(intval, entry['length'], endianess) return entry def build_signature_set(self): ''' Builds a list of signature tuples. Returns a list of tuples in the format: [(, [set of 2-byte signatures])]. ''' signatures = [] for (offset, sigset) in self.sigset.iteritems(): signatures.append((offset, sigset)) signatures.sort() return signatures def _to_string(self, value, size, endianess): ''' Converts an integer value into a raw string. @value - The integer value to convert. @size - Size, in bytes, of the integer value. @endianess - One of self.LITTLE_ENDIAN | self.BIG_ENDIAN. Returns a raw string containing value. ''' data = "" for i in range(0, size): data += chr((value >> (8*i)) & 0xFF) if endianess != self.LITTLE_ENDIAN: data = data[::-1] return data def split(self, data): ''' Splits multiple libmagic results in the data string into a list of separate results. @data - Data string returned from libmagic. Returns a list of result strings. ''' try: return data.split(self.RESULT_SEPERATOR) except: return [] ================================================ FILE: src/binwalk-1.0/src/binwalk/prettyprint.py ================================================ import sys import hashlib from datetime import datetime class PrettyPrint: ''' Class for printing Binwalk results to screen/log files. An instance of PrettyPrint is available via the Binwalk.display object. The PrettyPrint.results() method is of particular interest, as it is suitable for use as a Binwalk.scan() callback function, and can be used to print Binwalk.scan() results to stdout, a log file, or both. Example usage: import binwalk bw = binwalk.Binwalk() bw.display.header() bw.scan('firmware.bin', callback=bw.display.results) bw.display.footer() ''' def __init__(self, log=None, quiet=False, bwalk=None, verbose=0): ''' Class constructor. @log - Output log file. @quiet - If True, results will not be displayed to screen. @bwalk - The Binwalk class instance. @verbose - If set to True, target file information will be displayed when file_info() is called. Returns None. ''' self.fp = None self.log =log self.quiet = quiet self.binwalk = bwalk self.verbose = verbose if self.log is not None: self.fp = open(log, "w") def __del__(self): ''' Class deconstructor. ''' # Close the log file. try: self.fp.close() except: pass def _log(self, data): ''' Log data to the log file. ''' if self.fp is not None: self.fp.write(data) def _pprint(self, data): ''' Print data to stdout and the log file. ''' if not self.quiet: sys.stdout.write(data) self._log(data) def _file_md5(self, file_name): ''' Generate an MD5 hash of the specified file. ''' md5 = hashlib.md5() with open(file_name, 'rb') as f: for chunk in iter(lambda: f.read(128*md5.block_size), b''): md5.update(chunk) return md5.hexdigest() def file_info(self, file_name): ''' Prints detailed info about the specified file, including file name, scan time and the file's MD5 sum. Called internally by self.header if self.verbose is not 0. @file_name - The path to the target file. Returns None. ''' self._pprint("\n") self._pprint("Scan Time: %s\n" % datetime.now().strftime("%Y-%m-%d %H:%M:%S")) self._pprint("Signatures: %d\n" % self.binwalk.parser.signature_count) self._pprint("Target File: %s\n" % file_name) self._pprint("MD5 Checksum: %s\n" % self._file_md5(file_name)) def header(self, file_name=None): ''' Prints the Binwalk header, typically used just before starting a scan. @file_name - If specified, and if self.verbose > 0, then detailed file info will be included in the header. Returns None. ''' if self.verbose and file_name is not None: self.file_info(file_name) self._pprint("\nDECIMAL \tHEX \tDESCRIPTION\n") self._pprint("-------------------------------------------------------------------------------------------------------\n") def footer(self): ''' Prints the Binwalk footer, typically used just after completing a scan. Returns None. ''' self._pprint("\n") def results(self, offset, results): ''' Prints the results of a scan. Suitable for use as a callback function for Binwalk.scan(). @offset - The offset at which the results were found. @results - A list of libmagic result strings. Returns None. ''' offset_printed = False for info in results: # Check for any grep filters before printing if self.binwalk is not None and self.binwalk.filter.grep(info['description']): # Only display the offset once per list of results if not offset_printed: self._pprint("%-10d\t0x%-8X\t%s\n" % (offset, offset, info['description'])) offset_printed = True else: self._pprint("%s\t %s\t%s\n" % (' '*10, ' '*8, info['description'])) ================================================ FILE: src/binwalk-1.0/src/binwalk/smartsig.py ================================================ import re from common import str2int, get_quoted_strings class SmartSignature: ''' Class for parsing smart signature tags in libmagic result strings. This class is intended for internal use only, but a list of supported 'smart keywords' that may be used in magic files is available via the SmartSignature.KEYWORDS dictionary: from binwalk import SmartSignature for (i, keyword) in SmartSignature().KEYWORDS.iteritems(): print keyword ''' KEYWORD_DELIM_START = "{" KEYWORD_DELIM_END = "}" KEYWORDS = { 'jump' : '%sjump-to-offset:' % KEYWORD_DELIM_START, 'filename' : '%sfile-name:' % KEYWORD_DELIM_START, 'filesize' : '%sfile-size:' % KEYWORD_DELIM_START, 'raw-string' : '%sraw-string:' % KEYWORD_DELIM_START, # This one is special and must come last in a signature block 'raw-size' : '%sraw-string-length:' % KEYWORD_DELIM_START, 'adjust' : '%soffset-adjust:' % KEYWORD_DELIM_START, 'delay' : '%sextract-delay:' % KEYWORD_DELIM_START, 'raw-replace' : '%sraw-replace%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'one-of-many' : '%sone-of-many%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'include' : '%sfilter-include%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'exclude' : '%sfilter-exclude%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), } def __init__(self, filter, pre_filter_signatures=True): ''' Class constructor. @filter - Instance of the MagicFilter class. @pre_filter_signatures - Set to False to disable the pre-filtering of magic signatures. Returns None. ''' self.filter = filter self.last_one_of_many = None self.pre_filter_signatures = pre_filter_signatures def parse(self, data): ''' Parse a given data string for smart signature keywords. If any are found, interpret them and strip them. @data - String to parse, as returned by libmagic. Returns a dictionary of parsed values. ''' results = { 'description' : '', # The libmagic data string, stripped of all keywords 'name' : '', # The original name of the file, if known 'delay' : '', # Extract delay description 'extract' : '', # Name of the extracted file, filled in by Binwalk.Scan. 'jump' : 0, # The relative offset to resume the scan from 'size' : 0, # The size of the file, if known 'adjust' : 0, # The relative offset to add to the reported offset } # If pre-filtering is disabled, or the result data is not valid (i.e., potentially malicious), # don't parse anything, just return the raw data as the description. if not self.pre_filter_signatures or not self._is_valid(data): results['description'] = data else: # Parse the offset-adjust value. This is used to adjust the reported offset at which # a signature was located due to the fact that MagicParser.match expects all signatures # to be located at offset 0, which some wil not be. results['adjust'] = self._get_math_arg(data, 'adjust') # Parse the file-size value. This is used to determine how many bytes should be extracted # when extraction is enabled. If not specified, everything to the end of the file will be # extracted (see Binwalk.scan). try: results['size'] = str2int(self._get_keyword_arg(data, 'filesize')) except: pass results['delay'] = self._get_keyword_arg(data, 'delay') # Parse the string for the jump-to-offset keyword. # This keyword is honored, even if this string result is one of many. results['jump'] = self._get_math_arg(data, 'jump') # If this is one of many, don't do anything and leave description as a blank string. # Else, strip all keyword tags from the string and process additional keywords as necessary. if not self._one_of_many(data): results['name'] = self._get_keyword_arg(data, 'filename').strip('"') results['description'] = self._strip_tags(data) return results def _is_valid(self, data): ''' Validates that result data does not contain smart keywords in file-supplied strings. @data - Data string to validate. Returns True if data is OK. Returns False if data is not OK. ''' # All strings printed from the target file should be placed in strings, else there is # no way to distinguish between intended keywords and unintended keywords. Get all the # quoted strings. quoted_data = get_quoted_strings(data) # Check to see if there was any quoted data, and if so, if it contained the keyword starting delimiter if quoted_data and self.KEYWORD_DELIM_START in quoted_data: # If so, check to see if the quoted data contains any of our keywords. # If any keywords are found inside of quoted data, consider the keywords invalid. for (name, keyword) in self.KEYWORDS.iteritems(): if keyword in quoted_data: return False return True def _one_of_many(self, data): ''' Determines if a given data string is one result of many. @data - String result data. Returns True if the string result is one of many. Returns False if the string result is not one of many. ''' if not self.filter.invalid(data): if self.last_one_of_many is not None and data.startswith(self.last_one_of_many): return True if self.KEYWORDS['one-of-many'] in data: # Only match on the data before the first comma, as that is typically unique and static self.last_one_of_many = data.split(',')[0] else: self.last_one_of_many = None return False def _get_keyword_arg(self, data, keyword): ''' Retrieves the argument for keywords that specify arguments. @data - String result data, as returned by libmagic. @keyword - Keyword index in KEYWORDS. Returns the argument string value on success. Returns a blank string on failure. ''' arg = '' if self.KEYWORDS.has_key(keyword) and self.KEYWORDS[keyword] in data: arg = data.split(self.KEYWORDS[keyword])[1].split(self.KEYWORD_DELIM_END)[0] return arg def _get_math_arg(self, data, keyword): ''' Retrieves the argument for keywords that specifiy mathematical expressions as arguments. @data - String result data, as returned by libmagic. @keyword - Keyword index in KEYWORDS. Returns the resulting calculated value. ''' value = 0 arg = self._get_keyword_arg(data, keyword) if arg: for string_int in arg.split('+'): try: value += str2int(string_int) except: pass return value def _jump(self, data): ''' Obtains the jump-to-offset value of a signature, if any. @data - String result data. Returns the offset to jump to. ''' offset = 0 offset_str = self._get_keyword_arg(data, 'jump') if offset_str: try: offset = str2int(offset_str) except: pass return offset def _parse_raw_strings(self, data): ''' Process strings that aren't NULL byte terminated, but for which we know the string length. This should be called prior to any other smart parsing functions. @data - String to parse. Returns a parsed string. ''' if self.pre_filter_signatures and self._is_valid(data): # Get the raw string keyword arg raw_string = self._get_keyword_arg(data, 'raw-string') # Was a raw string keyword specified? if raw_string: # Get the raw string length arg raw_size = self._get_keyword_arg(data, 'raw-size') # Is the raw string length arg is a numeric value? if re.match('^-?[0-9]+$', raw_size): # Replace all instances of raw-replace in data with raw_string[:raw_size] # Also strip out everything after the raw-string keyword, including the keyword itself. # Failure to do so may (will) result in non-printable characters and this string will be # marked as invalid when it shouldn't be. data = data[:data.find(self.KEYWORDS['raw-string'])].replace(self.KEYWORDS['raw-replace'], '"' + raw_string[:str2int(raw_size)] + '"') return data def include(self, data): ''' Determines if a result should be included or excluded. @data - String result data. Returns True if the include smart tag is present. Returns False if the exclude smart tag is present. Returns None if neither smart tags are present. ''' # Validate keywords before checking for the include/exclude keywords. if self.pre_filter_signatures and self._is_valid(data): if self.KEYWORDS['exclude'] in data: return False elif self.KEYWORDS['include'] in data: return True return None def _strip_tags(self, data): ''' Strips the smart tags from a result string. @data - String result data. Returns a sanitized string. ''' if self.pre_filter_signatures: for (name, keyword) in self.KEYWORDS.iteritems(): start = data.find(keyword) if start != -1: end = data[start:].find(self.KEYWORD_DELIM_END) if end != -1: data = data.replace(data[start:start+end+1], "") return data ================================================ FILE: src/binwalk-1.0/src/binwalk/update.py ================================================ import urllib2 from config import * class Update: ''' Class for updating Binwalk configuration and signatures files from the subversion trunk. Example usage: from binwalk import Update Update().update() ''' BASE_URL = "http://binwalk.googlecode.com/svn/trunk/src/binwalk/" MAGIC_PREFIX = "magic/" CONFIG_PREFIX = "config/" def __init__(self): ''' Class constructor. ''' self.config = Config() def update(self): ''' Updates all system wide signatures and config files. Returns None. ''' self.update_binwalk() self.update_bincast() self.update_binarch() self.update_extract() def _do_update_from_svn(self, prefix, fname): ''' Updates the specified file to the latest version of that file in SVN. @prefix - The URL subdirectory where the file is located. @fname - The name of the file to update. Returns None. ''' url = self.BASE_URL + prefix + fname try: data = urllib2.urlopen(url).read() open(self.config.paths['system'][fname], "wb").write(data) except Exception, e: raise Exception("Update._do_update_from_svn failed to update file '%s': %s" % (url, str(e))) def update_binwalk(self): ''' Updates the binwalk signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINWALK_MAGIC_FILE) def update_bincast(self): ''' Updates the bincast signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINCAST_MAGIC_FILE) def update_binarch(self): ''' Updates the binarch signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINARCH_MAGIC_FILE) def update_extract(self): ''' Updates the extract.conf file. Returns None. ''' self._do_update_from_svn(self.CONFIG_PREFIX, self.config.EXTRACT_FILE) ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/__init__.py ================================================ import os import magic from config import * from update import * from filter import * from parser import * from smartsig import * from extractor import * from prettyprint import * from common import file_size class Binwalk: ''' Primary Binwalk class. Interesting class objects: self.filter - An instance of the MagicFilter class. self.extractor - An instance of the Extractor class. self.parser - An instance of the MagicParser class. self.display - An instance of the PrettyPrint class. self.magic_files - A list of magic file path strings to use whenever the scan() method is invoked. self.scan_length - The total number of bytes to be scanned. self.total_scanned - The number of bytes that have already been scanned. ''' # Default libmagic flags. Basically disable anything we don't need in the name of speed. DEFAULT_FLAGS = magic.MAGIC_NO_CHECK_TEXT | magic.MAGIC_NO_CHECK_ENCODING | magic.MAGIC_NO_CHECK_APPTYPE | magic.MAGIC_NO_CHECK_TOKENS # The MAX_SIGNATURE_SIZE limits the amount of data available to a signature. # While most headers/signatures are far less than this value, some may reference # pointers in the header structure which may point well beyond the header itself. # Passing the entire remaining buffer to libmagic is resource intensive and will # significantly slow the scan; this value represents a reasonable buffer size to # pass to libmagic which will not drastically affect scan time. MAX_SIGNATURE_SIZE = 8092 # Max number of bytes to process at one time. Everyone should have 50MB of memory, right? READ_BLOCK_SIZE = 50 * 1024 * 1024 # Minimum verbosity level at which to enable extractor verbosity. VERY_VERBOSE = 2 # Scan every byte by default. DEFAULT_BYTE_ALIGNMENT = 1 def __init__(self, magic_files=[], flags=magic.MAGIC_NONE, log=None, quiet=False, verbose=0): ''' Class constructor. @magic_files - A list of magic files to use. @flags - Flags to pass to magic_open. [TODO: Might this be more appropriate as an argument to load_signaures?] @log - Output PrettyPrint data to log file as well as to stdout. @quiet - If set to True, supress PrettyPrint output to stdout. @verbose - Verbosity level. Returns None. ''' self.flags = self.DEFAULT_FLAGS | flags self.magic_files = magic_files self.verbose = verbose self.total_scanned = 0 self.scan_length = 0 self.total_read = 0 self.magic = None self.mfile = None # Instantiate the config class so we can access file/directory paths self.config = Config() # Use the system default magic file if no other was specified if not self.magic_files or self.magic_files is None: # Append the user's magic file first so that those signatures take precedence self.magic_files = [ self.config.paths['user'][self.config.BINWALK_MAGIC_FILE], self.config.paths['system'][self.config.BINWALK_MAGIC_FILE], ] # Only set the extractor verbosity if told to be very verbose if self.verbose >= self.VERY_VERBOSE: extractor_verbose = True else: extractor_verbose = False # Create an instance of the PrettyPrint class, which can be used to print results to screen/file. self.display = PrettyPrint(log=log, quiet=quiet, verbose=verbose, bwalk=self) # Create MagicFilter and Extractor class instances. These can be used to: # # o Create include/exclude filters # o Specify file extraction rules to be applied during a scan # self.filter = MagicFilter() self.extractor = Extractor(verbose=extractor_verbose) # Create SmartSignature and MagicParser class instances. These are mostly for internal use. self.smart = SmartSignature(self.filter) self.parser = MagicParser(self.filter, self.smart) def __del__(self): ''' Class deconstructor. ''' self.cleanup() def cleanup(self): ''' Cleanup any temporary files generated by the internal instance of MagicParser. Returns None. ''' try: self.parser.cleanup() except: pass def load_signatures(self, magic_files=[], pre_filter_signatures=True, filter_short_signatures=True): ''' Load signatures from magic file(s). Called automatically by Binwalk.scan() with all defaults, if not already called manually. @magic_files - A list of magic files to use (default: self.magic_files). @pre_filter_signatures - Set to False to disable pre-filtering of signatures before invoking libmagic. @filter_short_signatures - Set to True to include signatures with short (<= 2 byte) magic strings. Returns None. ''' # Disable pre filtering in the smart signature class instance. # This is also checked by Binwalk.scan() before performing pre-filtering. self.smart.pre_filter = pre_filter_signatures # The magic files specified here override any already set if magic_files and magic_files is not None: self.magic_files = magic_files # Parse the magic file(s) and initialize libmagic self.mfile = self.parser.parse(self.magic_files, filter_short_signatures=filter_short_signatures, pre_filter_signatures=pre_filter_signatures) self.magic = magic.open(self.flags) self.magic.load(self.mfile) def scan(self, target_file, offset=0, length=0, align=DEFAULT_BYTE_ALIGNMENT, show_invalid_results=False, callback=None): ''' Performs a Binwalk scan on the target file. @target_file - File to scan. @offset - Starting offset at which to start the scan. @length - Number of bytes to scan. @align - Look for signatures every align bytes. @show_invalid_results - Set to True to display invalid results. @callback - Callback function to be invoked when matches are found. The callback function is passed two arguments: a list of result dictionaries containing the scan results (one result per dict), and the offset at which those results were identified. Example callback function: def my_callback(offset, results): print "Found %d results at offset %d:" % (len(results), offset) for result in results: print "\t%s" % result['description'] binwalk.Binwalk(callback=my_callback).scan("firmware.bin") Upon completion, the scan method returns a sorted list of tuples containing a list of results dictionaries and the offsets at which those results were identified: scan_items = [ (0, [{description : "LZMA compressed data..."}]), (112, [{description : "gzip compressed data..."}]) ] See SmartSignature.parse for a more detailed description of the results dictionary structure. ''' scan_results = {} self.total_read = 0 self.total_scanned = 0 self.scan_length = length self.filter.show_invalid_results = show_invalid_results # Load the default signatures if self.load_signatures has not already been invoked if self.magic is None: self.load_signatures() # Get a local copy of the signature sets generated by self.parser.build_signature_set. # This is accessed heavily throughout the scan, and there is less overhead for accessing local variables in Python. signature_set = self.parser.build_signature_set() # Need the total size of the target file, even if we aren't scanning the whole thing fsize = file_size(target_file) # Open the target file and seek to the specified start offset fd = open(target_file) fd.seek(offset) # If no length was specified, make the length the size of the target file minus the starting offset if self.scan_length == 0: self.scan_length = fsize - offset # Sanity check on the byte alignment; default to 1 if align <= 0: align = 1 # Main loop, scan through all the data while True: i = 0 # Read in the next block of data from the target file and make sure it's valid (data, dlen) = self._read_block(fd) if data is None or dlen == 0: break # The total number of bytes scanned could be bigger than the total number # of bytes read from the file under the following circumstances: # # o The previous dlen was not a multiple of align # o A previous result specified a jump offset that was beyond the end of the # then current data block # # If this is the case, we need to index into this data block appropriately in order to # resume the scan from the appropriate offset, and adjust dlen accordingly. bufindex = self.total_scanned - self.total_read if bufindex > 0: # If the total_scanned > total_read, then the total_scanned offset is in a subsequent block. # Set i to bufindex, which will cause i to be greater than dlen and this block will be skipped. i = bufindex elif bufindex < 0: # If the total_scanned offset is less than total_read, then the total_scanned offset is # somewhere inside this block. Set i to index into the block appropriately. i = dlen + bufindex else: # If the total_scanned offset ends at the end of this block, don't scan any of this block i = dlen # Scan through each block of data looking for signatures while i < dlen: smart = {} results = [] results_offset = -1 pre_filter_ok = False smart_jump_done = False # Pre-filter data by checking to see if the parser thinks this might be a valid match. # This eliminates unnecessary calls into libmagic, which are very expensive. # # Ideally, this should be done in the MagicParser class, but function calls are expensive. # Doing it here greatly decreases the scan time. if self.smart.pre_filter: for (sig_offset, sigset) in signature_set: if data[i+sig_offset:i+sig_offset+self.parser.MATCH_INDEX_SIZE] in sigset: pre_filter_ok = True break else: pre_filter_ok = True if pre_filter_ok: # Pass the data to libmagic, and split out multiple results into a list for magic_result in self.parser.split(self.magic.buffer(data[i:i+self.MAX_SIGNATURE_SIZE])): # Some file names are not NULL byte terminated, but rather their length is # specified in a size field. To ensure these are not marked as invalid due to # non-printable characters existing in the file name, parse the filename(s) and # trim them to the specified filename length, if one was specified. magic_result = self.smart._parse_raw_strings(magic_result) # Make sure this is a valid result before further processing if not self.filter.invalid(magic_result): # The smart filter parser returns a dictionary of keyword values and the signature description. smart = self.smart.parse(magic_result) # Validate the jump value and check if the response description should be displayed if smart['jump'] > -1 and self._should_display(smart['description']): # If multiple results are returned and one of them has smart['jump'] set to a non-zero value, # the calculated results offset will be wrong since i will have been incremented. Only set the # results_offset value when the first match is encountered. if results_offset < 0: results_offset = offset + smart['adjust'] + self.total_scanned # Double check to make sure the smart['adjust'] value is sane. # If it makes results_offset negative, then it is not sane. if results_offset >= 0: # Extract the result, if it matches one of the extract rules and is not a delayed extract. if self.extractor.enabled and not (self.extractor.delayed and smart['delay']): # If the signature did not specify a size, extract to the end of the file. if smart['size'] == 0: smart['size'] = fsize-results_offset smart['extract'] = self.extractor.extract( results_offset, smart['description'], target_file, smart['size'], name=smart['name']) # This appears to be a valid result, so append it to the results list. results.append(smart) # Jump to the offset specified by jump. Only do this once, so that if multiple results # are returned each of which specify a jump offset, only the first will be honored. if smart['jump'] > 0 and not smart_jump_done: # Once a jump offset has been honored, we need to start scanning every byte since the # jump offset may have thrown off the original alignment. In terms of speed this is fine, # since the jump offset usually saves more time anyway. If this is not what the user # wanted/intended, disabling pre filtering will disable jump offset processing completely. align = self.DEFAULT_BYTE_ALIGNMENT smart_jump_done = True i += (smart['jump'] - align) self.total_scanned += (smart['jump'] - align) # Did we find any valid results? if results_offset >= 0: scan_results[results_offset] = results if callback is not None: callback(results_offset, results) # Track the number of bytes scanned in this block, and the total number of bytes scanned. i += align self.total_scanned += align # Sort the results before returning them scan_items = scan_results.items() scan_items.sort() # Do delayed extraction, if specified. if self.extractor.enabled and self.extractor.delayed: scan_items = self.extractor.delayed_extract(scan_items, target_file, fsize) return scan_items def _should_display(self, data): ''' Determines if a result string should be displayed to the user or not. @data - Display string. Returns True if the string should be displayed. Returns False if the string should not be displayed. ''' return (data and data is not None and not self.filter.invalid(data) and self.filter.filter(data) != self.filter.FILTER_EXCLUDE) def _read_block(self, fd): ''' Reads in a block of data from the target file. @fd - File object for the target file. Returns a tuple of (file block data, block data length). ''' dlen = 0 data = None # Read in READ_BLOCK_SIZE plus MAX_SIGNATURE_SIZE bytes, but return a max dlen value # of READ_BLOCK_SIZE. This ensures that there is a MAX_SIGNATURE_SIZE buffer at the # end of the returned data in case a signature is found at or near data[dlen]. rlen = self.READ_BLOCK_SIZE + self.MAX_SIGNATURE_SIZE if self.total_read < self.scan_length: data = fd.read(rlen) if data and data is not None: # Get the actual length of the read in data dlen = len(data) # If we've read in more data than the scan length, truncate the dlen value if (self.total_read + dlen) >= self.scan_length: dlen = self.scan_length - self.total_read # If dlen is the expected rlen size, it should be set to READ_BLOCK_SIZE elif dlen == rlen: dlen = self.READ_BLOCK_SIZE # Increment self.total_read to reflect the amount of data that has been read # for processing (actual read size is larger of course, due to the MAX_SIGNATURE_SIZE # buffer of data at the end of each block). self.total_read += dlen # Seek to the self.total_read offset so the next read can pick up where this one left off fd.seek(self.total_read) return (data, dlen) ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/common.py ================================================ # Common functions. import os import re def file_size(filename): ''' Obtains the size of a given file. @filename - Path to the file. Returns the size of the file. ''' # Using open/lseek works on both regular files and block devices fd = os.open(filename, os.O_RDONLY) try: return os.lseek(fd, 0, os.SEEK_END) except Exception, e: raise Exception("file_size failed to obtain the size of '%s': %s" % (filename, str(e))) finally: os.close(fd) def str2int(string): ''' Attempts to convert string to a base 10 integer; if that fails, then base 16. @string - String to convert to an integer. Returns the integer value on success. Throws an exception if the string cannot be converted into either a base 10 or base 16 integer value. ''' try: return int(string) except: return int(string, 16) def strip_quoted_strings(string): ''' Strips out data in between double quotes. @string - String to strip. Returns a sanitized string. ''' # This regex removes all quoted data from string. # Note that this removes everything in between the first and last double quote. # This is intentional, as printed (and quoted) strings from a target file may contain # double quotes, and this function should ignore those. However, it also means that any # data between two quoted strings (ex: '"quote 1" you won't see me "quote 2"') will also be stripped. return re.sub(r'\"(.*)\"', "", string) def get_quoted_strings(string): ''' Returns a string comprised of all data in between double quotes. @string - String to get quoted data from. Returns a string of quoted data on success. Returns a blank string if no quoted data is present. ''' try: # This regex grabs all quoted data from string. # Note that this gets everything in between the first and last double quote. # This is intentional, as printed (and quoted) strings from a target file may contain # double quotes, and this function should ignore those. However, it also means that any # data between two quoted strings (ex: '"quote 1" non-quoted data "quote 2"') will also be included. return re.findall(r'\"(.*)\"', string)[0] except: return '' ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/config/extract.conf ================================================ ################################################################################################################# # Default extract rules loaded when --extract is specified. # # :: # # Note that %e is a place holder for the extracted file name. ################################################################################################################# # Assumes these utilities are installed in $PATH. gzip compressed data:gz:gzip -d -f '%e' lzma compressed data:7z:7zr e -y '%e' bzip2 compressed data:bz2:bzip2 -d -f '%e' zip archive data:zip:jar xf '%e' # jar does a better job of unzipping than unzip does... posix tar archive:tar:tar xvf '%e' # These assume the firmware-mod-kit is installed to /opt/firmware-mod-kit. # If not, change the file paths appropriately. squashfs filesystem:squashfs:/opt/firmware-mod-kit/trunk/unsquashfs_all.sh '%e' jffs2 filesystem:jffs2:/opt/firmware-mod-kit/trunk/src/jffs2/unjffs2 '%e' # requires root cpio archive:cpio:/opt/firmware-mod-kit/trunk/uncpio.sh '%e' # Extract, but don't run anything ext2 filesystem:ext2 romfs filesystem:romfs cramfs filesystem:cramfs private key:key ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/config.py ================================================ import os class Config: ''' Binwalk configuration class, used for accessing user and system file paths. After instatiating the class, file paths can be accessed via the self.paths dictionary. System file paths are listed under the 'system' key, user file paths under the 'user' key. For example, to get the path to both the user and system binwalk magic files: from binwalk import Config conf = Config() user_binwalk_file = conf.paths['user'][conf.BINWALK_MAGIC_FILE] system_binwalk_file = conf.paths['system'][conf.BINWALK_MAGIC_FILE] There is also an instance of this class available via the Binwalk.config object: import binwalk bw = binwalk.Binwalk() user_binwalk_file = bw.config.paths['user'][conf.BINWALK_MAGIC_FILE] system_binwalk_file = bw.config.paths['system'][conf.BINWALK_MAGIC_FILE] Valid file names under both the 'user' and 'system' keys are as follows: o BINWALK_MAGIC_FILE - Path to the default binwalk magic file. o BINCAST_MAGIC_FILE - Path to the bincast magic file (used when -C is specified with the command line binwalk script) o BINARCH_MAGIC_FILE - Path to the binarch magic file (used when -A is specified with the command line binwalk script) o EXTRACT_FILE - Path to the extract configuration file (used when -e is specified with the command line binwalk script) ''' # Release version VERSION = "1.0" # Sub directories BINWALK_USER_DIR = ".binwalk" BINWALK_MAGIC_DIR = "magic" BINWALK_CONFIG_DIR = "config" # File names EXTRACT_FILE = "extract.conf" BINWALK_MAGIC_FILE = "binwalk" BINCAST_MAGIC_FILE = "bincast" BINARCH_MAGIC_FILE = "binarch" def __init__(self): ''' Class constructor. Enumerates file paths and populates self.paths. ''' # Path to the user binwalk directory self.user_dir = self._get_user_dir() # Path to the system wide binwalk directory self.system_dir = self._get_system_dir() # Dictionary of all absolute user/system file paths self.paths = { 'user' : {}, 'system' : {}, } # Build the paths to all user-specific files self.paths['user'][self.BINWALK_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINWALK_MAGIC_FILE) self.paths['user'][self.BINCAST_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINCAST_MAGIC_FILE) self.paths['user'][self.BINARCH_MAGIC_FILE] = self._user_file(self.BINWALK_MAGIC_DIR, self.BINARCH_MAGIC_FILE) self.paths['user'][self.EXTRACT_FILE] = self._user_file(self.BINWALK_CONFIG_DIR, self.EXTRACT_FILE) # Build the paths to all system-wide files self.paths['system'][self.BINWALK_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINWALK_MAGIC_FILE) self.paths['system'][self.BINCAST_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINCAST_MAGIC_FILE) self.paths['system'][self.BINARCH_MAGIC_FILE] = self._system_file(self.BINWALK_MAGIC_DIR, self.BINARCH_MAGIC_FILE) self.paths['system'][self.EXTRACT_FILE] = self._system_file(self.BINWALK_CONFIG_DIR, self.EXTRACT_FILE) def _get_system_dir(self): ''' Find the directory where the binwalk module is installed on the system. ''' try: root = __file__ if os.path.islink(root): root = os.path.realpath(root) return os.path.dirname(os.path.abspath(root)) except: return '' def _get_user_dir(self): ''' Get the user's home directory. ''' try: # This should work in both Windows and Unix environments return os.getenv('USERPROFILE') or os.getenv('HOME') except: return '' def _file_path(self, dirname, filename): ''' Builds an absolute path and creates the directory and file if they don't already exist. @dirname - Directory path. @filename - File name. Returns a full path of 'dirname/filename'. ''' if not os.path.exists(dirname): try: os.makedirs(dirname) except: pass fpath = os.path.join(dirname, filename) if not os.path.exists(fpath): try: open(fpath, "w").close() except: pass return fpath def _user_file(self, subdir, basename): ''' Gets the full path to the 'subdir/basename' file in the user binwalk directory. @subdir - Subdirectory inside the user binwalk directory. @basename - File name inside the subdirectory. Returns the full path to the 'subdir/basename' file. ''' return self._file_path(os.path.join(self.user_dir, self.BINWALK_USER_DIR, subdir), basename) def _system_file(self, subdir, basename): ''' Gets the full path to the 'subdir/basename' file in the system binwalk directory. @subdir - Subdirectory inside the system binwalk directory. @basename - File name inside the subdirectory. Returns the full path to the 'subdir/basename' file. ''' return self._file_path(os.path.join(self.system_dir, subdir), basename) ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/extractor.py ================================================ import os import sys import shlex import tempfile import subprocess from config import * from common import file_size class Extractor: ''' Extractor class, responsible for extracting files from the target file and executing external applications, if requested. An instance of this class is accessible via the Binwalk.extractor object. Example usage: import binwalk bw = binwalk.Binwalk() # Create extraction rules for scan results containing the string 'gzip compressed data' and 'filesystem'. # The former will be saved to disk with a file extension of 'gz' and the command 'gunzip ' will be executed (note the %e placeholder). # The latter will be saved to disk with a file extension of 'fs' and no command will be executed. # These rules will take precedence over subsequent rules with the same match string. bw.extractor.add_rule(['gzip compressed data:gz:gunzip %e', 'filesystem:fs']) # Load the extraction rules from the default extract.conf file(s). bw.extractor.load_defaults() # Run the binwalk scan. bw.scan('firmware.bin') ''' # Extract rules are delimited with a colon. # :[:] RULE_DELIM = ':' # Comments in the extract.conf files start with a pound COMMENT_DELIM ='#' # Place holder for the extracted file name in the command FILE_NAME_PLACEHOLDER = '%e' def __init__(self, verbose=False): ''' Class constructor. @verbose - Set to True to display the output from any executed external applications. Returns None. ''' self.config = Config() self.enabled = False self.delayed = False self.verbose = verbose self.extract_rules = {} self.remove_after_execute = False def add_rule(self, rule): ''' Adds a set of rules to the extraction rule list. @rule - Rule string, or list of rule strings, in the format :[:] Returns None. ''' r = { 'extension' : '', 'cmd' : '' } if type(rule) != type([]): rules = [rule] else: rules = rule for rule in rules: r['cmd'] = '' r['extension'] = '' try: values = self._parse_rule(rule) match = values[0].lower() r['extension'] = values[1] r['cmd'] = values[2] except: pass # Verify that the match string and file extension were retrieved. # Only add the rule if it is a new one (first come, first served). if match and r['extension'] and not self.extract_rules.has_key(match): self.extract_rules[match] = {} self.extract_rules[match]['cmd'] = r['cmd'] self.extract_rules[match]['extension'] = r['extension'] # Once any rule is added, set self.enabled to True self.enabled = True def enable_delayed_extract(self, tf=None): ''' Enables / disables the delayed extraction feature. This feature ensures that certian supported file types will not contain extra data at the end of the file when they are extracted, but also means that these files will not be extracted until the end of the scan. @tf - Set to True to enable, False to disable. Returns the current delayed extraction setting. ''' if tf is not None: self.delayed = tf return self.delayed def load_from_file(self, fname): ''' Loads extraction rules from the specified file. @fname - Path to the extraction rule file. Returns None. ''' try: # Process each line from the extract file, ignoring comments for rule in open(fname).readlines(): self.add_rule(rule.split(self.COMMENT_DELIM, 1)[0]) except Exception, e: raise Exception("Extractor.load_from_file failed to load file '%s': %s" % (fname, str(e))) def load_defaults(self): ''' Loads default extraction rules from the user and system extract.conf files. Returns None. ''' # Load the user extract file first to ensure its rules take precedence. extract_files = [ self.config.paths['user'][self.config.EXTRACT_FILE], self.config.paths['system'][self.config.EXTRACT_FILE], ] for extract_file in extract_files: try: self.load_from_file(extract_file) except Exception, e: if self.verbose: raise Exception("Extractor.load_defaults failed to load file '%s': %s" % (extract_file, str(e))) def cleanup_extracted_files(self, tf=None): ''' Set the action to take after a file is extracted. @tf - If set to True, extracted files will be cleaned up after running a command against them. If set to False, extracted files will not be cleaned up after running a command against them. If set to None or not specified, the current setting will not be changed. Returns the current cleanup status (True/False). ''' if tf is not None: self.remove_after_execute = tf return self.remove_after_execute def extract(self, offset, description, file_name, size, name=None): ''' Extract an embedded file from the target file, if it matches an extract rule. Called automatically by Binwalk.scan(). @offset - Offset inside the target file to begin the extraction. @description - Description of the embedded file to extract, as returned by libmagic. @file_name - Path to the target file. @size - Number of bytes to extract. @name - Name to save the file as. Returns the name of the extracted file (blank string if nothing was extracted). ''' cleanup_extracted_fname = True rule = self._match(description) if rule is not None: fname = self._dd(file_name, offset, size, rule['extension'], output_file_name=name) if rule['cmd']: # Many extraction utilities will extract the file to a new file, just without # the file extension (i.e., myfile.7z => myfile). If the presumed resulting # file name already exists before executing the extract command, do not attempt # to clean it up even if its resulting file size is 0. if self.remove_after_execute: extracted_fname = os.path.splitext(fname)[0] if os.path.exists(extracted_fname): cleanup_extracted_fname = False # Execute the specified command against the extracted file self._execute(rule['cmd'], fname) # Only clean up files if remove_after_execute was specified if self.remove_after_execute: # Remove the original file that we extracted try: os.unlink(fname) except: pass # If the command worked, assume it removed the file extension from the extracted file # If the extracted file name file exists and is empty, remove it if cleanup_extracted_fname and os.path.exists(extracted_fname) and file_size(extracted_fname) == 0: try: os.unlink(extracted_fname) except: pass else: fname = '' return fname def delayed_extract(self, results, file_name, size): ''' Performs a delayed extraction (see self.enable_delayed_extract). Called internally by Binwalk.Scan(). @results - A list of dictionaries of all the scan results. @file_name - The path to the scanned file. @size - The size of the scanned file. Returns an updated results list containing the names of the newly extracted files. ''' index = 0 info_count = 0 nresults = results for (offset, infos) in results: info_count = 0 for info in infos: ninfos = infos if info['delay']: end_offset = self._entry_offset(index, results, info['delay']) if end_offset == -1: extract_size = size else: extract_size = (end_offset - offset) ninfos[info_count]['extract'] = self.extract(offset, info['description'], file_name, extract_size, info['name']) nresults[index] = (offset, ninfos) info_count += 1 index += 1 return nresults def _entry_offset(self, index, entries, description): ''' Gets the offset of the first entry that matches the description. @index - Index into the entries list to begin searching. @entries - Dictionary of result entries. @description - Case insensitive description. Returns the offset, if a matching description is found. Returns -1 if a matching description is not found. ''' description = description.lower() for (offset, infos) in entries[index:]: for info in infos: if info['description'].lower().startswith(description): return offset return -1 def _match(self, description): ''' Check to see if the provided description string matches an extract rule. Called internally by self.extract(). @description - Description string to check. Returns the associated rule dictionary if a match is found. Returns None if no match is found. ''' description = description.lower() for (m, rule) in self.extract_rules.iteritems(): if m in description: return rule return None def _parse_rule(self, rule): ''' Parses an extraction rule. @rule - Rule string. Returns an array of ['', '', '']. ''' return rule.strip().split(self.RULE_DELIM, 2) def _dd(self, file_name, offset, size, extension, output_file_name=None): ''' Extracts a file embedded inside the target file. @file_name - Path to the target file. @offset - Offset inside the target file where the embedded file begins. @size - Number of bytes to extract. @extension - The file exension to assign to the extracted file on disk. @output_file_name - The requested name of the output file. Returns the extracted file name. ''' # Default extracted file name is . altname = "%X.%s" % (offset, extension) if not output_file_name or output_file_name is None: fname = altname else: fname = "%s.%s" % (output_file_name, extension) # Sanitize output file name of invalid/dangerous characters (like file paths) fname = os.path.basename(fname) try: # Open the target file and seek to the offset fdin = open(file_name, "rb") fdin.seek(offset) # Open the extracted file try: fdout = open(fname, "wb") except: # Fall back to the alternate name if the requested name fails fname = altname fdout = open(fname, "wb") # Read size bytes from target file and write it to the extracted file fdout.write(fdin.read(size)) # Cleanup fdout.close() fdin.close() except Exception, e: raise Exception("Extractor.dd failed to extract data from '%s' to '%s': %s" % (file_name, fname, str(e))) return fname def _execute(self, cmd, fname): ''' Execute a command against the specified file. @cmd - Command to execute. @fname - File to run command against. Returns None. ''' tmp = None # If not in verbose mode, create a temporary file to redirect stdout and stderr to if not self.verbose: tmp = tempfile.TemporaryFile() try: # Replace all instances of FILE_NAME_PLACEHOLDER in the command with fname cmd = cmd.replace(self.FILE_NAME_PLACEHOLDER, fname) # Execute. subprocess.call(shlex.split(cmd), stdout=tmp, stderr=tmp) except Exception, e: sys.stderr.write("WARNING: Extractor.execute failed to run '%s': %s\n" % (cmd, str(e))) if tmp is not None: tmp.close() ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/filter.py ================================================ import common from smartsig import SmartSignature class MagicFilter: ''' Class to filter libmagic results based on include/exclude rules and false positive detection. An instance of this class is available via the Binwalk.filter object. Example code which creates include, exclude, and grep filters before running a Binwalk scan: import binwalk bw = binwalk.Binwalk() # Include all signatures whose descriptions contain the string 'filesystem' in the first line of the signature, even if those signatures are normally excluded. # Note that if exclusive=False was specified, this would merely add these signatures to the default signatures. # Since exclusive=True (the default) has been specified, ONLY those matching signatures will be loaded; all others will be ignored. bw.filter.include('filesystem') # Exclude all signatures whose descriptions contain the string 'jffs2', even if those signatures are normally included. # In this case, we are now searching for all filesystem signatures, except JFFS2. bw.filter.exclude('jffs2') # Add a grep filter. Unlike the include and exclude filters, it does not affect which results are returned by Binwalk.scan(), but it does affect which results # are printed by Binwalk.display.results(). This is particularly useful for cases like the bincast scan, where multiple lines of results are returned per offset, # but you only want certian ones displayed. In this case, only file systems whose description contain the string '2012' will be displayed. bw.filter.grep(filters=['2012']) bw.scan('firmware.bin') ''' # If the result returned by libmagic is "data" or contains the text # 'invalid' or a backslash are known to be invalid/false positives. DATA_RESULT = "data" INVALID_RESULTS = ["invalid", "\\"] INVALID_RESULT = "invalid" NON_PRINTABLE_RESULT = "\\" FILTER_INCLUDE = 0 FILTER_EXCLUDE = 1 def __init__(self, show_invalid_results=False): ''' Class constructor. @show_invalid_results - Set to True to display results marked as invalid. Returns None. ''' self.filters = [] self.grep_filters = [] self.show_invalid_results = show_invalid_results self.exclusive_filter = False self.smart = SmartSignature(self) def include(self, match, exclusive=True): ''' Adds a new filter which explicitly includes results that contain the specified matching text. @match - Case insensitive text, or list of texts, to match. @exclusive - If True, then results that do not explicitly contain a FILTER_INCLUDE match will be excluded. If False, signatures that contain the FILTER_INCLUDE match will be included in the scan, but will not cause non-matching results to be excluded. Returns None. ''' include_filter = { 'type' : self.FILTER_INCLUDE, 'filter' : '' } if type(match) != type([]): matches = [match] else: matches = match for m in matches: if m: if exclusive and not self.exclusive_filter: self.exclusive_filter = True include_filter['filter'] = m.lower() self.filters.append(include_filter) def exclude(self, match): ''' Adds a new filter which explicitly excludes results that contain the specified matching text. @match - Case insensitive text, or list of texts, to match. Returns None. ''' exclude_filter = { 'type' : self.FILTER_EXCLUDE, 'filter' : '' } if type(match) != type([]): matches = [match] else: matches = match for m in matches: if m: exclude_filter['filter'] = m.lower() self.filters.append(exclude_filter) def filter(self, data): ''' Checks to see if a given string should be excluded from or included in the results. Called internally by Binwalk.scan(). @data - String to check. Returns FILTER_INCLUDE if the string should be included. Returns FILTER_EXCLUDE if the string should be excluded. ''' data = data.lower() # Loop through the filters to see if any of them are a match. # If so, return the registered type for the matching filter (FILTER_INCLUDE | FILTER_EXCLUDE). for f in self.filters: if f['filter'] in data: return f['type'] # If there was not explicit match and exclusive filtering is enabled, return FILTER_EXCLUDE. if self.exclusive_filter: return self.FILTER_EXCLUDE return self.FILTER_INCLUDE def invalid(self, data): ''' Checks if the given string contains invalid data. Called internally by Binwalk.scan(). @data - String to validate. Returns True if data is invalid, False if valid. ''' # A result of 'data' is never ever valid. if data == self.DATA_RESULT: return True # If showing invalid results, just return False. if self.show_invalid_results: return False # Don't include quoted strings or keyword arguments in this search, as # strings from the target file may legitimately contain the INVALID_RESULT text. if self.INVALID_RESULT in common.strip_quoted_strings(self.smart._strip_tags(data)): return True # There should be no non-printable data in any of the data if self.NON_PRINTABLE_RESULT in data: return True return False def grep(self, data=None, filters=[]): ''' Add or check case-insensitive grep filters against the supplied data string. @data - Data string to check grep filters against. Not required if filters is specified. @filters - Filter, or list of filters, to add to the grep filters list. Not required if data is specified. Returns None if data is not specified. If data is specified, returns True if the data contains a grep filter, or if no grep filters exist. If data is specified, returns False if the data does not contain any grep filters. ''' # Add any specified filters to self.grep_filters if filters: if type(filters) != type([]): gfilters = [filters] else: gfilters = filters for gfilter in gfilters: # Filters are case insensitive self.grep_filters.append(gfilter.lower()) # Check the data against all grep filters until one is found if data is not None: # If no grep filters have been created, always return True if not self.grep_filters: return True # Filters are case insensitive data = data.lower() # If a filter exists in data, return True for gfilter in self.grep_filters: if gfilter in data: return True # Else, return False return False return None def clear(self): ''' Clears all include, exclude and grep filters. Retruns None. ''' self.filters = [] self.grep_filters = [] ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/magic/binarch ================================================ # MIPS prologue # addiu $sp, -XX # 27 BD FF XX 1 string \377\275\47 MIPSEL function prologue 0 string \47\275\377 MIPS function prologue # MIPS epilogue # jr $ra 0 belong 0x03e00008 MIPS function epilogue 0 lelong 0x03e00008 MIPSEL function epilogue # PowerPC epilogue # blr 0 belong 0x4E800020 PowerPC big endian function epilogue 0 lelong 0x4E800020 PowerPC little endian function epilogue # ARM prologue # STMFD SP!, {XX} 0 beshort 0xE92D ARMEB function prologue 2 leshort 0xE92D ARM function prologue # ARM epilogue # LDMFD SP!, {XX} 0 beshort 0xE8BD ARMEB function epilogue 2 leshort 0xE8BD ARM function epilogue # x86 epilogue # push ebp # move ebp, esp 0 string \x55\x89\xE5 Intel x86 function epilogue ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/magic/bincast ================================================ 0 belong x Hex: 0x%.8X #0 string x String: %s 0 lelong x Little Endian Long: %d 0 belong x Big Endian Long: %d 0 leshort x Little Endian Short: %d 0 beshort x Big Endian Short: %d 0 ledate x Little Endian Date: %s 0 bedate x Big Endian Date: %s ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/magic/binwalk ================================================ # ----------------------------Archive Formats-------------------------------------- # POSIX tar archives 0 string ustar\000 POSIX tar archive{offset-adjust:-257} 0 string ustar\040\040\000 POSIX tar archive (GNU){offset-adjust:-257} # JAR archiver (.j), this is the successor to ARJ, not Java's JAR (which is essentially ZIP) 0 string \x1aJar\x1b JAR (ARJ Software, Inc.) archive data{offset-adjust:-14} 0 string JARCS JAR (ARJ Software, Inc.) archive data # ARJ archiver (jason@jarthur.Claremont.EDU) 0 leshort 0xea60 ARJ archive data >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: "%s", >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # RAR archiver (Greg Roelofs, newt@uchicago.edu) 0 string Rar! RAR archive data # HPACK archiver (Peter Gutmann, pgut1@cs.aukuni.ac.nz) 0 string HPAK HPACK archive data # JAM Archive volume format, by Dmitry.Kohmanyuk@UA.net 0 string \351,\001JAM JAM archive # LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) 0 string -lzs- LHa 2.x? archive data [lzs] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh\40- LHa 2.x? archive data [lh ] [NSRL|LHA2]{offset-adjust:-2} 0 string -lhd- LHa 2.x? archive data [lhd] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh2- LHa 2.x? archive data [lh2] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh3- LHa 2.x? archive data [lh3] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh4- LHa (2.x) archive data [lh4] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh5- LHa (2.x) archive data [lh5] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh6- LHa (2.x) archive data [lh6] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh7- LHa (2.x) archive data [lh7] [NSRL|LHA2]{offset-adjust:-2} # cpio archives # # The SVR4 "cpio(4)" hints that there are additional formats, but they # are defined as "short"s; I think all the new formats are # character-header formats and thus are strings, not numbers. #0 string 070707 ASCII cpio archive (pre-SVR4 or odc) 0 string 070701 ASCII cpio archive (SVR4 with no CRC), >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} 0 string 070702 ASCII cpio archive (SVR4 with CRC) >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} # HP Printer Job Language # The header found on Win95 HP plot files is the "Silliest Thing possible" # (TM) # Every driver puts the language at some random position, with random case # (LANGUAGE and Language) # For example the LaserJet 5L driver puts the "PJL ENTER LANGUAGE" in line 10 # From: Uwe Bonnes # 0 string \033%-12345X@PJL HP Printer Job Language data >&0 string >\0 "%s" >>&0 string >\0 "%s" >>>&0 string >\0 "%s" >>>>&0 string >\0 "%s" #------------------------------------------------------------------------------ # # RPM: file(1) magic for Red Hat Packages Erik Troan (ewt@redhat.com) # 0 belong 0xedabeedb RPM >4 byte x v%d >6 beshort 0 bin >6 beshort 1 src >8 beshort 1 i386 >8 beshort 2 Alpha >8 beshort 3 Sparc >8 beshort 4 MIPS >8 beshort 5 PowerPC >8 beshort 6 68000 >8 beshort 7 SGI >8 beshort 8 RS6000 >8 beshort 9 IA64 >8 beshort 10 Sparc64 >8 beshort 11 MIPSel >8 beshort 12 ARM >10 string x "%s" #---------------------------Bootloaders-------------------------------- # CFE bootloader 0 string CFE1CFE1 CFE boot loader, little endian 0 string 1EFC1EFC CFE boot loader, big endian #------------------Compression Formats----------------------------- # AFX compressed files (Wolfram Kleff) 0 string -afx- AFX compressed file data{offset-adjust:-2} # bzip2 0 string BZh91AY&SY bzip2 compressed data, block size = 900k 0 string BZh81AY&SY bzip2 compressed data, block size = 800k 0 string BZh71AY&SY bzip2 compressed data, block size = 700k 0 string BZh61AY&SY bzip2 compressed data, block size = 600k 0 string BZh51AY&SY bzip2 compressed data, block size = 500k 0 string BZh41AY&SY bzip2 compressed data, block size = 400k 0 string BZh31AY&SY bzip2 compressed data, block size = 300k 0 string BZh21AY&SY bzip2 compressed data, block size = 200k 0 string BZh11AY&SY bzip2 compressed data, block size = 100k # lzop from 0 string \x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a lzop compressed data >9 beshort <0x0940 >>9 byte&0xf0 =0x00 - version 0. >>9 beshort&0x0fff x \b%03x, >>13 byte 1 LZO1X-1, >>13 byte 2 LZO1X-1(15), >>13 byte 3 LZO1X-999, ## >>22 bedate >0 last modified: %s, >>14 byte =0x00 os: MS-DOS >>14 byte =0x01 os: Amiga >>14 byte =0x02 os: VMS >>14 byte =0x03 os: Unix >>14 byte =0x05 os: Atari >>14 byte =0x06 os: OS/2 >>14 byte =0x07 os: MacOS >>14 byte =0x0A os: Tops/20 >>14 byte =0x0B os: WinNT >>14 byte =0x0E os: Win32 >9 beshort >0x0939 >>9 byte&0xf0 =0x00 - version 0. >>9 byte&0xf0 =0x10 - version 1. >>9 byte&0xf0 =0x20 - version 2. >>9 beshort&0x0fff x \b%03x, >>15 byte 1 LZO1X-1, >>15 byte 2 LZO1X-1(15), >>15 byte 3 LZO1X-999, ## >>25 bedate >0 last modified: %s, >>17 byte =0x00 os: MS-DOS >>17 byte =0x01 os: Amiga >>17 byte =0x02 os: VMS >>17 byte =0x03 os: Unix >>17 byte =0x05 os: Atari >>17 byte =0x06 os: OS/2 >>17 byte =0x07 os: MacOS >>17 byte =0x0A os: Tops/20 >>17 byte =0x0B os: WinNT >>17 byte =0x0E os: Win32 # lzip 0 string LZIP lzip compressed data >4 byte x \b, version: %d # LZO 0 string \211LZO\000\015\012\032\012 LZO compressed data # 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) # http://www.7-zip.org or DOC/7zFormat.txt # 0 string 7z\274\257\047\034 7-zip archive data, >6 byte x version %d >7 byte x \b.%d # standard unix compress 0 beshort 0x1f9d compress'd data >2 byte&0x80 >0 block compressed >2 byte&0x1f !16 invalid >2 byte&0x1f x %d bits # http://tukaani.org/xz/xz-file-format.txt 0 string \xFD\x37\x7a\x58\x5a\x00 xz compressed data # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) # Edited by Chris Chittleborough , March 2002 # * Original filename is only at offset 10 if "extra field" absent # * Produce shorter output - notably, only report compression methods # other than 8 ("deflate", the only method defined in RFC 1952). 0 string \037\213\x08 gzip compressed data >3 byte &0x01 \b, ASCII >3 byte &0x02 \b, has CRC >3 byte &0x04 \b, extra field >3 byte&0xC =0x08 >>10 string x \b{file-name:%s} >>10 string x \b, was "%s" >3 byte &0x10 \b, has comment >9 byte =0x00 \b, from FAT filesystem (MS-DOS, OS/2, NT) >9 byte =0x01 \b, from Amiga >9 byte =0x02 \b, from VMS >9 byte =0x03 \b, from Unix >9 byte =0x04 \b, from VM/CMS >9 byte =0x05 \b, from Atari >9 byte =0x06 \b, from HPFS filesystem (OS/2, NT) >9 byte =0x07 \b, from MacOS >9 byte =0x08 \b, from Z-System >9 byte =0x09 \b, from CP/M >9 byte =0x0A \b, from TOPS/20 >9 byte =0x0B \b, from NTFS filesystem (NT) >9 byte =0x0C \b, from QDOS >9 byte =0x0D \b, from Acorn RISCOS >9 byte >0x0D \b, invalid source >9 byte <0 \b, invalid source >3 byte &0x20 \b, encrypted (invalid) # Dates before 1992 are invalid, unless of course you're DD-WRT in which # case you don't know how to set a date in your gzip files. Brilliant. >4 lelong =0 \b, NULL date: >4 lelong <0 \b, invalid date: >4 lelong >0 >>4 lelong <694224000 \b, invalid date: >>4 lelong =694224000 \b, invalid date: >>4 lelong >694224000 \b, last modified: >4 ledate x %s >8 byte 2 \b, max compression >8 byte 4 \b, max speed # Zlib signatures 0 beshort 0x789C zlib compressed data 0 beshort 0x78DA zlib compressed data 0 beshort 0x7801 zlib compressed data # Supplementary magic data for the file(1) command to support # rzip(1). The format is described in magic(5). # # Copyright (C) 2003 by Andrew Tridgell. You may do whatever you want with # this file. # 0 string RZIP rzip compressed data >4 byte x - version %d >5 byte x \b.%d >6 belong x (%d bytes) # ZIP compression (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) 0 string PK\003\004 Zip archive data, >4 byte 0x00 v0.0 >4 byte 0x09 at least v0.9 to extract, >4 byte 0x0a at least v1.0 to extract, >4 byte 0x0b at least v1.1 to extract, >0x161 string WINZIP WinZIP self-extracting, >4 byte 0x14 >>30 ubelong !0x6d696d65 at least v2.0 to extract, >18 lelong !0 >>18 lelong <0 invalid >>18 lelong x compressed size: %d, >22 lelong !0 >>22 lelong <0 invalid >>22 lelong x uncompressed size: %d,{extract-delay:end of zip archive} >30 string x {file-name:{raw-replace}}name: {raw-replace} >26 leshort x {raw-string-length:%d} >30 string x {raw-string:%s >61 string x \b%s >92 string x \b%s >123 string x \b%s >154 string x \b%s} # ZIP footer 0 string PK\x05\x06 End of Zip archive >20 leshort x {offset-adjust:22+%d} >20 leshort >0 >>20 leshort x \b, comment: {raw-replace} >>20 leshort x {raw-string-length:%d} >>22 string x {raw-string:%s} # New LZMA format signature 0 string \xFFLZMA\x00 LZMA compressed data (new), >6 byte&0x10 0 single-block stream >6 byte&0x10 0x10 multi-block stream # See lzma file for LZMA signatures # Type: OpenSSL certificates/key files # From: Nicolas Collignon 0 string -----BEGIN\x20CERTIFICATE----- PEM certificate 0 string -----BEGIN\x20CERTIFICATE\x20REQ PEM certificate request 0 string -----BEGIN\x20RSA\x20PRIVATE PEM RSA private key 0 string -----BEGIN\x20DSA\x20PRIVATE PEM DSA private key # Type: OpenSSH key files # From: Nicolas Collignon 0 string SSH\x20PRIVATE\x20KEY OpenSSH RSA1 private key, >28 string >\0 version "%s" 0 string ssh-dss\x20 OpenSSH DSA public key 0 string ssh-rsa\x20 OpenSSH RSA public key # Type: Certificates/key files in DER format # From: Gert Hulselmans 0 string \x30\x82 Private key in DER format (PKCS#8), >4 string !\x02\x01\x00 invalid, >>2 beshort x header length: 4, sequence length: %d 0 string \x30\x82 Certificate in DER format (x509 v3), >4 string !\x30\x82 invalid, >>2 beshort x header length: 4, sequence length: %d # GnuPG # The format is very similar to pgp 0 string \001gpg GPG key trust database >4 byte x version %d 0 beshort 0x9901 GPG key public ring # This magic is not particularly good, as the keyrings don't have true # magic. Nevertheless, it covers many keyrings. #------------------------------------------------------------------------------ # Mavroyanopoulos Nikos # mcrypt: file(1) magic for mcrypt 2.2.x; 0 string \0m\3 mcrypt 2.5 encrypted data, >4 byte 0 invalid >4 string >\0 algorithm: "%s", >>&1 leshort <1 invalid >>&1 leshort >0 keysize: %d bytes, >>>&0 byte 0 invalid >>>&0 string >\0 mode: "%s", 0 string \0m\2 mcrypt 2.2 encrypted data, >3 byte 0 algorithm: blowfish-448, >3 byte 1 algorithm: DES, >3 byte 2 algorithm: 3DES, >3 byte 3 algorithm: 3-WAY, >3 byte 4 algorithm: GOST, >3 byte 6 algorithm: SAFER-SK64, >3 byte 7 algorithm: SAFER-SK128, >3 byte 8 algorithm: CAST-128, >3 byte 9 algorithm: xTEA, >3 byte 10 algorithm: TWOFISH-128, >3 byte 11 algorithm: RC2, >3 byte 12 algorithm: TWOFISH-192, >3 byte 13 algorithm: TWOFISH-256, >3 byte 14 algorithm: blowfish-128, >3 byte 15 algorithm: blowfish-192, >3 byte 16 algorithm: blowfish-256, >3 byte 100 algorithm: RC6, >3 byte 101 algorithm: IDEA, >3 byte <0 invalid algorithm >3 byte >101 invalid algorithm, >3 byte >16 >>3 byte <100 invalid algorithm, >4 byte 0 mode: CBC, >4 byte 1 mode: ECB, >4 byte 2 mode: CFB, >4 byte 3 mode: OFB, >4 byte 4 mode: nOFB, >4 byte <0 invalid mode, >4 byte >4 invalid mode, >5 byte 0 keymode: 8bit >5 byte 1 keymode: 4bit >5 byte 2 keymode: SHA-1 hash >5 byte 3 keymode: MD5 hash >5 byte <0 invalid keymode >5 byte >3 invalid keymode #------------------------------------------------------------------------------ # pgp: file(1) magic for Pretty Good Privacy # #0 beshort 0x9900 PGP key public ring #0 beshort 0x9501 PGP key security ring #0 beshort 0x9500 PGP key security ring #0 beshort 0xa600 PGP encrypted data 0 string -----BEGIN\040PGP PGP armored data >15 string PUBLIC\040KEY\040BLOCK- public key block >15 string MESSAGE- message >15 string SIGNED\040MESSAGE- signed message >15 string PGP\040SIGNATURE- signature #------------------Standard file formats------------------------------------ #------------------------------------------------------------------------------ # elf: file(1) magic for ELF executables # # We have to check the byte order flag to see what byte order all the # other stuff in the header is in. # # What're the correct byte orders for the nCUBE and the Fujitsu VPP500? # # updated by Daniel Quinlan (quinlan@yggdrasil.com) 0 string \177ELF ELF >4 byte 0 invalid class >4 byte 1 32-bit # only for MIPS - in the future, the ABI field of e_flags should be used. >>18 leshort 8 >>>36 lelong &0x20 N32 >>18 leshort 10 >>>36 lelong &0x20 N32 >>18 beshort 8 >>>36 belong &0x20 N32 >>18 beshort 10 >>>36 belong &0x20 N32 >4 byte 2 64-bit >5 byte 0 invalid byte order >5 byte 1 LSB # The official e_machine number for MIPS is now #8, regardless of endianness. # The second number (#10) will be deprecated later. For now, we still # say something if #10 is encountered, but only gory details for #8. >>18 leshort 8 # only for 32-bit >>>4 byte 1 >>>>36 lelong&0xf0000000 0x00000000 MIPS-I >>>>36 lelong&0xf0000000 0x10000000 MIPS-II >>>>36 lelong&0xf0000000 0x20000000 MIPS-III >>>>36 lelong&0xf0000000 0x30000000 MIPS-IV >>>>36 lelong&0xf0000000 0x40000000 MIPS-V >>>>36 lelong&0xf0000000 0x60000000 MIPS32 >>>>36 lelong&0xf0000000 0x70000000 MIPS64 >>>>36 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 lelong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 lelong&0xf0000000 0x00000000 MIPS-I >>>>48 lelong&0xf0000000 0x10000000 MIPS-II >>>>48 lelong&0xf0000000 0x20000000 MIPS-III >>>>48 lelong&0xf0000000 0x30000000 MIPS-IV >>>>48 lelong&0xf0000000 0x40000000 MIPS-V >>>>48 lelong&0xf0000000 0x60000000 MIPS32 >>>>48 lelong&0xf0000000 0x70000000 MIPS64 >>>>48 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 lelong&0xf0000000 0x90000000 MIPS64 rel2 >>16 leshort 0 no file type, >>16 leshort 1 relocatable, >>16 leshort 2 executable, >>16 leshort 3 shared object, # Core handling from Peter Tobias # corrections by Christian 'Dr. Disk' Hechelmann >>16 leshort 4 core file # Core file detection is not reliable. #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, >>18 leshort 4 Motorola >>>36 lelong &0x01000000 68000 - invalid byte order, >>>36 lelong &0x00810000 CPU32 - invalid byte order, >>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, >>18 leshort 8 MIPS, >>18 leshort 9 Amdahl - invalid byte order, >>18 leshort 10 MIPS (deprecated), >>18 leshort 11 RS6000 - invalid byte order, >>18 leshort 15 PA-RISC - invalid byte order, >>>50 leshort 0x0214 2.0 >>>48 leshort &0x0008 (LP64), >>18 leshort 16 nCUBE, >>18 leshort 17 Fujitsu VPP500, >>18 leshort 18 SPARC32PLUS, >>18 leshort 20 PowerPC, >>18 leshort 22 IBM S/390, >>18 leshort 36 NEC V800, >>18 leshort 37 Fujitsu FR20, >>18 leshort 38 TRW RH-32, >>18 leshort 39 Motorola RCE, >>18 leshort 40 ARM, >>18 leshort 41 Alpha, >>18 leshort 0xa390 IBM S/390 (obsolete), >>18 leshort 42 Hitachi SH, >>18 leshort 43 SPARC V9 - invalid byte order, >>18 leshort 44 Siemens Tricore Embedded Processor, >>18 leshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 leshort 46 Hitachi H8/300, >>18 leshort 47 Hitachi H8/300H, >>18 leshort 48 Hitachi H8S, >>18 leshort 49 Hitachi H8/500, >>18 leshort 50 IA-64 (Intel 64 bit architecture) >>18 leshort 51 Stanford MIPS-X, >>18 leshort 52 Motorola Coldfire, >>18 leshort 53 Motorola M68HC12, >>18 leshort 62 AMD x86-64, >>18 leshort 75 Digital VAX, >>18 leshort 97 NatSemi 32k, >>18 leshort 0x9026 Alpha (unofficial), >>20 lelong 0 invalid version >>20 lelong 1 version 1 >>36 lelong 1 MathCoPro/FPU/MAU Required >5 byte 2 MSB # only for MIPS - see comment in little-endian section above. >>18 beshort 8 # only for 32-bit >>>4 byte 1 >>>>36 belong&0xf0000000 0x00000000 MIPS-I >>>>36 belong&0xf0000000 0x10000000 MIPS-II >>>>36 belong&0xf0000000 0x20000000 MIPS-III >>>>36 belong&0xf0000000 0x30000000 MIPS-IV >>>>36 belong&0xf0000000 0x40000000 MIPS-V >>>>36 belong&0xf0000000 0x60000000 MIPS32 >>>>36 belong&0xf0000000 0x70000000 MIPS64 >>>>36 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 belong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 belong&0xf0000000 0x00000000 MIPS-I >>>>48 belong&0xf0000000 0x10000000 MIPS-II >>>>48 belong&0xf0000000 0x20000000 MIPS-III >>>>48 belong&0xf0000000 0x30000000 MIPS-IV >>>>48 belong&0xf0000000 0x40000000 MIPS-V >>>>48 belong&0xf0000000 0x60000000 MIPS32 >>>>48 belong&0xf0000000 0x70000000 MIPS64 >>>>48 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 belong&0xf0000000 0x90000000 MIPS64 rel2 >>16 beshort 0 no file type, >>16 beshort 1 relocatable, >>16 beshort 2 executable, >>16 beshort 3 shared object, >>16 beshort 4 core file, #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) belong >0 (signal %d), >>16 beshort &0xff00 processor-specific, >>18 beshort 0 no machine, >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, >>18 beshort 4 Motorola >>>36 belong &0x01000000 68000, >>>36 belong &0x00810000 CPU32, >>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, >>18 beshort 8 MIPS, >>18 beshort 9 Amdahl, >>18 beshort 10 MIPS (deprecated), >>18 beshort 11 RS6000, >>18 beshort 15 PA-RISC >>>50 beshort 0x0214 2.0 >>>48 beshort &0x0008 (LP64) >>18 beshort 16 nCUBE, >>18 beshort 17 Fujitsu VPP500, >>18 beshort 18 SPARC32PLUS, >>>36 belong&0xffff00 &0x000100 V8+ Required, >>>36 belong&0xffff00 &0x000200 Sun UltraSPARC1 Extensions Required, >>>36 belong&0xffff00 &0x000400 HaL R1 Extensions Required, >>>36 belong&0xffff00 &0x000800 Sun UltraSPARC3 Extensions Required, >>18 beshort 20 PowerPC or cisco 4500, >>18 beshort 21 cisco 7500, >>18 beshort 22 IBM S/390, >>18 beshort 24 cisco SVIP, >>18 beshort 25 cisco 7200, >>18 beshort 36 NEC V800 or cisco 12000, >>18 beshort 37 Fujitsu FR20, >>18 beshort 38 TRW RH-32, >>18 beshort 39 Motorola RCE, >>18 beshort 40 ARM, >>18 beshort 41 Alpha, >>18 beshort 42 Hitachi SH, >>18 beshort 43 SPARC V9, >>18 beshort 44 Siemens Tricore Embedded Processor, >>18 beshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 beshort 46 Hitachi H8/300, >>18 beshort 47 Hitachi H8/300H, >>18 beshort 48 Hitachi H8S, >>18 beshort 49 Hitachi H8/500, >>18 beshort 50 Intel Merced Processor, >>18 beshort 51 Stanford MIPS-X, >>18 beshort 52 Motorola Coldfire, >>18 beshort 53 Motorola M68HC12, >>18 beshort 73 Cray NV1, >>18 beshort 75 Digital VAX, >>18 beshort 97 NatSemi 32k, >>18 beshort 0x9026 Alpha (unofficial), >>18 beshort 0xa390 IBM S/390 (obsolete), >>18 beshort 0xde3d Ubicom32, >>20 belong 0 invalid version >>20 belong 1 version 1 >>36 belong 1 MathCoPro/FPU/MAU Required # Up to now only 0, 1 and 2 are defined; I've seen a file with 0x83, it seemed # like proper ELF, but extracting the string had bad results. >4 byte <0x80 >>8 string >\0 ("%s") >8 string \0 >>7 byte 0 (SYSV) >>7 byte 1 (HP-UX) >>7 byte 2 (NetBSD) >>7 byte 3 (GNU/Linux) >>7 byte 4 (GNU/Hurd) >>7 byte 5 (86Open) >>7 byte 6 (Solaris) >>7 byte 7 (Monterey) >>7 byte 8 (IRIX) >>7 byte 9 (FreeBSD) >>7 byte 10 (Tru64) >>7 byte 11 (Novell Modesto) >>7 byte 12 (OpenBSD) >>7 byte 97 (ARM) >>7 byte 255 (embedded) # XXX - according to Microsoft's spec, at an offset of 0x3c in a # PE-format executable is the offset in the file of the PE header; # unfortunately, that's a little-endian offset, and there's no way # to specify an indirect offset with a specified byte order. # So, for now, we assume the standard MS-DOS stub, which puts the # PE header at 0x80 = 128. # # Required OS version and subsystem version were 4.0 on some NT 3.51 # executables built with Visual C++ 4.0, so it's not clear that # they're interesting. The user version was 0.0, but there's # probably some linker directive to set it. The linker version was # 3.0, except for one ".exe" which had it as 4.20 (same damn linker!). # # many of the compressed formats were extraced from IDARC 1.23 source code # 0 string MZ Microsoft >0x18 leshort <0x40 MS-DOS executable >0 string MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b, PE for MS Windows >>&18 leshort&0x2000 >0 (DLL) >>&88 leshort 0 (unknown subsystem) >>&88 leshort 1 (native) >>&88 leshort 2 (GUI) >>&88 leshort 3 (console) >>&88 leshort 7 (POSIX) >>&0 leshort 0x0 unknown processor >>&0 leshort 0x14c Intel 80386 >>&0 leshort 0x166 MIPS R4000 >>&0 leshort 0x184 Alpha >>&0 leshort 0x268 Motorola 68000 >>&0 leshort 0x1f0 PowerPC >>&0 leshort 0x290 PA-RISC >>&18 leshort&0x0100 >0 32-bit >>&18 leshort&0x1000 >0 system file >>&228 lelong >0 \b, Mono/.Net assembly >>&0xf4 search/0x140 \x0\x40\x1\x0 >>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive >30 string Copyright\x201989-1990\x20PKWARE\x20Inc. Self-extracting PKZIP archive # Is next line correct? One might expect "Corp." not "Copr." If it is right, add a note to that effect. >30 string PKLITE\x20Copr. Self-extracting PKZIP archive >0x18 leshort >0x3f >>(0x3c.l) string PE\0\0 PE >>>(0x3c.l+25) byte 1 \b32 executable >>>(0x3c.l+25) byte 2 \b32+ executable # hooray, there's a DOS extender using the PE format, with a valid PE # executable inside (which just prints a message and exits if run in win) >>>(0x3c.l+92) leshort <10 >>>>(8.s*16) string 32STUB for MS-DOS, 32rtm DOS extender >>>>(8.s*16) string !32STUB for MS Windows >>>>>(0x3c.l+22) leshort&0x2000 >0 (DLL) >>>>>(0x3c.l+92) leshort 0 (unknown subsystem) >>>>>(0x3c.l+92) leshort 1 (native) >>>>>(0x3c.l+92) leshort 2 (GUI) >>>>>(0x3c.l+92) leshort 3 (console) >>>>>(0x3c.l+92) leshort 7 (POSIX) >>>(0x3c.l+92) leshort 10 (EFI application) >>>(0x3c.l+92) leshort 11 (EFI boot service driver) >>>(0x3c.l+92) leshort 12 (EFI runtime driver) >>>(0x3c.l+92) leshort 13 (XBOX) >>>(0x3c.l+4) leshort 0x0 unknown processor >>>(0x3c.l+4) leshort 0x14c Intel 80386 >>>(0x3c.l+4) leshort 0x166 MIPS R4000 >>>(0x3c.l+4) leshort 0x184 Alpha >>>(0x3c.l+4) leshort 0x268 Motorola 68000 >>>(0x3c.l+4) leshort 0x1f0 PowerPC >>>(0x3c.l+4) leshort 0x290 PA-RISC >>>(0x3c.l+4) leshort 0x200 Intel Itanium >>>(0x3c.l+22) leshort&0x0100 >0 32-bit >>>(0x3c.l+22) leshort&0x1000 >0 system file >>>(0x3c.l+232) lelong >0 Mono/.Net assembly >>>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed >>>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed >>>>(0x3c.l+0xf8) search/0x140 UPX2 >>>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>(0x3c.l+0xf8) search/0x140 .idata >>>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive >>>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .rsrc >>>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive >>>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive >>>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive >>>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .data >>>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed >>>>>(0x3c.l+0xf7) byte x >>>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .reloc >>>>>(&0xe.l+(-4)) search/0x180 PK\3\4 \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive >>>>0x30 string Inno \b, InnoSetup self-extracting archive >>(0x3c.l) string !PE\0\0 MS-DOS executable >>(0x3c.l) string NE \b, NE >>>(0x3c.l+0x36) byte 0 (unknown OS) >>>(0x3c.l+0x36) byte 1 for OS/2 1.x >>>(0x3c.l+0x36) byte 2 for MS Windows 3.x >>>(0x3c.l+0x36) byte 3 for MS-DOS >>>(0x3c.l+0x36) byte >3 (unknown OS) >>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender >>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) >>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) >>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive >>>(0x3c.l+0x70) search/0x80 WinZip(R)\x20Self-Extractor \b, ZIP self-extracting archive (WinZip) >>(0x3c.l) string LX\0\0 \b, LX >>>(0x3c.l+0x0a) leshort <1 (unknown OS) >>>(0x3c.l+0x0a) leshort 1 for OS/2 >>>(0x3c.l+0x0a) leshort 2 for MS Windows >>>(0x3c.l+0x0a) leshort 3 for DOS >>>(0x3c.l+0x0a) leshort >3 (unknown OS) >>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) >>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) >>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) >>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) >>>(0x3c.l+0x08) leshort 1 i80286 >>>(0x3c.l+0x08) leshort 2 i80386 >>>(0x3c.l+0x08) leshort 3 i80486 >>>(8.s*16) string emx \b, emx >>>>&1 string x "%s" >>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive #------------------------------------------------------------------------------ # bFLT: file(1) magic for BFLT uclinux binary files # # From Philippe De Muyter # # Additional fields added by Craig Heffner # 0 string bFLT BFLT executable >4 belong x version %ld, >4 belong 4 >8 belong x code offset: 0x%.8X, >12 belong x data segment starts at: 0x%.8X, >16 belong x bss segment starts at: 0x%.8X, >20 belong x bss segment ends at: 0x%.8X, >24 belong x stack size: %d bytes, >28 belong x relocation records start at: 0x%.8X, >32 belong x number of reolcation records: %d, >>36 belong&0x1 0x1 ram >>36 belong&0x2 0x2 gotpic >>36 belong&0x4 0x4 gzip >>36 belong&0x8 0x8 gzdata #----------------------------------------------------------------- # MIPS COFF file formats # 0 beshort 0x0160 MIPSEB ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0162 MIPSEL-BE ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6001 MIPSEB-LE ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6201 MIPSEL ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 2 additions # 0 beshort 0x0163 MIPSEB MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0166 MIPSEL-BE MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x6301 MIPSEB-LE MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x6601 MIPSEL MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 3 additions # 0 beshort 0x0140 MIPSEB MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0142 MIPSEL-BE MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x4001 MIPSEB-LE MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x4201 MIPSEL MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x180 MIPSEB Ucode 0 beshort 0x182 MIPSEL-BE Ucode # Windows CE package files 0 string MSCE\0\0\0\0 Microsoft WinCE installer >20 lelong 0 \b, architecture-independent >20 lelong 103 \b, Hitachi SH3 >20 lelong 104 \b, Hitachi SH4 >20 lelong 0xA11 \b, StrongARM >20 lelong 4000 \b, MIPS R4000 >20 lelong 10003 \b, Hitachi SH3 >20 lelong 10004 \b, Hitachi SH3E >20 lelong 10005 \b, Hitachi SH4 >20 lelong 70001 \b, ARM 7TDMI >52 leshort 1 \b, 1 file >52 leshort >1 \b, %u files >56 leshort 1 \b, 1 registry entry >56 leshort >1 \b, %u registry entries #------------------------------------------------------------------------------ # Microsoft Xbox executables .xbe (Esa Hyytiä ) 0 string XBEH XBE, Microsoft Xbox executable # probabilistic checks whether signed or not >0x0004 ulelong =0x0 >>&2 ulelong =0x0 >>>&2 ulelong =0x0 \b, not signed >0x0004 ulelong >0 >>&2 ulelong >0 >>>&2 ulelong >0 \b, signed # expect base address of 0x10000 >0x0104 ulelong =0x10000 >>(0x0118-0x0FF60) ulelong&0x80000007 0x80000007 \b, all regions >>(0x0118-0x0FF60) ulelong&0x80000007 !0x80000007 >>>(0x0118-0x0FF60) ulelong >0 (regions: >>>>(0x0118-0x0FF60) ulelong &0x00000001 NA >>>>(0x0118-0x0FF60) ulelong &0x00000002 Japan >>>>(0x0118-0x0FF60) ulelong &0x00000004 Rest_of_World >>>>(0x0118-0x0FF60) ulelong &0x80000000 Manufacturer >>>(0x0118-0x0FF60) ulelong >0 \b) #------------------------------------------------------------------------------ # motorola: file(1) magic for Motorola 68K and 88K binaries # # 68K # 0 beshort 0x0208 mc68k COFF >18 beshort ^00000020 object >18 beshort &00000020 executable >12 belong >0 not stripped >168 string .lowmem Apple toolbox >20 beshort 0407 (impure) >20 beshort 0410 (pure) >20 beshort 0413 (demand paged) >20 beshort 0421 (standalone) 0 beshort 0x0209 mc68k executable (shared) >12 belong >0 not stripped 0 beshort 0x020A mc68k executable (shared demand paged) >12 belong >0 not stripped # # Motorola/UniSoft 68K Binary Compatibility Standard (BCS) # 0 beshort 0x022A 68K BCS executable # # 88K # # Motorola/88Open BCS # 0 beshort 0x022B 88K BCS executable #------------------------------------------------------------------------------ # Sony Playstation executables (Adam Sjoegren ) : 0 string PS-X\x20EXE Sony Playstation executable # Area: >113 string x ("%s") #------------------------------------------------------------------------------ # cisco: file(1) magic for cisco Systems routers # # Most cisco file-formats are covered by the generic elf code # # Microcode files are non-ELF, 0x8501 conflicts with NetBSD/alpha. 0 beshort 0x8501 cisco IOS >0 belong&0xffffff00 0x85011400 microcode >0 belong&0xffffff00 0x8501cb00 experimental microcode >7 string >\0 for "%s" # EST flat binary format (which isn't, but anyway) # From: Mark Brown 0 string ESTFBINR EST flat binary # These are not the binaries themselves, but string references to them # are a strong indication that they exist elsewhere... #0 string /bin/busybox Busybox string reference: "%s"{one-of-many} #0 string /bin/sh Shell string reference: "%s"{one-of-many} #--------------------File Systems--------------------- # Minix filesystems - Juan Cespedes 0x410 leshort 0x137f Minix filesystem >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 leshort 0x138f Minix filesystem, 30 char names 0x410 leshort 0x2468 Minix filesystem, version 2 0x410 leshort 0x2478 Minix filesystem, version 2, 30 char names 0x410 leshort 0x4d5a Minix filesystem, version 3 0x410 leshort 0x4d6a Minix filesystem, version 3, 30 char names 0x410 beshort 0x137f Minix filesystem (big endian) >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 beshort 0x138f Minix filesystem (big endian), 30 char names 0x410 beshort 0x2468 Minix filesystem (big endian), version 2 0x410 beshort 0x2478 Minix filesystem (big endian), version 2, 30 char names 0x410 beshort 0x4d5a Minix filesystem (big endian), version 3 0x410 beshort 0x4d6a Minix filesystem (big endian), version 3, 30 char names # YAFFS 0 string \x03\x00\x00\x00\x01\x00\x00\x00\xFF\xFF YAFFS filesystem # EFS2 file system - jojo@utulsa.edu 0 lelong 0x53000000 EFS2 Qualcomm filesystem super block, little endian, >8 string !EFSSuper invalid, >4 leshort &1 NAND >4 leshort ^1 NOR >4 leshort x version 0x%x, >24 lelong x %d blocks, >16 lelong x 0x%x pages per block, >20 lelong x 0x%x bytes per page 0 belong 0x53000000 EFS2 Qualcomm filesystem super block, big endian, >8 string !SSFErepu invalid, >4 beshort &1 NAND >4 beshort ^1 NOR >4 beshort x version 0x%x, >24 belong x %d blocks, >16 belong x 0x%x pages per block, >20 belong x 0x%x bytes per page # TROC file system 0 string TROC TROC filesystem, >4 lelong x %d file entries # PFS file system 0 string PFS/ PFS filesystem, >4 string x version "%s", >14 leshort x %d files # MPFS file system 0 string MPFS MPFS (Microchip) filesystem, >4 byte x version %d. >5 byte x \b%d, >6 leshort x %d file entries # cramfs filesystem - russell@coker.com.au 0 lelong 0x28cd3d45 CramFS filesystem, little endian >4 lelong <0 invalid >4 lelong x size %lu >8 lelong &1 version #2 >8 lelong &2 sorted_dirs >8 lelong &4 hole_support >32 lelong x CRC 0x%x, >36 lelong x edition %lu, >40 lelong <0 invalid >40 lelong x %lu blocks, >44 lelong <0 invalid >44 lelong x %lu files >4 lelong x {jump-to-offset:%lu} >4 lelong x {file-size:%lu} 0 belong 0x28cd3d45 CramFS filesystem, big endian >4 belong <0 invalid >4 belong x size %lu >8 belong &1 version #2 >8 belong &2 sorted_dirs >8 belong &4 hole_support >32 belong x CRC 0x%x, >36 belong x edition %lu, >40 belong <0 invalid >40 belong x %lu blocks, >44 belong <0 invalid >44 belong x %lu files >4 belong x {jump-to-offset:%lu} >4 belong x {file-size:%lu} # JFFS2 file system # If used with binwalk's smart signature feature (on by default, -S to disable) # this signature can potentially lead to missing some JFFS2 file systems if there # are multiple JFFS2 file systems in a target file and there are no other identified # files in between the JFFS2 file systems. This is an unlikely scenario however, and # the below signatures are much improved in terms of readability and accuracy in the # vast majority of real world scenarios. 0 leshort 0x1985 JFFS2 filesystem, little endian{filter-include} >2 leshort !0xE001 >>2 leshort !0xE002 >>>2 leshort !0x2003 >>>>2 leshort !0x2004 >>>>>2 leshort !0x2006 >>>>>>2 leshort !0xE008 >>>>>>>2 leshort !0xE009 \b, invalid >(4.l) leshort !0x1985 >>(4.l+1) leshort !0x1985 >>>(4.l+2) leshort !0x1985 >>>>(4.l+3) leshort !0x1985 >>>>>(4.l) leshort !0xFFFF >>>>>>(4.l+1) leshort !0xFFFF >>>>>>>(4.l+2) leshort !0xFFFF >>>>>>>>(4.l+3) leshort !0xFFFF \b, invalid >4 lelong x {one-of-many}{jump-to-offset:%d} 0 beshort 0x1985 JFFS2 filesystem, big endian{filter-include} >2 beshort !0xE001 >>2 beshort !0xE002 >>>2 beshort !0x2003 >>>>2 beshort !0x2004 >>>>>2 beshort !0x2006 >>>>>>2 beshort !0xE008 >>>>>>>2 beshort !0xE009 \b, invalid >(4.L) beshort !0x1985 >>(4.L+1) beshort !0x1985 >>>(4.L+2) beshort !0x1985 >>>>(4.L+3) beshort !0x1985 >>>>>(4.L) beshort !0xFFFF >>>>>>(4.L+1) beshort !0xFFFF >>>>>>>(4.L+2) beshort !0xFFFF >>>>>>>>(4.L+3) beshort !0xFFFF \b, invalid >4 belong x {one-of-many}{jump-to-offset:%d} # Squashfs, big endian 0 string sqsh Squashfs filesystem, big endian, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort 3 >>63 bequad x size: %lld bytes, >28 beshort >3 >>40 bequad x size: %lld bytes, >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs, little endian 0 string hsqs Squashfs filesystem, little endian, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Squashfs with LZMA compression 0 string sqlz Squashfs filesystem, big endian, lzma compression, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs 3.3 LZMA signature 0 string qshs Squashfs filesystem, big endian, lzma signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string tqsh Squashfs filesystem, big endian, DD-WRT signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string hsqt Squashfs filesystem, little endian, DD-WRT signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Non-standard Squashfs signature found on some D-Link routers 0 string shsq Squashfs filesystem, little endian, non-standard signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # ext2/ext3 filesystems - Andreas Dilger # ext4 filesystem - Eric Sandeen # volume label and UUID Russell Coker # http://etbe.coker.com.au/2008/07/08/label-vs-uuid-vs-device/ 0 leshort 0xEF53 Linux EXT filesystem,{filter-include}{offset-adjust:-0x438} >2 leshort >4 invalid state >2 leshort 3 invalid state >2 leshort <0 invalid state >4 leshort >3 invalid error behavior >4 leshort <0 invalid error behavior >4 lelong >1 invalid major revision >4 lelong <0 invalid major revision >4 lelong x rev %d >6 leshort x \b.%d # No journal? ext2 >36 lelong ^0x0000004 ext2 filesystem data >>2 leshort ^0x0000001 (mounted or unclean) # Has a journal? ext3 or ext4 >36 lelong &0x0000004 # and small INCOMPAT? >>40 lelong <0x0000040 # and small RO_COMPAT? >>>44 lelong <0x0000008 ext3 filesystem data # else large RO_COMPAT? >>>44 lelong >0x0000007 ext4 filesystem data # else large INCOMPAT? >>40 lelong >0x000003f ext4 filesystem data >48 belong x \b, UUID=%08x >52 beshort x \b-%04x >54 beshort x \b-%04x >56 beshort x \b-%04x >58 belong x \b-%08x >60 beshort x \b%04x >64 string >0 \b, volume name "%s" #romfs filesystems - Juan Cespedes 0 string -rom1fs-\0 romfs filesystem, version 1 >8 belong >10000000 invalid >8 belong x size: %d bytes, >16 string x {file-name:%s} >16 string x named "%s" >8 belong x {file-size:%d} >8 belong x {jump-to-offset:%d} # Wind River MemFS file system, found in some VxWorks devices 0 string owowowowowowowowowowowowowowow Wind River management filesystem, >30 string !ow invalid, >32 belong 1 compressed, >32 belong 2 plain text, >36 belong x %d files # netboot image - Juan Cespedes 0 lelong 0x1b031336L Netboot image, >4 lelong&0xFFFFFF00 0 >>4 lelong&0x100 0x000 mode 2 >>4 lelong&0x100 0x100 mode 3 >4 lelong&0xFFFFFF00 !0 unknown mode (invalid) #--------------------------Firmware Formats--------------------------- # uImage file # From: Craig Heffner, U-Boot image.h header definitions file 0 belong 0x27051956 uImage header, header size: 64 bytes, >4 belong x header CRC: 0x%X, >8 bedate x created: %s, >12 belong x image size: %d bytes, >16 belong x Data Address: 0x%X, >20 belong x Entry Point: 0x%X, >24 belong x data CRC: 0x%X, #>28 byte x OS type: %d, >28 byte 0 OS: invalid OS, >28 byte 1 OS: OpenBSD, >28 byte 2 OS: NetBSD, >28 byte 3 OS: FreeBSD, >28 byte 4 OS: 4.4BSD, >28 byte 5 OS: Linux, >28 byte 6 OS: SVR4, >28 byte 7 OS: Esix, >28 byte 8 OS: Solaris, >28 byte 9 OS: Irix, >28 byte 10 OS: SCO, >28 byte 11 OS: Dell, >28 byte 12 OS: NCR, >28 byte 13 OS: LynxOS, >28 byte 14 OS: VxWorks, >28 byte 15 OS: pSOS, >28 byte 16 OS: QNX, >28 byte 17 OS: Firmware, >28 byte 18 OS: RTEMS, >28 byte 19 OS: ARTOS, >28 byte 20 OS: Unity OS, #>29 byte x CPU arch: %d, >29 byte 0 CPU: invalid OS, >29 byte 1 CPU: Alpha, >29 byte 2 CPU: ARM, >29 byte 3 CPU: Intel x86, >29 byte 4 CPU: IA64, >29 byte 5 CPU: MIPS, >29 byte 6 CPU: MIPS 64 bit, >29 byte 7 CPU: PowerPC, >29 byte 8 CPU: IBM S390, >29 byte 9 CPU: SuperH, >29 byte 10 CPU: Sparc, >29 byte 11 CPU: Sparc 64 bit, >29 byte 12 CPU: M68K, >29 byte 13 CPU: Nios-32, >29 byte 14 CPU: MicroBlaze, >29 byte 15 CPU: Nios-II, >29 byte 16 CPU: Blackfin, >29 byte 17 CPU: AVR, >29 byte 18 CPU: STMicroelectronics ST200, #>30 byte x image type: %d, >30 byte 0 image type: invalid Image, >30 byte 1 image type: Standalone Program, >30 byte 2 image type: OS Kernel Image, >30 byte 3 image type: RAMDisk Image, >30 byte 4 image type: Multi-File Image, >30 byte 5 image type: Firmware Image, >30 byte 6 image type: Script file, >30 byte 7 image type: Filesystem Image, >30 byte 8 image type: Binary Flat Device Tree Blob #>31 byte x compression type: %d, >31 byte 0 compression type: none, >31 byte 1 compression type: gzip, >31 byte 2 compression type: bzip2, >31 byte 3 compression type: lzma, >32 string x image name: "%s" #IMG0 header, found in VxWorks-based Mercury router firmware 0 string IMG0 IMG0 (VxWorks) header, >4 belong x size: %d #Mediatek bootloader signature #From xp-dev.com 0 string BOOTLOADER! Mediatek bootloader #CSYS header formats 0 string CSYS\x00 CSYS header, little endian, >8 lelong x size: %d 0 string CSYS\x80 CSYS header, big endian, >8 belong x size: %d # wrgg firmware image 0 string wrgg02 WRGG firmware header, >6 string x name: "%s", >48 string x root device: "%s" # trx image file 0 string HDR0 TRX firmware header, little endian, header size: 28 bytes, >4 lelong x image size: %d bytes, >8 lelong x CRC32: 0x%X >12 lelong x flags/version: 0x%X 0 string 0RDH TRX firmware header, big endian, header size: 28 bytes, >4 belong x image size: %d bytes, >8 belong x CRC32: 0x%X >12 belong x flags/version: 0x%X # Ubicom firmware image 0 belong 0xFA320080 Ubicom firmware header, >12 belong x checksum: 0x%X, >24 belong x image size: %d # The ROME bootloader is used by several RealTek-based products. # Unfortunately, the magic bytes are specific to each product, so # separate signatures must be created for each one. # Netgear KWGR614 ROME image 0 string G614 Realtek firmware header (ROME bootloader), >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # Linksys WRT54GX ROME image 0 belong 0x59a0e842 Realtek firmware header (ROME bootloader) >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # PackImg tag, somtimes used as a delimiter between the kernel and rootfs in firmware images. 0 string --PaCkImGs-- PackImg section delimiter tag, >16 lelong x little endian size: %d bytes; >16 belong x big endian size: %d bytes #------------------------------------------------------------------------------ # Broadcom header format # 0 string BCRM Broadcom header, >4 lelong x number of sections: %d, >>8 lelong 18 first section type: flash >>8 lelong 19 first section type: disk >>8 lelong 21 first section type: tag # Berkeley Lab Checkpoint Restart (BLCR) checkpoint context files # http://ftg.lbl.gov/checkpoint 0 string Ck0\0\0R\0\0\0 BLCR >16 lelong 1 x86 >16 lelong 3 alpha >16 lelong 5 x86-64 >16 lelong 7 ARM >8 lelong x context data (little endian, version %d) 0 string \0\0\0C\0\0\0R BLCR >16 belong 2 SPARC >16 belong 4 ppc >16 belong 6 ppc64 >16 belong 7 ARMEB >16 belong 8 SPARC64 >8 belong x context data (big endian, version %d) # Aculab VoIP firmware # From: Mark Brown 0 string VoIP\x20Startup\x20and Aculab VoIP firmware >35 string x format "%s" #------------------------------------------------------------------------------ # HP LaserJet 1000 series downloadable firmware file 0 string \xbe\xefABCDEFGH HP LaserJet 1000 series downloadable firmware # From Albert Cahalan # really le32 operation,destination,payloadsize (but quite predictable) # 01 00 00 00 00 00 00 c0 00 02 00 00 0 string \1\0\0\0\0\0\0\300\0\2\0\0 Marvell Libertas firmware #--------------------------------------------------------------------------- # The following entries have been tested by Duncan Laurie (a # lead Sun/Cobalt developer) who agrees that they are good and worthy of # inclusion. # Boot ROM images for Sun/Cobalt Linux server appliances 0 string Cobalt\x20Networks\x20Inc.\nFirmware\x20v Paged COBALT boot rom >38 string x V%.4s # New format for Sun/Cobalt boot ROMs is annoying, it stores the version code # at the very end where file(1) can't get it. 0 string CRfs COBALT boot rom data (Flat boot rom or file system) # # Motorola S-Records, from Gerd Truschinski 0 string S0 Motorola S-Record; binary data in text format # -------------------------------- # Microsoft Xbox data file formats 0 string XIP0 XIP, Microsoft Xbox data 0 string XTF0 XTF, Microsoft Xbox data #Windows CE 0 string CECE Windows CE RTOS{offset-adjust:-64} # -------------------------------- # ZynOS ROM header format # From openwrt zynos.h. 0 string SIG ZynOS header, header size: 48 bytes,{offset-adjust:-6} #>0 belong x load address 0x%X, >3 byte <0x7F rom image type: >>3 byte <1 invalid, >>3 byte >7 invalid, >>3 byte 1 ROMIMG, >>3 byte 2 ROMBOOT, >>3 byte 3 BOOTEXT, >>3 byte 4 ROMBIN, >>3 byte 5 ROMDIR, >>3 byte 6 6, >>3 byte 7 ROMMAP, >3 byte >0x7F ram image type: >>3 byte >0x82 invalid, >>3 byte 0x80 RAM, >>3 byte 0x81 RAMCODE, >>3 byte 0x82 RAMBOOT, >4 belong >0x40000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x uncompressed size: %d, >8 belong >0x40000000 invalid >8 belong <0 invalid >8 belong 0 invalid >8 belong x compressed size: %d, >14 beshort x uncompressed checksum: 0x%X, >16 beshort x compressed checksum: 0x%X, >12 byte x flags: 0x%X, >12 byte &0x40 uncompressed checksum is valid, >12 byte &0x80 the binary is compressed, >>12 byte &0x20 compressed checksum is valid, >35 belong x memory map table address: 0x%X # Firmware header used by some VxWorks-based Cisco products 0 string CI032.00 Cisco VxWorks firmware header, >8 lelong >1024 invalid >8 lelong <0 invalid >8 lelong x header size: %d bytes, >32 lelong >1024 invalid >32 lelong <0 invalid >32 lelong x number of files: %d, >48 lelong <0 invalid >48 lelong x image size: %d, >64 string x firmware version: "%s" # Firmware header used by some TV's 0 string FNIB ZBOOT firmware header, header size: 32 bytes, >8 lelong x load address: 0x%.8X, >12 lelong x start address: 0x%.8X, >16 lelong x checksum: 0x%.8X, >20 lelong x version: 0x%.8X, >24 lelong <1 invalid >24 lelong x image size: %d bytes # Firmware header used by several D-Link routers (and probably others) 0 string \x5e\xa3\xa4\x17 DLOB firmware header, >(7.b+12) string !\x5e\xa3\xa4\x17 invalid, #>>12 string x %s, >(7.b+40) string x boot partition: "%s" # TP-Link firmware header structure; thanks to Jonathan McGowan for reversing and documenting this format 0 string TP-LINK\x20Technologies TP-Link firmware header,{offset-adjust:-4} #>-4 lelong x header version: %d, >0x94 beshort x firmware version: %d. >0x96 beshort x \b%d. >0x98 beshort x \b%d, >0x18 string x image version: "%s", #>0x74 belong x image size: %d bytes, >0x3C belong x product ID: 0x%X, >0x40 belong x product version: %d, >0x70 belong x kernel load address: 0x%X, >0x74 belong x kernel entry point: 0x%X, >0x7C belong x kernel offset: %d, >0x80 belong x kernel length: %d, >0x84 belong x rootfs offset: %d, >0x88 belong x rootfs length: %d, >0x8C belong x bootloader offset: %d, >0x90 belong x bootloader length: %d # Tag Image File Format, from Daniel Quinlan (quinlan@yggdrasil.com) # The second word of TIFF files is the TIFF version number, 42, which has # never changed. The TIFF specification recommends testing for it. 0 string MM\x00\x2a TIFF image data, big-endian 0 string II\x2a\x00 TIFF image data, little-endian # PNG [Portable Network Graphics, or "PNG's Not GIF"] images # (Greg Roelofs, newt@uchicago.edu) # (Albert Cahalan, acahalan@cs.uml.edu) # # 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ... # 0 string \x89PNG\x0d\x0a\x1a\x0a PNG image >16 belong x \b, %ld x >20 belong x %ld, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, #>26 byte 0 deflate/32K, >28 byte 0 non-interlaced >28 byte 1 interlaced # GIF 0 string GIF8 GIF image data >4 string 7a \b, version 8"%s", >4 string 9a \b, version 8"%s", >6 leshort >0 %hd x >8 leshort >0 %hd #>10 byte &0x80 color mapped, #>10 byte&0x07 =0x00 2 colors #>10 byte&0x07 =0x01 4 colors #>10 byte&0x07 =0x02 8 colors #>10 byte&0x07 =0x03 16 colors #>10 byte&0x07 =0x04 32 colors #>10 byte&0x07 =0x05 64 colors #>10 byte&0x07 =0x06 128 colors #>10 byte&0x07 =0x07 256 colors # PC bitmaps (OS/2, Windows BMP files) (Greg Roelofs, newt@uchicago.edu) 0 string BM >14 leshort 12 PC bitmap, OS/2 1.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 64 PC bitmap, OS/2 2.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 40 PC bitmap, Windows 3.x format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d >14 leshort 128 PC bitmap, Windows NT/2000 format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d #------------------------------------------------------------------------------ # JPEG images # SunOS 5.5.1 had # # 0 string \377\330\377\340 JPEG file # 0 string \377\330\377\356 JPG file # # both of which turn into "JPEG image data" here. # 0 beshort 0xffd8 JPEG image data >6 string JFIF \b, JFIF standard # The following added by Erik Rossen 1999-09-06 # in a vain attempt to add image size reporting for JFIF. Note that these # tests are not fool-proof since some perfectly valid JPEGs are currently # impossible to specify in magic(4) format. # First, a little JFIF version info: >>11 byte x \b %d. >>12 byte x \b%02d # Next, the resolution or aspect ratio of the image: #>>13 byte 0 \b, aspect ratio #>>13 byte 1 \b, resolution (DPI) #>>13 byte 2 \b, resolution (DPCM) #>>4 beshort x \b, segment length %d # Next, show thumbnail info, if it exists: >>18 byte !0 \b, thumbnail %dx >>>19 byte x \b%d # EXIF moved down here to avoid reporting a bogus version number, # and EXIF version number printing added. # - Patrik R=E5dman >6 string Exif \b, EXIF standard # Look for EXIF IFD offset in IFD 0, and then look for EXIF version tag in EXIF IFD. # All possible combinations of entries have to be enumerated, since no looping # is possible. And both endians are possible... # The combinations included below are from real-world JPEGs. # Little-endian >>12 string II # IFD 0 Entry #5: >>>70 leshort 0x8769 # EXIF IFD Entry #1: >>>>(78.l+14) leshort 0x9000 >>>>>(78.l+23) byte x %c >>>>>(78.l+24) byte x \b.%c >>>>>(78.l+25) byte !0x30 \b%c # IFD 0 Entry #9: >>>118 leshort 0x8769 # EXIF IFD Entry #3: >>>>(126.l+38) leshort 0x9000 >>>>>(126.l+47) byte x %c >>>>>(126.l+48) byte x \b.%c >>>>>(126.l+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 leshort 0x8769 # EXIF IFD Entry #3: >>>>(138.l+38) leshort 0x9000 >>>>>(138.l+47) byte x %c >>>>>(138.l+48) byte x \b.%c >>>>>(138.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(138.l+50) leshort 0x9000 >>>>>(138.l+59) byte x %c >>>>>(138.l+60) byte x \b.%c >>>>>(138.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.l+62) leshort 0x9000 >>>>>(138.l+71) byte x %c >>>>>(138.l+72) byte x \b.%c >>>>>(138.l+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 leshort 0x8769 # EXIF IFD Entry #3: >>>>(150.l+38) leshort 0x9000 >>>>>(150.l+47) byte x %c >>>>>(150.l+48) byte x \b.%c >>>>>(150.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(150.l+50) leshort 0x9000 >>>>>(150.l+59) byte x %c >>>>>(150.l+60) byte x \b.%c >>>>>(150.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(150.l+62) leshort 0x9000 >>>>>(150.l+71) byte x %c >>>>>(150.l+72) byte x \b.%c >>>>>(150.l+73) byte !0x30 \b%c # Big-endian >>12 string MM # IFD 0 Entry #9: >>>118 beshort 0x8769 # EXIF IFD Entry #1: >>>>(126.L+14) beshort 0x9000 >>>>>(126.L+23) byte x %c >>>>>(126.L+24) byte x \b.%c >>>>>(126.L+25) byte !0x30 \b%c # EXIF IFD Entry #3: >>>>(126.L+38) beshort 0x9000 >>>>>(126.L+47) byte x %c >>>>>(126.L+48) byte x \b.%c >>>>>(126.L+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 beshort 0x8769 # EXIF IFD Entry #3: >>>>(138.L+38) beshort 0x9000 >>>>>(138.L+47) byte x %c >>>>>(138.L+48) byte x \b.%c >>>>>(138.L+49) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.L+62) beshort 0x9000 >>>>>(138.L+71) byte x %c >>>>>(138.L+72) byte x \b.%c >>>>>(138.L+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 beshort 0x8769 # EXIF IFD Entry #4: >>>>(150.L+50) beshort 0x9000 >>>>>(150.L+59) byte x %c >>>>>(150.L+60) byte x \b.%c >>>>>(150.L+61) byte !0x30 \b%c # Here things get sticky. We can do ONE MORE marker segment with # indirect addressing, and that's all. It would be great if we could # do pointer arithemetic like in an assembler language. Christos? # And if there was some sort of looping construct to do searches, plus a few # named accumulators, it would be even more effective... # At least we can show a comment if no other segments got inserted before: >(4.S+5) byte 0xFE >>(4.S+8) string >\0 \b, comment: "%s" # FIXME: When we can do non-byte counted strings, we can use that to get # the string's count, and fix Debian bug #283760 #>(4.S+5) byte 0xFE \b, comment #>>(4.S+6) beshort x \b length=%d #>>(4.S+8) string >\0 \b, "%s" # Or, we can show the encoding type (I've included only the three most common) # and image dimensions if we are lucky and the SOFn (image segment) is here: >(4.S+5) byte 0xC0 \b, baseline >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC1 \b, extended sequential >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC2 \b, progressive >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d # I've commented-out quantisation table reporting. I doubt anyone cares yet. #>(4.S+5) byte 0xDB \b, quantisation table #>>(4.S+6) beshort x \b length=%d #>14 beshort x \b, %d x #>16 beshort x \b %d #-------------------------Kernels------------------------------------- # Linux kernel boot images, from Albert Cahalan # and others such as Axel Kohlmeyer # and Nicolás Lichtmaier # All known start with: b8 c0 07 8e d8 b8 00 90 8e c0 b9 00 01 29 f6 29 0 string \xb8\xc0\x07\x8e\xd8\xb8\x00\x90\x8e\xc0\xb9\x00\x01\x29\xf6\x29 Linux kernel boot image >514 string !HdrS (invalid) # Finds and prints Linux kernel strings in raw Linux kernels (output like uname -a). # Commonly found in decompressed embedded kernel binaries. 0 string Linux\ version\ Linux kernel version >14 byte 0 invalid >14 byte !0 >>14 string x "%s >>45 string x \b%s >>76 string x \b%s >>107 string x \b%s" # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5D # ------------------------------------------------------------------ 0 string \x5D\x00\x00 LZMA compressed data, properties: 0x5D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x01 # ------------------------------------------------------------------ 0 string \x01\x00\x00 LZMA compressed data, properties: 0x01, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x02 # ------------------------------------------------------------------ 0 string \x02\x00\x00 LZMA compressed data, properties: 0x02, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x03 # ------------------------------------------------------------------ 0 string \x03\x00\x00 LZMA compressed data, properties: 0x03, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x04 # ------------------------------------------------------------------ 0 string \x04\x00\x00 LZMA compressed data, properties: 0x04, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x09 # ------------------------------------------------------------------ 0 string \x09\x00\x00 LZMA compressed data, properties: 0x09, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0A # ------------------------------------------------------------------ 0 string \x0A\x00\x00 LZMA compressed data, properties: 0x0A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0B # ------------------------------------------------------------------ 0 string \x0B\x00\x00 LZMA compressed data, properties: 0x0B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0C # ------------------------------------------------------------------ 0 string \x0C\x00\x00 LZMA compressed data, properties: 0x0C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x12 # ------------------------------------------------------------------ 0 string \x12\x00\x00 LZMA compressed data, properties: 0x12, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x13 # ------------------------------------------------------------------ 0 string \x13\x00\x00 LZMA compressed data, properties: 0x13, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x14 # ------------------------------------------------------------------ 0 string \x14\x00\x00 LZMA compressed data, properties: 0x14, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1B # ------------------------------------------------------------------ 0 string \x1B\x00\x00 LZMA compressed data, properties: 0x1B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1C # ------------------------------------------------------------------ 0 string \x1C\x00\x00 LZMA compressed data, properties: 0x1C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x24 # ------------------------------------------------------------------ 0 string \x24\x00\x00 LZMA compressed data, properties: 0x24, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2D # ------------------------------------------------------------------ 0 string \x2D\x00\x00 LZMA compressed data, properties: 0x2D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2E # ------------------------------------------------------------------ 0 string \x2E\x00\x00 LZMA compressed data, properties: 0x2E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2F # ------------------------------------------------------------------ 0 string \x2F\x00\x00 LZMA compressed data, properties: 0x2F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x30 # ------------------------------------------------------------------ 0 string \x30\x00\x00 LZMA compressed data, properties: 0x30, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x31 # ------------------------------------------------------------------ 0 string \x31\x00\x00 LZMA compressed data, properties: 0x31, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x36 # ------------------------------------------------------------------ 0 string \x36\x00\x00 LZMA compressed data, properties: 0x36, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x37 # ------------------------------------------------------------------ 0 string \x37\x00\x00 LZMA compressed data, properties: 0x37, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x38 # ------------------------------------------------------------------ 0 string \x38\x00\x00 LZMA compressed data, properties: 0x38, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x39 # ------------------------------------------------------------------ 0 string \x39\x00\x00 LZMA compressed data, properties: 0x39, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x3F # ------------------------------------------------------------------ 0 string \x3F\x00\x00 LZMA compressed data, properties: 0x3F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x40 # ------------------------------------------------------------------ 0 string \x40\x00\x00 LZMA compressed data, properties: 0x40, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x41 # ------------------------------------------------------------------ 0 string \x41\x00\x00 LZMA compressed data, properties: 0x41, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x48 # ------------------------------------------------------------------ 0 string \x48\x00\x00 LZMA compressed data, properties: 0x48, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x49 # ------------------------------------------------------------------ 0 string \x49\x00\x00 LZMA compressed data, properties: 0x49, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x51 # ------------------------------------------------------------------ 0 string \x51\x00\x00 LZMA compressed data, properties: 0x51, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5A # ------------------------------------------------------------------ 0 string \x5A\x00\x00 LZMA compressed data, properties: 0x5A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5B # ------------------------------------------------------------------ 0 string \x5B\x00\x00 LZMA compressed data, properties: 0x5B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5C # ------------------------------------------------------------------ 0 string \x5C\x00\x00 LZMA compressed data, properties: 0x5C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5E # ------------------------------------------------------------------ 0 string \x5E\x00\x00 LZMA compressed data, properties: 0x5E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x63 # ------------------------------------------------------------------ 0 string \x63\x00\x00 LZMA compressed data, properties: 0x63, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x64 # ------------------------------------------------------------------ 0 string \x64\x00\x00 LZMA compressed data, properties: 0x64, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x65 # ------------------------------------------------------------------ 0 string \x65\x00\x00 LZMA compressed data, properties: 0x65, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x66 # ------------------------------------------------------------------ 0 string \x66\x00\x00 LZMA compressed data, properties: 0x66, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6C # ------------------------------------------------------------------ 0 string \x6C\x00\x00 LZMA compressed data, properties: 0x6C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6D # ------------------------------------------------------------------ 0 string \x6D\x00\x00 LZMA compressed data, properties: 0x6D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6E # ------------------------------------------------------------------ 0 string \x6E\x00\x00 LZMA compressed data, properties: 0x6E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x75 # ------------------------------------------------------------------ 0 string \x75\x00\x00 LZMA compressed data, properties: 0x75, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x76 # ------------------------------------------------------------------ 0 string \x76\x00\x00 LZMA compressed data, properties: 0x76, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x7E # ------------------------------------------------------------------ 0 string \x7E\x00\x00 LZMA compressed data, properties: 0x7E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x87 # ------------------------------------------------------------------ 0 string \x87\x00\x00 LZMA compressed data, properties: 0x87, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x88 # ------------------------------------------------------------------ 0 string \x88\x00\x00 LZMA compressed data, properties: 0x88, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x89 # ------------------------------------------------------------------ 0 string \x89\x00\x00 LZMA compressed data, properties: 0x89, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8A # ------------------------------------------------------------------ 0 string \x8A\x00\x00 LZMA compressed data, properties: 0x8A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8B # ------------------------------------------------------------------ 0 string \x8B\x00\x00 LZMA compressed data, properties: 0x8B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x90 # ------------------------------------------------------------------ 0 string \x90\x00\x00 LZMA compressed data, properties: 0x90, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x91 # ------------------------------------------------------------------ 0 string \x91\x00\x00 LZMA compressed data, properties: 0x91, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x92 # ------------------------------------------------------------------ 0 string \x92\x00\x00 LZMA compressed data, properties: 0x92, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x93 # ------------------------------------------------------------------ 0 string \x93\x00\x00 LZMA compressed data, properties: 0x93, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x99 # ------------------------------------------------------------------ 0 string \x99\x00\x00 LZMA compressed data, properties: 0x99, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9A # ------------------------------------------------------------------ 0 string \x9A\x00\x00 LZMA compressed data, properties: 0x9A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9B # ------------------------------------------------------------------ 0 string \x9B\x00\x00 LZMA compressed data, properties: 0x9B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA2 # ------------------------------------------------------------------ 0 string \xA2\x00\x00 LZMA compressed data, properties: 0xA2, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA3 # ------------------------------------------------------------------ 0 string \xA3\x00\x00 LZMA compressed data, properties: 0xA3, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xAB # ------------------------------------------------------------------ 0 string \xAB\x00\x00 LZMA compressed data, properties: 0xAB, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB4 # ------------------------------------------------------------------ 0 string \xB4\x00\x00 LZMA compressed data, properties: 0xB4, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB5 # ------------------------------------------------------------------ 0 string \xB5\x00\x00 LZMA compressed data, properties: 0xB5, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB6 # ------------------------------------------------------------------ 0 string \xB6\x00\x00 LZMA compressed data, properties: 0xB6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB7 # ------------------------------------------------------------------ 0 string \xB7\x00\x00 LZMA compressed data, properties: 0xB7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB8 # ------------------------------------------------------------------ 0 string \xB8\x00\x00 LZMA compressed data, properties: 0xB8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBD # ------------------------------------------------------------------ 0 string \xBD\x00\x00 LZMA compressed data, properties: 0xBD, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBE # ------------------------------------------------------------------ 0 string \xBE\x00\x00 LZMA compressed data, properties: 0xBE, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBF # ------------------------------------------------------------------ 0 string \xBF\x00\x00 LZMA compressed data, properties: 0xBF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC0 # ------------------------------------------------------------------ 0 string \xC0\x00\x00 LZMA compressed data, properties: 0xC0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC6 # ------------------------------------------------------------------ 0 string \xC6\x00\x00 LZMA compressed data, properties: 0xC6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC7 # ------------------------------------------------------------------ 0 string \xC7\x00\x00 LZMA compressed data, properties: 0xC7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC8 # ------------------------------------------------------------------ 0 string \xC8\x00\x00 LZMA compressed data, properties: 0xC8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xCF # ------------------------------------------------------------------ 0 string \xCF\x00\x00 LZMA compressed data, properties: 0xCF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD0 # ------------------------------------------------------------------ 0 string \xD0\x00\x00 LZMA compressed data, properties: 0xD0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD8 # ------------------------------------------------------------------ 0 string \xD8\x00\x00 LZMA compressed data, properties: 0xD8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes #------------------------------------------------------------------------------ # $File: sql,v 1.6 2009/09/19 16:28:12 christos Exp $ # sql: file(1) magic for SQL files # # From: "Marty Leisner" # Recognize some MySQL files. # 0 beshort 0xfe01 MySQL table definition file >2 string <1 invalid >2 string >\11 invalid >2 byte x Version %d 0 string \xfe\xfe\x03 MySQL MISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x07 MySQL MISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x05 MySQL ISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x06 MySQL ISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \376bin MySQL replication log #------------------------------------------------------------------------------ # iRiver H Series database file # From Ken Guest # As observed from iRivNavi.iDB and unencoded firmware # 0 string iRivDB iRiver Database file >11 string >\0 Version "%s" >39 string iHP-100 [H Series] #------------------------------------------------------------------------------ # SQLite database files # Ken Guest , Ty Sarna, Zack Weinberg # # Version 1 used GDBM internally; its files cannot be distinguished # from other GDBM files. # # Version 2 used this format: 0 string **\x20This\x20file\x20contains\x20an\x20SQLite SQLite 2.x database # Version 3 of SQLite allows applications to embed their own "user version" # number in the database. Detect this and distinguish those files. 0 string SQLite\x20format\x203 >60 string _MTN Monotone source repository >60 belong !0 SQLite 3.x database, user version %u >60 belong 0 SQLite 3.x database ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/parser.py ================================================ import os.path import tempfile from common import str2int class MagicParser: ''' Class for loading, parsing and creating libmagic-compatible magic files. This class is primarily used internally by the Binwalk class, and a class instance of it is available via the Binwalk.parser object. One useful method however, is file_from_string(), which will generate a temporary magic file from a given signature string: import binwalk bw = binwalk.Binwalk() # Create a temporary magic file that contains a single entry with a signature of '\\x00FOOBAR\\xFF', and append the resulting # temporary file name to the list of magic files in the Binwalk class instance. bw.magic_files.append(bw.parser.file_from_string('\\x00FOOBAR\\xFF', display_name='My custom signature')) bw.scan('firmware.bin') All magic files generated by this class will be deleted when the class deconstructor is called. ''' SHORT_SIZE = 2 SHORTS = ['beshort', 'leshort', 'byte'] BIG_ENDIAN = 'big' LITTLE_ENDIAN = 'little' MAGIC_STRING_FORMAT = "%d\tstring\t%s\t%s\n" DEFAULT_DISPLAY_NAME = "Raw string signature" WILDCARD = 'x' # If libmagic returns multiple results, they are delimited with this string. RESULT_SEPERATOR = "\\012- " # Size of the keys used in the matches set. Limited to 2 # as the key is the magic signature of a given magic file entry. # Entries can have variable length signatures, but the lowest # common demonitor is 2, so the first two bytes of the signature # is used as the key. Does this result in collisions and false # positives? Yes. But false positives are filtered out by the # MagicFilter class. The main purpose of MagicParser.match is to # limit the number of calls to libmagic without itself incurring # large computational overhead. And for that purpose, this is # quite effective. MATCH_INDEX_SIZE = 2 def __init__(self, filter=None, smart=None): ''' Class constructor. @filter - Instance of the MagicFilter class. May be None if the parse/parse_file methods are not used. @smart - Instance of the SmartSignature class. May be None if the parse/parse_file methods are not used. Returns None. ''' self.matches = set([]) self.signatures = {} self.sigset = {} self.filter = filter self.smart = smart self.raw_fd = None self.signature_count = 0 self.fd = tempfile.NamedTemporaryFile() def __del__(self): ''' Class deconstructor. ''' self.cleanup() def cleanup(self): ''' Cleans up any tempfiles created by the class instance. Returns None. ''' # Clean up the tempfiles try: self.fd.close() except: pass try: self.raw_fd.close() except: pass def file_from_string(self, signature_string, offset=0, display_name=DEFAULT_DISPLAY_NAME): ''' Generates a magic file from a signature string. @signature_string - The string signature to search for. @offset - The offset at which the signature should occur. @display_name - The text to display when the signature is found. Returns the name of the generated temporary magic file. ''' self.raw_fd = tempfile.NamedTemporaryFile() self.raw_fd.write(self.MAGIC_STRING_FORMAT % (offset, signature_string, display_name)) self.raw_fd.seek(0) return self.raw_fd.name def parse(self, file_name, filter_short_signatures=True, pre_filter_signatures=True): ''' Parses magic file(s) and contatenates them into a single temporary magic file while simultaneously removing filtered signatures. @file_name - Magic file, or list of magic files, to parse. @filter_short_signatures - Set to False to include entries with short (2 byte) magic signatures. @pre_filter_signatures - Set to False to disable smart signature keywords. Returns the name of the generated temporary magic file, which will be automatically deleted when the class deconstructor is called. ''' if type(file_name) == type([]): files = file_name else: files = [file_name] for fname in files: if os.path.exists(fname): self.parse_file(fname, filter_short_signatures, pre_filter_signatures) self.fd.seek(0) return self.fd.name def parse_file(self, file_name, filter_short_signatures=True, pre_filter_signatures=True): ''' Parses a magic file and appends valid signatures to the temporary magic file, as allowed by the existing filter rules. @file_name - Magic file to parse. @filter_short_signatures - Set to False to include entries with short (2 byte) magic signatures. @pre_filter_signatures - Set to False to disable smart signature keywords. Returns None. ''' # Default to not including signature entries until we've # found what looks like a valid entry. include = False line_count = 0 try: for line in open(file_name).readlines(): line_count += 1 # Check if this is the first line of a signature entry entry = self._parse_line(line) if entry is not None: # Once an entry is identified, default to excluding the entry include = False if pre_filter_signatures: # If the smart signature include keyword is specified for this entry, # add an include filter for this signature description. if self.smart.include(entry['description']): self.filter.include(entry['description'], exclusive=False) include = True # If we haven't already explicitly included this entry, and we are # filtering out short signatures and this is a short signature, then # add an exclude filter for this signature description if not include and filter_short_signatures and self._is_short(entry): self.filter.exclude(entry['description']) # If this signature is marked for inclusion, include it. if self.filter.filter(entry['description']) == self.filter.FILTER_INCLUDE: include = True if include: self.signature_count += 1 if not self.signatures.has_key(entry['offset']): self.signatures[entry['offset']] = [] if entry['condition'][:self.MATCH_INDEX_SIZE] not in self.signatures[entry['offset']]: self.signatures[entry['offset']].append(entry['condition'][:self.MATCH_INDEX_SIZE]) # Keep writing lines of the signature to the temporary magic file until # we detect a signature that should not be included. if include: self.fd.write(line) except Exception, e: raise Exception("Error parsing magic file '%s' on line %d: %s" % (file_name, line_count, str(e))) # Generate a dictionary of offsets with a set of signatures for (offset, siglist) in self.signatures.iteritems(): self.sigset[offset] = set(siglist) def _is_short(self, entry): ''' Determines if a signature entry has a short (2 byte) signature or not. @entry - Entry dictionary, as returned by self._parse_line(). Returns True if the signature is short, False if not short. ''' if entry['type'] in self.SHORTS: return True elif 'string' in entry['type']: if len(entry['condition'].decode('string_escape')) <= self.SHORT_SIZE: return True return False def _parse_line(self, line): ''' Parses a signature line into its four parts (offset, type, condition and description), looking for the first line of a given signature. @line - The signature line to parse. Returns a dictionary with the respective line parts populated if the line is the first of a signature. Returns a dictionary with all parts set to None if the line is not the first of a signature. ''' entry = { 'offset' : '', 'type' : '', 'condition' : '', 'description' : '', 'length' : 0 } # Quick and dirty pre-filter. We are only concerned with the first line of a # signature, which will always start with a number. Make sure the first byte of # the line is a number; if not, don't process. if line[:1] < '0' or line[:1] > '9': return None try: # Split the line into white-space separated parts. # For this to work properly, replace escaped spaces ('\ ') with '\x20'. # This means the same thing, but doesn't confuse split(). line_parts = line.replace('\\ ', '\\x20').split() entry['offset'] = line_parts[0] entry['type'] = line_parts[1] # The condition line may contain escaped sequences, so be sure to decode it properly. entry['condition'] = line_parts[2].decode('string_escape') entry['description'] = ' '.join(line_parts[3:]) except Exception, e: raise Exception("%s :: %s", (str(e), line)) # We've already verified that the first character in this line is a number, so this *shouldn't* # throw an exception, but let's catch it just in case... try: entry['offset'] = str2int(entry['offset']) except Exception, e: raise Exception("%s :: %s", (str(e), line)) # If this is a string, get the length of the string if 'string' in entry['type']: entry['length'] = len(entry['condition']) # Else, we need to jump through a few more hoops... else: # Default to little endian, unless the type field starts with 'be'. # This assumes that we're running on a little endian system... if entry['type'].startswith('be'): endianess = self.BIG_ENDIAN else: endianess = self.LITTLE_ENDIAN # Try to convert the condition to an integer. This does not allow # for more advanced conditions for the first line of a signature, # but needing that is rare. if entry['condition'] != self.WILDCARD: try: intval = str2int(entry['condition'].strip('L')) except Exception, e: raise Exception("Failed to evaluate condition for '%s' type: '%s', condition: '%s', error: %s" % (entry['description'], entry['type'], entry['condition'], str(e))) else: intval = 0 entry['length'] = 1 # How long is the field type? if entry['type'] == 'byte': entry['length'] = 1 elif 'short' in entry['type']: entry['length'] = 2 elif 'long' in entry['type']: entry['length'] = 4 elif 'quad' in entry['type']: entry['length'] = 8 # Convert the integer value to a string of the appropriate endianess entry['condition'] = self._to_string(intval, entry['length'], endianess) return entry def build_signature_set(self): ''' Builds a list of signature tuples. Returns a list of tuples in the format: [(, [set of 2-byte signatures])]. ''' signatures = [] for (offset, sigset) in self.sigset.iteritems(): signatures.append((offset, sigset)) signatures.sort() return signatures def _to_string(self, value, size, endianess): ''' Converts an integer value into a raw string. @value - The integer value to convert. @size - Size, in bytes, of the integer value. @endianess - One of self.LITTLE_ENDIAN | self.BIG_ENDIAN. Returns a raw string containing value. ''' data = "" for i in range(0, size): data += chr((value >> (8*i)) & 0xFF) if endianess != self.LITTLE_ENDIAN: data = data[::-1] return data def split(self, data): ''' Splits multiple libmagic results in the data string into a list of separate results. @data - Data string returned from libmagic. Returns a list of result strings. ''' try: return data.split(self.RESULT_SEPERATOR) except: return [] ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/prettyprint.py ================================================ import sys import hashlib from datetime import datetime class PrettyPrint: ''' Class for printing Binwalk results to screen/log files. An instance of PrettyPrint is available via the Binwalk.display object. The PrettyPrint.results() method is of particular interest, as it is suitable for use as a Binwalk.scan() callback function, and can be used to print Binwalk.scan() results to stdout, a log file, or both. Example usage: import binwalk bw = binwalk.Binwalk() bw.display.header() bw.scan('firmware.bin', callback=bw.display.results) bw.display.footer() ''' def __init__(self, log=None, quiet=False, bwalk=None, verbose=0): ''' Class constructor. @log - Output log file. @quiet - If True, results will not be displayed to screen. @bwalk - The Binwalk class instance. @verbose - If set to True, target file information will be displayed when file_info() is called. Returns None. ''' self.fp = None self.log =log self.quiet = quiet self.binwalk = bwalk self.verbose = verbose if self.log is not None: self.fp = open(log, "w") def __del__(self): ''' Class deconstructor. ''' # Close the log file. try: self.fp.close() except: pass def _log(self, data): ''' Log data to the log file. ''' if self.fp is not None: self.fp.write(data) def _pprint(self, data): ''' Print data to stdout and the log file. ''' if not self.quiet: sys.stdout.write(data) self._log(data) def _file_md5(self, file_name): ''' Generate an MD5 hash of the specified file. ''' md5 = hashlib.md5() with open(file_name, 'rb') as f: for chunk in iter(lambda: f.read(128*md5.block_size), b''): md5.update(chunk) return md5.hexdigest() def file_info(self, file_name): ''' Prints detailed info about the specified file, including file name, scan time and the file's MD5 sum. Called internally by self.header if self.verbose is not 0. @file_name - The path to the target file. Returns None. ''' self._pprint("\n") self._pprint("Scan Time: %s\n" % datetime.now().strftime("%Y-%m-%d %H:%M:%S")) self._pprint("Signatures: %d\n" % self.binwalk.parser.signature_count) self._pprint("Target File: %s\n" % file_name) self._pprint("MD5 Checksum: %s\n" % self._file_md5(file_name)) def header(self, file_name=None): ''' Prints the Binwalk header, typically used just before starting a scan. @file_name - If specified, and if self.verbose > 0, then detailed file info will be included in the header. Returns None. ''' if self.verbose and file_name is not None: self.file_info(file_name) self._pprint("\nDECIMAL \tHEX \tDESCRIPTION\n") self._pprint("-------------------------------------------------------------------------------------------------------\n") def footer(self): ''' Prints the Binwalk footer, typically used just after completing a scan. Returns None. ''' self._pprint("\n") def results(self, offset, results): ''' Prints the results of a scan. Suitable for use as a callback function for Binwalk.scan(). @offset - The offset at which the results were found. @results - A list of libmagic result strings. Returns None. ''' offset_printed = False for info in results: # Check for any grep filters before printing if self.binwalk is not None and self.binwalk.filter.grep(info['description']): # Only display the offset once per list of results if not offset_printed: self._pprint("%-10d\t0x%-8X\t%s\n" % (offset, offset, info['description'])) offset_printed = True else: self._pprint("%s\t %s\t%s\n" % (' '*10, ' '*8, info['description'])) ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/smartsig.py ================================================ import re from common import str2int, get_quoted_strings class SmartSignature: ''' Class for parsing smart signature tags in libmagic result strings. This class is intended for internal use only, but a list of supported 'smart keywords' that may be used in magic files is available via the SmartSignature.KEYWORDS dictionary: from binwalk import SmartSignature for (i, keyword) in SmartSignature().KEYWORDS.iteritems(): print keyword ''' KEYWORD_DELIM_START = "{" KEYWORD_DELIM_END = "}" KEYWORDS = { 'jump' : '%sjump-to-offset:' % KEYWORD_DELIM_START, 'filename' : '%sfile-name:' % KEYWORD_DELIM_START, 'filesize' : '%sfile-size:' % KEYWORD_DELIM_START, 'raw-string' : '%sraw-string:' % KEYWORD_DELIM_START, # This one is special and must come last in a signature block 'raw-size' : '%sraw-string-length:' % KEYWORD_DELIM_START, 'adjust' : '%soffset-adjust:' % KEYWORD_DELIM_START, 'delay' : '%sextract-delay:' % KEYWORD_DELIM_START, 'raw-replace' : '%sraw-replace%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'one-of-many' : '%sone-of-many%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'include' : '%sfilter-include%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), 'exclude' : '%sfilter-exclude%s' % (KEYWORD_DELIM_START, KEYWORD_DELIM_END), } def __init__(self, filter, pre_filter_signatures=True): ''' Class constructor. @filter - Instance of the MagicFilter class. @pre_filter_signatures - Set to False to disable the pre-filtering of magic signatures. Returns None. ''' self.filter = filter self.last_one_of_many = None self.pre_filter_signatures = pre_filter_signatures def parse(self, data): ''' Parse a given data string for smart signature keywords. If any are found, interpret them and strip them. @data - String to parse, as returned by libmagic. Returns a dictionary of parsed values. ''' results = { 'description' : '', # The libmagic data string, stripped of all keywords 'name' : '', # The original name of the file, if known 'delay' : '', # Extract delay description 'extract' : '', # Name of the extracted file, filled in by Binwalk.Scan. 'jump' : 0, # The relative offset to resume the scan from 'size' : 0, # The size of the file, if known 'adjust' : 0, # The relative offset to add to the reported offset } # If pre-filtering is disabled, or the result data is not valid (i.e., potentially malicious), # don't parse anything, just return the raw data as the description. if not self.pre_filter_signatures or not self._is_valid(data): results['description'] = data else: # Parse the offset-adjust value. This is used to adjust the reported offset at which # a signature was located due to the fact that MagicParser.match expects all signatures # to be located at offset 0, which some wil not be. results['adjust'] = self._get_math_arg(data, 'adjust') # Parse the file-size value. This is used to determine how many bytes should be extracted # when extraction is enabled. If not specified, everything to the end of the file will be # extracted (see Binwalk.scan). try: results['size'] = str2int(self._get_keyword_arg(data, 'filesize')) except: pass results['delay'] = self._get_keyword_arg(data, 'delay') # Parse the string for the jump-to-offset keyword. # This keyword is honored, even if this string result is one of many. results['jump'] = self._get_math_arg(data, 'jump') # If this is one of many, don't do anything and leave description as a blank string. # Else, strip all keyword tags from the string and process additional keywords as necessary. if not self._one_of_many(data): results['name'] = self._get_keyword_arg(data, 'filename').strip('"') results['description'] = self._strip_tags(data) return results def _is_valid(self, data): ''' Validates that result data does not contain smart keywords in file-supplied strings. @data - Data string to validate. Returns True if data is OK. Returns False if data is not OK. ''' # All strings printed from the target file should be placed in strings, else there is # no way to distinguish between intended keywords and unintended keywords. Get all the # quoted strings. quoted_data = get_quoted_strings(data) # Check to see if there was any quoted data, and if so, if it contained the keyword starting delimiter if quoted_data and self.KEYWORD_DELIM_START in quoted_data: # If so, check to see if the quoted data contains any of our keywords. # If any keywords are found inside of quoted data, consider the keywords invalid. for (name, keyword) in self.KEYWORDS.iteritems(): if keyword in quoted_data: return False return True def _one_of_many(self, data): ''' Determines if a given data string is one result of many. @data - String result data. Returns True if the string result is one of many. Returns False if the string result is not one of many. ''' if not self.filter.invalid(data): if self.last_one_of_many is not None and data.startswith(self.last_one_of_many): return True if self.KEYWORDS['one-of-many'] in data: # Only match on the data before the first comma, as that is typically unique and static self.last_one_of_many = data.split(',')[0] else: self.last_one_of_many = None return False def _get_keyword_arg(self, data, keyword): ''' Retrieves the argument for keywords that specify arguments. @data - String result data, as returned by libmagic. @keyword - Keyword index in KEYWORDS. Returns the argument string value on success. Returns a blank string on failure. ''' arg = '' if self.KEYWORDS.has_key(keyword) and self.KEYWORDS[keyword] in data: arg = data.split(self.KEYWORDS[keyword])[1].split(self.KEYWORD_DELIM_END)[0] return arg def _get_math_arg(self, data, keyword): ''' Retrieves the argument for keywords that specifiy mathematical expressions as arguments. @data - String result data, as returned by libmagic. @keyword - Keyword index in KEYWORDS. Returns the resulting calculated value. ''' value = 0 arg = self._get_keyword_arg(data, keyword) if arg: for string_int in arg.split('+'): try: value += str2int(string_int) except: pass return value def _jump(self, data): ''' Obtains the jump-to-offset value of a signature, if any. @data - String result data. Returns the offset to jump to. ''' offset = 0 offset_str = self._get_keyword_arg(data, 'jump') if offset_str: try: offset = str2int(offset_str) except: pass return offset def _parse_raw_strings(self, data): ''' Process strings that aren't NULL byte terminated, but for which we know the string length. This should be called prior to any other smart parsing functions. @data - String to parse. Returns a parsed string. ''' if self.pre_filter_signatures and self._is_valid(data): # Get the raw string keyword arg raw_string = self._get_keyword_arg(data, 'raw-string') # Was a raw string keyword specified? if raw_string: # Get the raw string length arg raw_size = self._get_keyword_arg(data, 'raw-size') # Is the raw string length arg is a numeric value? if re.match('^-?[0-9]+$', raw_size): # Replace all instances of raw-replace in data with raw_string[:raw_size] # Also strip out everything after the raw-string keyword, including the keyword itself. # Failure to do so may (will) result in non-printable characters and this string will be # marked as invalid when it shouldn't be. data = data[:data.find(self.KEYWORDS['raw-string'])].replace(self.KEYWORDS['raw-replace'], '"' + raw_string[:str2int(raw_size)] + '"') return data def include(self, data): ''' Determines if a result should be included or excluded. @data - String result data. Returns True if the include smart tag is present. Returns False if the exclude smart tag is present. Returns None if neither smart tags are present. ''' # Validate keywords before checking for the include/exclude keywords. if self.pre_filter_signatures and self._is_valid(data): if self.KEYWORDS['exclude'] in data: return False elif self.KEYWORDS['include'] in data: return True return None def _strip_tags(self, data): ''' Strips the smart tags from a result string. @data - String result data. Returns a sanitized string. ''' if self.pre_filter_signatures: for (name, keyword) in self.KEYWORDS.iteritems(): start = data.find(keyword) if start != -1: end = data[start:].find(self.KEYWORD_DELIM_END) if end != -1: data = data.replace(data[start:start+end+1], "") return data ================================================ FILE: src/binwalk-1.0/src/build/lib.linux-x86_64-2.7/binwalk/update.py ================================================ import urllib2 from config import * class Update: ''' Class for updating Binwalk configuration and signatures files from the subversion trunk. Example usage: from binwalk import Update Update().update() ''' BASE_URL = "http://binwalk.googlecode.com/svn/trunk/src/binwalk/" MAGIC_PREFIX = "magic/" CONFIG_PREFIX = "config/" def __init__(self): ''' Class constructor. ''' self.config = Config() def update(self): ''' Updates all system wide signatures and config files. Returns None. ''' self.update_binwalk() self.update_bincast() self.update_binarch() self.update_extract() def _do_update_from_svn(self, prefix, fname): ''' Updates the specified file to the latest version of that file in SVN. @prefix - The URL subdirectory where the file is located. @fname - The name of the file to update. Returns None. ''' url = self.BASE_URL + prefix + fname try: data = urllib2.urlopen(url).read() open(self.config.paths['system'][fname], "wb").write(data) except Exception, e: raise Exception("Update._do_update_from_svn failed to update file '%s': %s" % (url, str(e))) def update_binwalk(self): ''' Updates the binwalk signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINWALK_MAGIC_FILE) def update_bincast(self): ''' Updates the bincast signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINCAST_MAGIC_FILE) def update_binarch(self): ''' Updates the binarch signature file. Returns None. ''' self._do_update_from_svn(self.MAGIC_PREFIX, self.config.BINARCH_MAGIC_FILE) def update_extract(self): ''' Updates the extract.conf file. Returns None. ''' self._do_update_from_svn(self.CONFIG_PREFIX, self.config.EXTRACT_FILE) ================================================ FILE: src/binwalk-1.0/src/build/scripts-2.7/binwalk ================================================ #!/usr/bin/python import sys import os.path import binwalk from threading import Thread from binwalk.common import str2int from getopt import GetoptError, getopt as GetOpt def display_status(bwalk): while True: # Display the current scan progress when the enter key is pressed. raw_input() print "Progress: %.2f%% (%d / %d)\n" % (((float(bwalk.total_scanned) / float(bwalk.scan_length)) * 100), bwalk.total_scanned, bwalk.scan_length) def usage(fd): fd.write("\n") fd.write("Binwalk v%s\n" % binwalk.Config.VERSION) fd.write("Craig Heffner, http://www.devttys0.com\n") fd.write("\n") fd.write("Usage: %s [OPTIONS] [FILE1] [FILE2] [FILE3] ...\n" % os.path.basename(sys.argv[0])) fd.write("\n") fd.write("\t-o, --offset= Start scan at this file offset\n") fd.write("\t-l, --length= Number of bytes to scan\n") fd.write("\t-b, --align= Set byte alignment [default: 1]\n") fd.write("\t-m, --magic= Specify an alternate magic file to use\n") fd.write("\t-i, --include= Include matches that are normally excluded and that have in their description\n") fd.write("\t-x, --exclude= Exclude matches that have in their description\n") fd.write("\t-y, --search= Only search for matches that have in their description\n") fd.write("\t-g, --grep= Grep results for the specified text\n") fd.write("\t-R, --raw-bytes= Search for a sequence of raw bytes instead of using the default magic signatures\n") fd.write("\t-f, --file= Log results to file\n") fd.write("\t-D, --dd= Extract entries whose descriptions match , give them file extension , and execute \n") fd.write("\t-e, --extract=[file] Automatically extract known file types. Load rules from file, if specified.\n") fd.write("\t-r, --rm Cleanup extracted files and zero-size files\n") fd.write("\t-d, --delay Delay file extraction for files with known footers\n") fd.write("\t-a, --all Include all short signatures\n") fd.write("\t-I, --show-invalid Show results marked as invalid\n") fd.write("\t-A, --opcodes Scan for executable code\n") fd.write("\t-C, --cast Cast file contents as various data types\n") fd.write("\t-k, --keep-going Show all matching results at a given offset, not just the first one\n") fd.write("\t-q, --quiet Supress output to stdout\n") fd.write("\t-v, --verbose Be verbose (specify twice for very verbose)\n") fd.write("\t-u, --update Update magic signature files\n") fd.write("\t-h, --help Show help output\n") fd.write("\n") if fd == sys.stderr: sys.exit(1) else: sys.exit(0) def main(): MIN_ARGC = 2 align = 1 offset = 0 length = 0 quiet = False pre_filter = True verbose = 0 log_file = None show_invalid = False short_sig = True custom_signature = None delay_extraction = False extract_rules_file = None extract_from_config = False cleanup_after_extract = False magic_flags = binwalk.magic.MAGIC_NONE options = [] magic_files = [] target_files = [] greps = [] includes = [] excludes = [] searches = [] extracts = [] config = binwalk.Config() short_options = "aACdhkeqruvPIf:o:l:b:i:x:y:D:m:R:g:" long_options = [ "rm", "all", "help", "quiet", "verbose", "opcodes", "cast", "update", "keep-going", "show-invalid", "profile", "delay", "file=", "offset=", "length=", "align=", "include=", "exclude=", "extract=", "search=", "dd=", "grep=", "magic=", "raw-bytes=", ] # Require at least one argument (the target file) if len(sys.argv) < MIN_ARGC: usage(sys.stderr) try: opts, args = GetOpt(sys.argv[1:], short_options, long_options) except GetoptError, e: sys.stderr.write("%s\n" % str(e)) usage(sys.stderr) for opt, arg in opts: if opt in ("-h", "--help"): usage(sys.stdout) elif opt in ("-d", "--delay"): delay_extraction = True elif opt in ("-f", "--file"): log_file = arg elif opt in ("-q", "--quiet"): quiet = True elif opt in ("-v", "--verbose"): verbose += 1 elif opt in ("-o", "--offset"): offset = str2int(arg) elif opt in ("-l", "--length"): length = str2int(arg) elif opt in ("-b", "--align"): align = str2int(arg) elif opt in ("-i", "--include"): includes.append(arg) elif opt in ("-y", "--search"): searches.append(arg) elif opt in ("-x", "--exclude"): excludes.append(arg) elif opt in ("-D", "--dd"): extracts.append(arg) elif opt in ("-g", "--grep"): greps.append(arg) elif opt in ("-e", "--extract"): if arg: extract_rules_file = arg else: extract_from_config = True elif opt in ("-r", "--rm"): cleanup_after_extract = True elif opt in ("-m", "--magic"): magic_files.append(arg) elif opt in ("-a", "--all"): short_sig = False elif opt in ("-k", "--keep-going"): magic_flags |= binwalk.magic.MAGIC_CONTINUE elif opt in ("-I", "--show-invalid"): show_invalid = True elif opt in ("-A", "--opcodes"): # Check every single offset align = 1 # Don't filter out short signatures as some opcode sigs are only 2 bytes short_sig = False # Load user file first so its signatures take precedence magic_files.append(config.paths['user'][config.BINARCH_MAGIC_FILE]) magic_files.append(config.paths['system'][config.BINARCH_MAGIC_FILE]) elif opt in ("-C", "--cast"): # Check every single offset align = 1 # Don't stop at the first match (everything matches everything in this scan) magic_flags |= binwalk.magic.MAGIC_CONTINUE # Disable all pre filtering; we want to check everything for this scan pre_filter = False # Don't filter shot signatures, or else some casts won't be displayed short_sig = False # Load user file first so its signatures take precedence magic_files.append(config.paths['user'][config.BINCAST_MAGIC_FILE]) magic_files.append(config.paths['system'][config.BINCAST_MAGIC_FILE]) elif opt in ("-R", "--raw-bytes"): # Disable short signature filtering, as the supplied string may be short short_sig = False custom_signature = arg elif opt in ("-u", "--update"): try: sys.stdout.write("Updating signatures...") sys.stdout.flush() binwalk.Update().update() sys.stdout.write("done.\n") sys.exit(0) except Exception, e: if 'Permission denied' in str(e): sys.stderr.write("failed (permission denied). Check your user permissions, or run the update as root.\n") else: sys.stderr.write('\n' + str(e) + '\n') sys.exit(1) # The --profile option is handled prior to calling main() elif opt not in ('-P', '--profile'): usage(sys.stderr) # Append the option and argument to the list of processed options # This is used later to determine which argv entries are file names options.append(opt) options.append(arg) options.append("%s%s" % (opt, arg)) options.append("%s=%s" % (opt, arg)) # Treat any command line options not processed by getopt as target file paths for opt in sys.argv[1:]: #TODO: Do we really want to not process valid files that start with a '-'? # This is probably OK, and ensures that no options are treated as target files. if opt not in options and not opt.startswith('-'): target_files.append(opt) # If more than one target file was specified, enable verbose mode; else, there is # nothing in the output to indicate which scan corresponds to which file. if len(target_files) > 1: verbose = True # Instantiate the Binwalk class bwalk = binwalk.Binwalk(flags=magic_flags, verbose=verbose, log=log_file, quiet=quiet) # If a custom signature was specified, create a temporary magic file containing the custom signature # and ensure that it is the only magic file that will be loaded when Binwalk.scan() is called. if custom_signature is not None: magic_files = bwalk.parser.file_from_string(custom_signature) # Set any specified filters bwalk.filter.include(includes, exclusive=False) bwalk.filter.exclude(excludes) bwalk.filter.include(searches) bwalk.filter.grep(filters=greps) # Add any specified extract rules bwalk.extractor.add_rule(extracts) # If -e was specified, load the default extract rules if extract_from_config: bwalk.extractor.load_defaults() # If --extract was specified, load the specified extraction rules file if extract_rules_file is not None: bwalk.extractor.load_from_file(extract_rules_file) # Set the extractor cleanup value (True to clean up files, False to leave them on disk) bwalk.extractor.cleanup_extracted_files(cleanup_after_extract) # Enable delayed extraction, which will prevent supported file types from having trailing data when extracted bwalk.extractor.enable_delayed_extract(delay_extraction) # Load the magic file(s) bwalk.load_signatures(magic_files=magic_files, pre_filter_signatures=pre_filter, filter_short_signatures=short_sig) # Scan each target file for target_file in target_files: bwalk.display.header(target_file) # Start the display_status function as a daemon thread t = Thread(target=display_status, args=(bwalk,)) t.setDaemon(True) t.start() # Catch keyboard interrupts so that we can properly clean up after the scan try: bwalk.scan(target_file, offset=offset, length=length, align=align, show_invalid_results=show_invalid, callback=bwalk.display.results) except KeyboardInterrupt: pass bwalk.display.footer() # Be sure to drink your ovaltine. # And also to clean up any temporary magic files. bwalk.cleanup() try: # Special options for profiling the code. For debug use only. if '--profile' in sys.argv or '-P' in sys.argv: import cProfile cProfile.run('main()') else: main() except KeyboardInterrupt: pass ================================================ FILE: src/binwalk-1.0/src/magic/archives ================================================ # ----------------------------Archive Formats-------------------------------------- # POSIX tar archives 0 string ustar\000 POSIX tar archive{offset-adjust:-257} 0 string ustar\040\040\000 POSIX tar archive (GNU){offset-adjust:-257} # JAR archiver (.j), this is the successor to ARJ, not Java's JAR (which is essentially ZIP) 0 string \x1aJar\x1b JAR (ARJ Software, Inc.) archive data{offset-adjust:-14} 0 string JARCS JAR (ARJ Software, Inc.) archive data # ARJ archiver (jason@jarthur.Claremont.EDU) 0 leshort 0xea60 ARJ archive data >5 byte x \b, v%d, >8 byte &0x04 multi-volume, >8 byte &0x10 slash-switched, >8 byte &0x20 backup, >34 string x original name: "%s", >7 byte 0 os: MS-DOS >7 byte 1 os: PRIMOS >7 byte 2 os: Unix >7 byte 3 os: Amiga >7 byte 4 os: Macintosh >7 byte 5 os: OS/2 >7 byte 6 os: Apple ][ GS >7 byte 7 os: Atari ST >7 byte 8 os: NeXT >7 byte 9 os: VAX/VMS >3 byte >0 %d] # RAR archiver (Greg Roelofs, newt@uchicago.edu) 0 string Rar! RAR archive data # HPACK archiver (Peter Gutmann, pgut1@cs.aukuni.ac.nz) 0 string HPAK HPACK archive data # JAM Archive volume format, by Dmitry.Kohmanyuk@UA.net 0 string \351,\001JAM JAM archive # LHARC/LHA archiver (Greg Roelofs, newt@uchicago.edu) 0 string -lzs- LHa 2.x? archive data [lzs] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh\40- LHa 2.x? archive data [lh ] [NSRL|LHA2]{offset-adjust:-2} 0 string -lhd- LHa 2.x? archive data [lhd] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh2- LHa 2.x? archive data [lh2] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh3- LHa 2.x? archive data [lh3] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh4- LHa (2.x) archive data [lh4] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh5- LHa (2.x) archive data [lh5] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh6- LHa (2.x) archive data [lh6] [NSRL|LHA2]{offset-adjust:-2} 0 string -lh7- LHa (2.x) archive data [lh7] [NSRL|LHA2]{offset-adjust:-2} # cpio archives # # The SVR4 "cpio(4)" hints that there are additional formats, but they # are defined as "short"s; I think all the new formats are # character-header formats and thus are strings, not numbers. #0 string 070707 ASCII cpio archive (pre-SVR4 or odc) 0 string 070701 ASCII cpio archive (SVR4 with no CRC), >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} 0 string 070702 ASCII cpio archive (SVR4 with CRC) >110 byte 0 invalid >110 string x file name: "%s" >54 string x {jump-to-offset:0x%.8s+112} # HP Printer Job Language # The header found on Win95 HP plot files is the "Silliest Thing possible" # (TM) # Every driver puts the language at some random position, with random case # (LANGUAGE and Language) # For example the LaserJet 5L driver puts the "PJL ENTER LANGUAGE" in line 10 # From: Uwe Bonnes # 0 string \033%-12345X@PJL HP Printer Job Language data >&0 string >\0 "%s" >>&0 string >\0 "%s" >>>&0 string >\0 "%s" >>>>&0 string >\0 "%s" #------------------------------------------------------------------------------ # # RPM: file(1) magic for Red Hat Packages Erik Troan (ewt@redhat.com) # 0 belong 0xedabeedb RPM >4 byte x v%d >6 beshort 0 bin >6 beshort 1 src >8 beshort 1 i386 >8 beshort 2 Alpha >8 beshort 3 Sparc >8 beshort 4 MIPS >8 beshort 5 PowerPC >8 beshort 6 68000 >8 beshort 7 SGI >8 beshort 8 RS6000 >8 beshort 9 IA64 >8 beshort 10 Sparc64 >8 beshort 11 MIPSel >8 beshort 12 ARM >10 string x "%s" ================================================ FILE: src/binwalk-1.0/src/magic/bootloaders ================================================ #---------------------------Bootloaders-------------------------------- # CFE bootloader 0 string CFE1CFE1 CFE boot loader, little endian 0 string 1EFC1EFC CFE boot loader, big endian ================================================ FILE: src/binwalk-1.0/src/magic/compressed ================================================ #------------------Compression Formats----------------------------- # AFX compressed files (Wolfram Kleff) 0 string -afx- AFX compressed file data{offset-adjust:-2} # bzip2 0 string BZh91AY&SY bzip2 compressed data, block size = 900k 0 string BZh81AY&SY bzip2 compressed data, block size = 800k 0 string BZh71AY&SY bzip2 compressed data, block size = 700k 0 string BZh61AY&SY bzip2 compressed data, block size = 600k 0 string BZh51AY&SY bzip2 compressed data, block size = 500k 0 string BZh41AY&SY bzip2 compressed data, block size = 400k 0 string BZh31AY&SY bzip2 compressed data, block size = 300k 0 string BZh21AY&SY bzip2 compressed data, block size = 200k 0 string BZh11AY&SY bzip2 compressed data, block size = 100k # lzop from 0 string \x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a lzop compressed data >9 beshort <0x0940 >>9 byte&0xf0 =0x00 - version 0. >>9 beshort&0x0fff x \b%03x, >>13 byte 1 LZO1X-1, >>13 byte 2 LZO1X-1(15), >>13 byte 3 LZO1X-999, ## >>22 bedate >0 last modified: %s, >>14 byte =0x00 os: MS-DOS >>14 byte =0x01 os: Amiga >>14 byte =0x02 os: VMS >>14 byte =0x03 os: Unix >>14 byte =0x05 os: Atari >>14 byte =0x06 os: OS/2 >>14 byte =0x07 os: MacOS >>14 byte =0x0A os: Tops/20 >>14 byte =0x0B os: WinNT >>14 byte =0x0E os: Win32 >9 beshort >0x0939 >>9 byte&0xf0 =0x00 - version 0. >>9 byte&0xf0 =0x10 - version 1. >>9 byte&0xf0 =0x20 - version 2. >>9 beshort&0x0fff x \b%03x, >>15 byte 1 LZO1X-1, >>15 byte 2 LZO1X-1(15), >>15 byte 3 LZO1X-999, ## >>25 bedate >0 last modified: %s, >>17 byte =0x00 os: MS-DOS >>17 byte =0x01 os: Amiga >>17 byte =0x02 os: VMS >>17 byte =0x03 os: Unix >>17 byte =0x05 os: Atari >>17 byte =0x06 os: OS/2 >>17 byte =0x07 os: MacOS >>17 byte =0x0A os: Tops/20 >>17 byte =0x0B os: WinNT >>17 byte =0x0E os: Win32 # lzip 0 string LZIP lzip compressed data >4 byte x \b, version: %d # LZO 0 string \211LZO\000\015\012\032\012 LZO compressed data # 7-zip archiver, from Thomas Klausner (wiz@danbala.tuwien.ac.at) # http://www.7-zip.org or DOC/7zFormat.txt # 0 string 7z\274\257\047\034 7-zip archive data, >6 byte x version %d >7 byte x \b.%d # standard unix compress 0 beshort 0x1f9d compress'd data >2 byte&0x80 >0 block compressed >2 byte&0x1f !16 invalid >2 byte&0x1f x %d bits # http://tukaani.org/xz/xz-file-format.txt 0 string \xFD\x37\x7a\x58\x5a\x00 xz compressed data # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver) # Edited by Chris Chittleborough , March 2002 # * Original filename is only at offset 10 if "extra field" absent # * Produce shorter output - notably, only report compression methods # other than 8 ("deflate", the only method defined in RFC 1952). 0 string \037\213\x08 gzip compressed data >3 byte &0x01 \b, ASCII >3 byte &0x02 \b, has CRC >3 byte &0x04 \b, extra field >3 byte&0xC =0x08 >>10 string x \b{file-name:%s} >>10 string x \b, was "%s" >3 byte &0x10 \b, has comment >9 byte =0x00 \b, from FAT filesystem (MS-DOS, OS/2, NT) >9 byte =0x01 \b, from Amiga >9 byte =0x02 \b, from VMS >9 byte =0x03 \b, from Unix >9 byte =0x04 \b, from VM/CMS >9 byte =0x05 \b, from Atari >9 byte =0x06 \b, from HPFS filesystem (OS/2, NT) >9 byte =0x07 \b, from MacOS >9 byte =0x08 \b, from Z-System >9 byte =0x09 \b, from CP/M >9 byte =0x0A \b, from TOPS/20 >9 byte =0x0B \b, from NTFS filesystem (NT) >9 byte =0x0C \b, from QDOS >9 byte =0x0D \b, from Acorn RISCOS >9 byte >0x0D \b, invalid source >9 byte <0 \b, invalid source >3 byte &0x20 \b, encrypted (invalid) # Dates before 1992 are invalid, unless of course you're DD-WRT in which # case you don't know how to set a date in your gzip files. Brilliant. >4 lelong =0 \b, NULL date: >4 lelong <0 \b, invalid date: >4 lelong >0 >>4 lelong <694224000 \b, invalid date: >>4 lelong =694224000 \b, invalid date: >>4 lelong >694224000 \b, last modified: >4 ledate x %s >8 byte 2 \b, max compression >8 byte 4 \b, max speed # Zlib signatures 0 beshort 0x789C zlib compressed data 0 beshort 0x78DA zlib compressed data 0 beshort 0x7801 zlib compressed data # Supplementary magic data for the file(1) command to support # rzip(1). The format is described in magic(5). # # Copyright (C) 2003 by Andrew Tridgell. You may do whatever you want with # this file. # 0 string RZIP rzip compressed data >4 byte x - version %d >5 byte x \b.%d >6 belong x (%d bytes) # ZIP compression (Greg Roelofs, c/o zip-bugs@wkuvx1.wku.edu) 0 string PK\003\004 Zip archive data, >4 byte 0x00 v0.0 >4 byte 0x09 at least v0.9 to extract, >4 byte 0x0a at least v1.0 to extract, >4 byte 0x0b at least v1.1 to extract, >0x161 string WINZIP WinZIP self-extracting, >4 byte 0x14 >>30 ubelong !0x6d696d65 at least v2.0 to extract, >18 lelong !0 >>18 lelong <0 invalid >>18 lelong x compressed size: %d, >22 lelong !0 >>22 lelong <0 invalid >>22 lelong x uncompressed size: %d,{extract-delay:end of zip archive} >30 string x {file-name:{raw-replace}}name: {raw-replace} >26 leshort x {raw-string-length:%d} >30 string x {raw-string:%s >61 string x \b%s >92 string x \b%s >123 string x \b%s >154 string x \b%s} # ZIP footer 0 string PK\x05\x06 End of Zip archive >20 leshort x {offset-adjust:22+%d} >20 leshort >0 >>20 leshort x \b, comment: {raw-replace} >>20 leshort x {raw-string-length:%d} >>22 string x {raw-string:%s} # New LZMA format signature 0 string \xFFLZMA\x00 LZMA compressed data (new), >6 byte&0x10 0 single-block stream >6 byte&0x10 0x10 multi-block stream # See lzma file for LZMA signatures ================================================ FILE: src/binwalk-1.0/src/magic/crypto ================================================ # Type: OpenSSL certificates/key files # From: Nicolas Collignon 0 string -----BEGIN\x20CERTIFICATE----- PEM certificate 0 string -----BEGIN\x20CERTIFICATE\x20REQ PEM certificate request 0 string -----BEGIN\x20RSA\x20PRIVATE PEM RSA private key 0 string -----BEGIN\x20DSA\x20PRIVATE PEM DSA private key # Type: OpenSSH key files # From: Nicolas Collignon 0 string SSH\x20PRIVATE\x20KEY OpenSSH RSA1 private key, >28 string >\0 version "%s" 0 string ssh-dss\x20 OpenSSH DSA public key 0 string ssh-rsa\x20 OpenSSH RSA public key # Type: Certificates/key files in DER format # From: Gert Hulselmans 0 string \x30\x82 Private key in DER format (PKCS#8), >4 string !\x02\x01\x00 invalid, >>2 beshort x header length: 4, sequence length: %d 0 string \x30\x82 Certificate in DER format (x509 v3), >4 string !\x30\x82 invalid, >>2 beshort x header length: 4, sequence length: %d # GnuPG # The format is very similar to pgp 0 string \001gpg GPG key trust database >4 byte x version %d 0 beshort 0x9901 GPG key public ring # This magic is not particularly good, as the keyrings don't have true # magic. Nevertheless, it covers many keyrings. #------------------------------------------------------------------------------ # Mavroyanopoulos Nikos # mcrypt: file(1) magic for mcrypt 2.2.x; 0 string \0m\3 mcrypt 2.5 encrypted data, >4 byte 0 invalid >4 string >\0 algorithm: "%s", >>&1 leshort <1 invalid >>&1 leshort >0 keysize: %d bytes, >>>&0 byte 0 invalid >>>&0 string >\0 mode: "%s", 0 string \0m\2 mcrypt 2.2 encrypted data, >3 byte 0 algorithm: blowfish-448, >3 byte 1 algorithm: DES, >3 byte 2 algorithm: 3DES, >3 byte 3 algorithm: 3-WAY, >3 byte 4 algorithm: GOST, >3 byte 6 algorithm: SAFER-SK64, >3 byte 7 algorithm: SAFER-SK128, >3 byte 8 algorithm: CAST-128, >3 byte 9 algorithm: xTEA, >3 byte 10 algorithm: TWOFISH-128, >3 byte 11 algorithm: RC2, >3 byte 12 algorithm: TWOFISH-192, >3 byte 13 algorithm: TWOFISH-256, >3 byte 14 algorithm: blowfish-128, >3 byte 15 algorithm: blowfish-192, >3 byte 16 algorithm: blowfish-256, >3 byte 100 algorithm: RC6, >3 byte 101 algorithm: IDEA, >3 byte <0 invalid algorithm >3 byte >101 invalid algorithm, >3 byte >16 >>3 byte <100 invalid algorithm, >4 byte 0 mode: CBC, >4 byte 1 mode: ECB, >4 byte 2 mode: CFB, >4 byte 3 mode: OFB, >4 byte 4 mode: nOFB, >4 byte <0 invalid mode, >4 byte >4 invalid mode, >5 byte 0 keymode: 8bit >5 byte 1 keymode: 4bit >5 byte 2 keymode: SHA-1 hash >5 byte 3 keymode: MD5 hash >5 byte <0 invalid keymode >5 byte >3 invalid keymode #------------------------------------------------------------------------------ # pgp: file(1) magic for Pretty Good Privacy # #0 beshort 0x9900 PGP key public ring #0 beshort 0x9501 PGP key security ring #0 beshort 0x9500 PGP key security ring #0 beshort 0xa600 PGP encrypted data 0 string -----BEGIN\040PGP PGP armored data >15 string PUBLIC\040KEY\040BLOCK- public key block >15 string MESSAGE- message >15 string SIGNED\040MESSAGE- signed message >15 string PGP\040SIGNATURE- signature ================================================ FILE: src/binwalk-1.0/src/magic/executables ================================================ #------------------Standard file formats------------------------------------ #------------------------------------------------------------------------------ # elf: file(1) magic for ELF executables # # We have to check the byte order flag to see what byte order all the # other stuff in the header is in. # # What're the correct byte orders for the nCUBE and the Fujitsu VPP500? # # updated by Daniel Quinlan (quinlan@yggdrasil.com) 0 string \177ELF ELF >4 byte 0 invalid class >4 byte 1 32-bit # only for MIPS - in the future, the ABI field of e_flags should be used. >>18 leshort 8 >>>36 lelong &0x20 N32 >>18 leshort 10 >>>36 lelong &0x20 N32 >>18 beshort 8 >>>36 belong &0x20 N32 >>18 beshort 10 >>>36 belong &0x20 N32 >4 byte 2 64-bit >5 byte 0 invalid byte order >5 byte 1 LSB # The official e_machine number for MIPS is now #8, regardless of endianness. # The second number (#10) will be deprecated later. For now, we still # say something if #10 is encountered, but only gory details for #8. >>18 leshort 8 # only for 32-bit >>>4 byte 1 >>>>36 lelong&0xf0000000 0x00000000 MIPS-I >>>>36 lelong&0xf0000000 0x10000000 MIPS-II >>>>36 lelong&0xf0000000 0x20000000 MIPS-III >>>>36 lelong&0xf0000000 0x30000000 MIPS-IV >>>>36 lelong&0xf0000000 0x40000000 MIPS-V >>>>36 lelong&0xf0000000 0x60000000 MIPS32 >>>>36 lelong&0xf0000000 0x70000000 MIPS64 >>>>36 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 lelong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 lelong&0xf0000000 0x00000000 MIPS-I >>>>48 lelong&0xf0000000 0x10000000 MIPS-II >>>>48 lelong&0xf0000000 0x20000000 MIPS-III >>>>48 lelong&0xf0000000 0x30000000 MIPS-IV >>>>48 lelong&0xf0000000 0x40000000 MIPS-V >>>>48 lelong&0xf0000000 0x60000000 MIPS32 >>>>48 lelong&0xf0000000 0x70000000 MIPS64 >>>>48 lelong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 lelong&0xf0000000 0x90000000 MIPS64 rel2 >>16 leshort 0 no file type, >>16 leshort 1 relocatable, >>16 leshort 2 executable, >>16 leshort 3 shared object, # Core handling from Peter Tobias # corrections by Christian 'Dr. Disk' Hechelmann >>16 leshort 4 core file # Core file detection is not reliable. #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) lelong >0 (signal %d), >>16 leshort &0xff00 processor-specific, >>18 leshort 0 no machine, >>18 leshort 1 AT&T WE32100 - invalid byte order, >>18 leshort 2 SPARC - invalid byte order, >>18 leshort 3 Intel 80386, >>18 leshort 4 Motorola >>>36 lelong &0x01000000 68000 - invalid byte order, >>>36 lelong &0x00810000 CPU32 - invalid byte order, >>>36 lelong 0 68020 - invalid byte order, >>18 leshort 5 Motorola 88000 - invalid byte order, >>18 leshort 6 Intel 80486, >>18 leshort 7 Intel 80860, >>18 leshort 8 MIPS, >>18 leshort 9 Amdahl - invalid byte order, >>18 leshort 10 MIPS (deprecated), >>18 leshort 11 RS6000 - invalid byte order, >>18 leshort 15 PA-RISC - invalid byte order, >>>50 leshort 0x0214 2.0 >>>48 leshort &0x0008 (LP64), >>18 leshort 16 nCUBE, >>18 leshort 17 Fujitsu VPP500, >>18 leshort 18 SPARC32PLUS, >>18 leshort 20 PowerPC, >>18 leshort 22 IBM S/390, >>18 leshort 36 NEC V800, >>18 leshort 37 Fujitsu FR20, >>18 leshort 38 TRW RH-32, >>18 leshort 39 Motorola RCE, >>18 leshort 40 ARM, >>18 leshort 41 Alpha, >>18 leshort 0xa390 IBM S/390 (obsolete), >>18 leshort 42 Hitachi SH, >>18 leshort 43 SPARC V9 - invalid byte order, >>18 leshort 44 Siemens Tricore Embedded Processor, >>18 leshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 leshort 46 Hitachi H8/300, >>18 leshort 47 Hitachi H8/300H, >>18 leshort 48 Hitachi H8S, >>18 leshort 49 Hitachi H8/500, >>18 leshort 50 IA-64 (Intel 64 bit architecture) >>18 leshort 51 Stanford MIPS-X, >>18 leshort 52 Motorola Coldfire, >>18 leshort 53 Motorola M68HC12, >>18 leshort 62 AMD x86-64, >>18 leshort 75 Digital VAX, >>18 leshort 97 NatSemi 32k, >>18 leshort 0x9026 Alpha (unofficial), >>20 lelong 0 invalid version >>20 lelong 1 version 1 >>36 lelong 1 MathCoPro/FPU/MAU Required >5 byte 2 MSB # only for MIPS - see comment in little-endian section above. >>18 beshort 8 # only for 32-bit >>>4 byte 1 >>>>36 belong&0xf0000000 0x00000000 MIPS-I >>>>36 belong&0xf0000000 0x10000000 MIPS-II >>>>36 belong&0xf0000000 0x20000000 MIPS-III >>>>36 belong&0xf0000000 0x30000000 MIPS-IV >>>>36 belong&0xf0000000 0x40000000 MIPS-V >>>>36 belong&0xf0000000 0x60000000 MIPS32 >>>>36 belong&0xf0000000 0x70000000 MIPS64 >>>>36 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>36 belong&0xf0000000 0x90000000 MIPS64 rel2 # only for 64-bit >>>4 byte 2 >>>>48 belong&0xf0000000 0x00000000 MIPS-I >>>>48 belong&0xf0000000 0x10000000 MIPS-II >>>>48 belong&0xf0000000 0x20000000 MIPS-III >>>>48 belong&0xf0000000 0x30000000 MIPS-IV >>>>48 belong&0xf0000000 0x40000000 MIPS-V >>>>48 belong&0xf0000000 0x60000000 MIPS32 >>>>48 belong&0xf0000000 0x70000000 MIPS64 >>>>48 belong&0xf0000000 0x80000000 MIPS32 rel2 >>>>48 belong&0xf0000000 0x90000000 MIPS64 rel2 >>16 beshort 0 no file type, >>16 beshort 1 relocatable, >>16 beshort 2 executable, >>16 beshort 3 shared object, >>16 beshort 4 core file, #>>>(0x38+0xcc) string >\0 of '%s' #>>>(0x38+0x10) belong >0 (signal %d), >>16 beshort &0xff00 processor-specific, >>18 beshort 0 no machine, >>18 beshort 1 AT&T WE32100, >>18 beshort 2 SPARC, >>18 beshort 3 Intel 80386 - invalid byte order, >>18 beshort 4 Motorola >>>36 belong &0x01000000 68000, >>>36 belong &0x00810000 CPU32, >>>36 belong 0 68020, >>18 beshort 5 Motorola 88000, >>18 beshort 6 Intel 80486 - invalid byte order, >>18 beshort 7 Intel 80860, >>18 beshort 8 MIPS, >>18 beshort 9 Amdahl, >>18 beshort 10 MIPS (deprecated), >>18 beshort 11 RS6000, >>18 beshort 15 PA-RISC >>>50 beshort 0x0214 2.0 >>>48 beshort &0x0008 (LP64) >>18 beshort 16 nCUBE, >>18 beshort 17 Fujitsu VPP500, >>18 beshort 18 SPARC32PLUS, >>>36 belong&0xffff00 &0x000100 V8+ Required, >>>36 belong&0xffff00 &0x000200 Sun UltraSPARC1 Extensions Required, >>>36 belong&0xffff00 &0x000400 HaL R1 Extensions Required, >>>36 belong&0xffff00 &0x000800 Sun UltraSPARC3 Extensions Required, >>18 beshort 20 PowerPC or cisco 4500, >>18 beshort 21 cisco 7500, >>18 beshort 22 IBM S/390, >>18 beshort 24 cisco SVIP, >>18 beshort 25 cisco 7200, >>18 beshort 36 NEC V800 or cisco 12000, >>18 beshort 37 Fujitsu FR20, >>18 beshort 38 TRW RH-32, >>18 beshort 39 Motorola RCE, >>18 beshort 40 ARM, >>18 beshort 41 Alpha, >>18 beshort 42 Hitachi SH, >>18 beshort 43 SPARC V9, >>18 beshort 44 Siemens Tricore Embedded Processor, >>18 beshort 45 Argonaut RISC Core, Argonaut Technologies Inc., >>18 beshort 46 Hitachi H8/300, >>18 beshort 47 Hitachi H8/300H, >>18 beshort 48 Hitachi H8S, >>18 beshort 49 Hitachi H8/500, >>18 beshort 50 Intel Merced Processor, >>18 beshort 51 Stanford MIPS-X, >>18 beshort 52 Motorola Coldfire, >>18 beshort 53 Motorola M68HC12, >>18 beshort 73 Cray NV1, >>18 beshort 75 Digital VAX, >>18 beshort 97 NatSemi 32k, >>18 beshort 0x9026 Alpha (unofficial), >>18 beshort 0xa390 IBM S/390 (obsolete), >>18 beshort 0xde3d Ubicom32, >>20 belong 0 invalid version >>20 belong 1 version 1 >>36 belong 1 MathCoPro/FPU/MAU Required # Up to now only 0, 1 and 2 are defined; I've seen a file with 0x83, it seemed # like proper ELF, but extracting the string had bad results. >4 byte <0x80 >>8 string >\0 ("%s") >8 string \0 >>7 byte 0 (SYSV) >>7 byte 1 (HP-UX) >>7 byte 2 (NetBSD) >>7 byte 3 (GNU/Linux) >>7 byte 4 (GNU/Hurd) >>7 byte 5 (86Open) >>7 byte 6 (Solaris) >>7 byte 7 (Monterey) >>7 byte 8 (IRIX) >>7 byte 9 (FreeBSD) >>7 byte 10 (Tru64) >>7 byte 11 (Novell Modesto) >>7 byte 12 (OpenBSD) >>7 byte 97 (ARM) >>7 byte 255 (embedded) # XXX - according to Microsoft's spec, at an offset of 0x3c in a # PE-format executable is the offset in the file of the PE header; # unfortunately, that's a little-endian offset, and there's no way # to specify an indirect offset with a specified byte order. # So, for now, we assume the standard MS-DOS stub, which puts the # PE header at 0x80 = 128. # # Required OS version and subsystem version were 4.0 on some NT 3.51 # executables built with Visual C++ 4.0, so it's not clear that # they're interesting. The user version was 0.0, but there's # probably some linker directive to set it. The linker version was # 3.0, except for one ".exe" which had it as 4.20 (same damn linker!). # # many of the compressed formats were extraced from IDARC 1.23 source code # 0 string MZ Microsoft >0x18 leshort <0x40 MS-DOS executable >0 string MZ\0\0\0\0\0\0\0\0\0\0PE\0\0 \b, PE for MS Windows >>&18 leshort&0x2000 >0 (DLL) >>&88 leshort 0 (unknown subsystem) >>&88 leshort 1 (native) >>&88 leshort 2 (GUI) >>&88 leshort 3 (console) >>&88 leshort 7 (POSIX) >>&0 leshort 0x0 unknown processor >>&0 leshort 0x14c Intel 80386 >>&0 leshort 0x166 MIPS R4000 >>&0 leshort 0x184 Alpha >>&0 leshort 0x268 Motorola 68000 >>&0 leshort 0x1f0 PowerPC >>&0 leshort 0x290 PA-RISC >>&18 leshort&0x0100 >0 32-bit >>&18 leshort&0x1000 >0 system file >>&228 lelong >0 \b, Mono/.Net assembly >>&0xf4 search/0x140 \x0\x40\x1\x0 >>>(&0.l+(4)) string MSCF \b, WinHKI CAB self-extracting archive >30 string Copyright\x201989-1990\x20PKWARE\x20Inc. Self-extracting PKZIP archive # Is next line correct? One might expect "Corp." not "Copr." If it is right, add a note to that effect. >30 string PKLITE\x20Copr. Self-extracting PKZIP archive >0x18 leshort >0x3f >>(0x3c.l) string PE\0\0 PE >>>(0x3c.l+25) byte 1 \b32 executable >>>(0x3c.l+25) byte 2 \b32+ executable # hooray, there's a DOS extender using the PE format, with a valid PE # executable inside (which just prints a message and exits if run in win) >>>(0x3c.l+92) leshort <10 >>>>(8.s*16) string 32STUB for MS-DOS, 32rtm DOS extender >>>>(8.s*16) string !32STUB for MS Windows >>>>>(0x3c.l+22) leshort&0x2000 >0 (DLL) >>>>>(0x3c.l+92) leshort 0 (unknown subsystem) >>>>>(0x3c.l+92) leshort 1 (native) >>>>>(0x3c.l+92) leshort 2 (GUI) >>>>>(0x3c.l+92) leshort 3 (console) >>>>>(0x3c.l+92) leshort 7 (POSIX) >>>(0x3c.l+92) leshort 10 (EFI application) >>>(0x3c.l+92) leshort 11 (EFI boot service driver) >>>(0x3c.l+92) leshort 12 (EFI runtime driver) >>>(0x3c.l+92) leshort 13 (XBOX) >>>(0x3c.l+4) leshort 0x0 unknown processor >>>(0x3c.l+4) leshort 0x14c Intel 80386 >>>(0x3c.l+4) leshort 0x166 MIPS R4000 >>>(0x3c.l+4) leshort 0x184 Alpha >>>(0x3c.l+4) leshort 0x268 Motorola 68000 >>>(0x3c.l+4) leshort 0x1f0 PowerPC >>>(0x3c.l+4) leshort 0x290 PA-RISC >>>(0x3c.l+4) leshort 0x200 Intel Itanium >>>(0x3c.l+22) leshort&0x0100 >0 32-bit >>>(0x3c.l+22) leshort&0x1000 >0 system file >>>(0x3c.l+232) lelong >0 Mono/.Net assembly >>>>(0x3c.l+0xf8) string UPX0 \b, UPX compressed >>>>(0x3c.l+0xf8) search/0x140 PEC2 \b, PECompact2 compressed >>>>(0x3c.l+0xf8) search/0x140 UPX2 >>>>>(&0x10.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>(0x3c.l+0xf8) search/0x140 .idata >>>>>(&0xe.l+(-4)) string PK\3\4 \b, ZIP self-extracting archive (Info-Zip) >>>>>(&0xe.l+(-4)) string ZZ0 \b, ZZip self-extracting archive >>>>>(&0xe.l+(-4)) string ZZ1 \b, ZZip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .rsrc >>>>>(&0x0f.l+(-4)) string a\\\4\5 \b, WinHKI self-extracting archive >>>>>(&0x0f.l+(-4)) string Rar! \b, RAR self-extracting archive >>>>>(&0x0f.l+(-4)) search/0x3000 MSCF \b, InstallShield self-extracting archive >>>>>(&0x0f.l+(-4)) search/32 Nullsoft \b, Nullsoft Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .data >>>>>(&0x0f.l) string WEXTRACT \b, MS CAB-Installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .petite\0 \b, Petite compressed >>>>>(0x3c.l+0xf7) byte x >>>>>>(&0x104.l+(-4)) string =!sfx! \b, ACE self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .WISE \b, WISE installer self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .dz\0\0\0 \b, Dzip self-extracting archive >>>>(0x3c.l+0xf8) search/0x140 .reloc >>>>>(&0xe.l+(-4)) search/0x180 PK\3\4 \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 _winzip_ \b, ZIP self-extracting archive (WinZip) >>>>&(0x3c.l+0xf8) search/0x100 SharedD \b, Microsoft Installer self-extracting archive >>>>0x30 string Inno \b, InnoSetup self-extracting archive >>(0x3c.l) string !PE\0\0 MS-DOS executable >>(0x3c.l) string NE \b, NE >>>(0x3c.l+0x36) byte 0 (unknown OS) >>>(0x3c.l+0x36) byte 1 for OS/2 1.x >>>(0x3c.l+0x36) byte 2 for MS Windows 3.x >>>(0x3c.l+0x36) byte 3 for MS-DOS >>>(0x3c.l+0x36) byte >3 (unknown OS) >>>(0x3c.l+0x36) byte 0x81 for MS-DOS, Phar Lap DOS extender >>>(0x3c.l+0x0c) leshort&0x8003 0x8002 (DLL) >>>(0x3c.l+0x0c) leshort&0x8003 0x8001 (driver) >>>&(&0x24.s-1) string ARJSFX \b, ARJ self-extracting archive >>>(0x3c.l+0x70) search/0x80 WinZip(R)\x20Self-Extractor \b, ZIP self-extracting archive (WinZip) >>(0x3c.l) string LX\0\0 \b, LX >>>(0x3c.l+0x0a) leshort <1 (unknown OS) >>>(0x3c.l+0x0a) leshort 1 for OS/2 >>>(0x3c.l+0x0a) leshort 2 for MS Windows >>>(0x3c.l+0x0a) leshort 3 for DOS >>>(0x3c.l+0x0a) leshort >3 (unknown OS) >>>(0x3c.l+0x10) lelong&0x28000 =0x8000 (DLL) >>>(0x3c.l+0x10) lelong&0x20000 >0 (device driver) >>>(0x3c.l+0x10) lelong&0x300 0x300 (GUI) >>>(0x3c.l+0x10) lelong&0x28300 <0x300 (console) >>>(0x3c.l+0x08) leshort 1 i80286 >>>(0x3c.l+0x08) leshort 2 i80386 >>>(0x3c.l+0x08) leshort 3 i80486 >>>(8.s*16) string emx \b, emx >>>>&1 string x "%s" >>>&(&0x54.l-3) string arjsfx \b, ARJ self-extracting archive #------------------------------------------------------------------------------ # bFLT: file(1) magic for BFLT uclinux binary files # # From Philippe De Muyter # # Additional fields added by Craig Heffner # 0 string bFLT BFLT executable >4 belong x version %ld, >4 belong 4 >8 belong x code offset: 0x%.8X, >12 belong x data segment starts at: 0x%.8X, >16 belong x bss segment starts at: 0x%.8X, >20 belong x bss segment ends at: 0x%.8X, >24 belong x stack size: %d bytes, >28 belong x relocation records start at: 0x%.8X, >32 belong x number of reolcation records: %d, >>36 belong&0x1 0x1 ram >>36 belong&0x2 0x2 gotpic >>36 belong&0x4 0x4 gzip >>36 belong&0x8 0x8 gzdata #----------------------------------------------------------------- # MIPS COFF file formats # 0 beshort 0x0160 MIPSEB ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0162 MIPSEL-BE ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6001 MIPSEB-LE ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %d >22 byte x \b.%ld # 0 beshort 0x6201 MIPSEL ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 2 additions # 0 beshort 0x0163 MIPSEB MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0166 MIPSEL-BE MIPS-II ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x6301 MIPSEB-LE MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x6601 MIPSEL MIPS-II ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # MIPS 3 additions # 0 beshort 0x0140 MIPSEB MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x0142 MIPSEL-BE MIPS-III ECOFF executable >20 beshort 0407 (impure) >20 beshort 0410 (swapped) >20 beshort 0413 (paged) >8 belong >0 not stripped >8 belong 0 stripped >22 byte x - version %ld >23 byte x \b.%ld # 0 beshort 0x4001 MIPSEB-LE MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x4201 MIPSEL MIPS-III ECOFF executable >20 beshort 03401 (impure) >20 beshort 04001 (swapped) >20 beshort 05401 (paged) >8 belong >0 not stripped >8 belong 0 stripped >23 byte x - version %ld >22 byte x \b.%ld # 0 beshort 0x180 MIPSEB Ucode 0 beshort 0x182 MIPSEL-BE Ucode # Windows CE package files 0 string MSCE\0\0\0\0 Microsoft WinCE installer >20 lelong 0 \b, architecture-independent >20 lelong 103 \b, Hitachi SH3 >20 lelong 104 \b, Hitachi SH4 >20 lelong 0xA11 \b, StrongARM >20 lelong 4000 \b, MIPS R4000 >20 lelong 10003 \b, Hitachi SH3 >20 lelong 10004 \b, Hitachi SH3E >20 lelong 10005 \b, Hitachi SH4 >20 lelong 70001 \b, ARM 7TDMI >52 leshort 1 \b, 1 file >52 leshort >1 \b, %u files >56 leshort 1 \b, 1 registry entry >56 leshort >1 \b, %u registry entries #------------------------------------------------------------------------------ # Microsoft Xbox executables .xbe (Esa Hyytiä ) 0 string XBEH XBE, Microsoft Xbox executable # probabilistic checks whether signed or not >0x0004 ulelong =0x0 >>&2 ulelong =0x0 >>>&2 ulelong =0x0 \b, not signed >0x0004 ulelong >0 >>&2 ulelong >0 >>>&2 ulelong >0 \b, signed # expect base address of 0x10000 >0x0104 ulelong =0x10000 >>(0x0118-0x0FF60) ulelong&0x80000007 0x80000007 \b, all regions >>(0x0118-0x0FF60) ulelong&0x80000007 !0x80000007 >>>(0x0118-0x0FF60) ulelong >0 (regions: >>>>(0x0118-0x0FF60) ulelong &0x00000001 NA >>>>(0x0118-0x0FF60) ulelong &0x00000002 Japan >>>>(0x0118-0x0FF60) ulelong &0x00000004 Rest_of_World >>>>(0x0118-0x0FF60) ulelong &0x80000000 Manufacturer >>>(0x0118-0x0FF60) ulelong >0 \b) #------------------------------------------------------------------------------ # motorola: file(1) magic for Motorola 68K and 88K binaries # # 68K # 0 beshort 0x0208 mc68k COFF >18 beshort ^00000020 object >18 beshort &00000020 executable >12 belong >0 not stripped >168 string .lowmem Apple toolbox >20 beshort 0407 (impure) >20 beshort 0410 (pure) >20 beshort 0413 (demand paged) >20 beshort 0421 (standalone) 0 beshort 0x0209 mc68k executable (shared) >12 belong >0 not stripped 0 beshort 0x020A mc68k executable (shared demand paged) >12 belong >0 not stripped # # Motorola/UniSoft 68K Binary Compatibility Standard (BCS) # 0 beshort 0x022A 68K BCS executable # # 88K # # Motorola/88Open BCS # 0 beshort 0x022B 88K BCS executable #------------------------------------------------------------------------------ # Sony Playstation executables (Adam Sjoegren ) : 0 string PS-X\x20EXE Sony Playstation executable # Area: >113 string x ("%s") #------------------------------------------------------------------------------ # cisco: file(1) magic for cisco Systems routers # # Most cisco file-formats are covered by the generic elf code # # Microcode files are non-ELF, 0x8501 conflicts with NetBSD/alpha. 0 beshort 0x8501 cisco IOS >0 belong&0xffffff00 0x85011400 microcode >0 belong&0xffffff00 0x8501cb00 experimental microcode >7 string >\0 for "%s" # EST flat binary format (which isn't, but anyway) # From: Mark Brown 0 string ESTFBINR EST flat binary # These are not the binaries themselves, but string references to them # are a strong indication that they exist elsewhere... #0 string /bin/busybox Busybox string reference: "%s"{one-of-many} #0 string /bin/sh Shell string reference: "%s"{one-of-many} ================================================ FILE: src/binwalk-1.0/src/magic/filesystems ================================================ #--------------------File Systems--------------------- # Minix filesystems - Juan Cespedes 0x410 leshort 0x137f Minix filesystem >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 leshort 0x138f Minix filesystem, 30 char names 0x410 leshort 0x2468 Minix filesystem, version 2 0x410 leshort 0x2478 Minix filesystem, version 2, 30 char names 0x410 leshort 0x4d5a Minix filesystem, version 3 0x410 leshort 0x4d6a Minix filesystem, version 3, 30 char names 0x410 beshort 0x137f Minix filesystem (big endian) >0x402 beshort !0 \b, %d zones >0x1e string minix \b, bootable 0x410 beshort 0x138f Minix filesystem (big endian), 30 char names 0x410 beshort 0x2468 Minix filesystem (big endian), version 2 0x410 beshort 0x2478 Minix filesystem (big endian), version 2, 30 char names 0x410 beshort 0x4d5a Minix filesystem (big endian), version 3 0x410 beshort 0x4d6a Minix filesystem (big endian), version 3, 30 char names # YAFFS 0 string \x03\x00\x00\x00\x01\x00\x00\x00\xFF\xFF YAFFS filesystem # EFS2 file system - jojo@utulsa.edu 0 lelong 0x53000000 EFS2 Qualcomm filesystem super block, little endian, >8 string !EFSSuper invalid, >4 leshort &1 NAND >4 leshort ^1 NOR >4 leshort x version 0x%x, >24 lelong x %d blocks, >16 lelong x 0x%x pages per block, >20 lelong x 0x%x bytes per page 0 belong 0x53000000 EFS2 Qualcomm filesystem super block, big endian, >8 string !SSFErepu invalid, >4 beshort &1 NAND >4 beshort ^1 NOR >4 beshort x version 0x%x, >24 belong x %d blocks, >16 belong x 0x%x pages per block, >20 belong x 0x%x bytes per page # TROC file system 0 string TROC TROC filesystem, >4 lelong x %d file entries # PFS file system 0 string PFS/ PFS filesystem, >4 string x version "%s", >14 leshort x %d files # MPFS file system 0 string MPFS MPFS (Microchip) filesystem, >4 byte x version %d. >5 byte x \b%d, >6 leshort x %d file entries # cramfs filesystem - russell@coker.com.au 0 lelong 0x28cd3d45 CramFS filesystem, little endian >4 lelong <0 invalid >4 lelong x size %lu >8 lelong &1 version #2 >8 lelong &2 sorted_dirs >8 lelong &4 hole_support >32 lelong x CRC 0x%x, >36 lelong x edition %lu, >40 lelong <0 invalid >40 lelong x %lu blocks, >44 lelong <0 invalid >44 lelong x %lu files >4 lelong x {jump-to-offset:%lu} >4 lelong x {file-size:%lu} 0 belong 0x28cd3d45 CramFS filesystem, big endian >4 belong <0 invalid >4 belong x size %lu >8 belong &1 version #2 >8 belong &2 sorted_dirs >8 belong &4 hole_support >32 belong x CRC 0x%x, >36 belong x edition %lu, >40 belong <0 invalid >40 belong x %lu blocks, >44 belong <0 invalid >44 belong x %lu files >4 belong x {jump-to-offset:%lu} >4 belong x {file-size:%lu} # JFFS2 file system # If used with binwalk's smart signature feature (on by default, -S to disable) # this signature can potentially lead to missing some JFFS2 file systems if there # are multiple JFFS2 file systems in a target file and there are no other identified # files in between the JFFS2 file systems. This is an unlikely scenario however, and # the below signatures are much improved in terms of readability and accuracy in the # vast majority of real world scenarios. 0 leshort 0x1985 JFFS2 filesystem, little endian{filter-include} >2 leshort !0xE001 >>2 leshort !0xE002 >>>2 leshort !0x2003 >>>>2 leshort !0x2004 >>>>>2 leshort !0x2006 >>>>>>2 leshort !0xE008 >>>>>>>2 leshort !0xE009 \b, invalid >(4.l) leshort !0x1985 >>(4.l+1) leshort !0x1985 >>>(4.l+2) leshort !0x1985 >>>>(4.l+3) leshort !0x1985 >>>>>(4.l) leshort !0xFFFF >>>>>>(4.l+1) leshort !0xFFFF >>>>>>>(4.l+2) leshort !0xFFFF >>>>>>>>(4.l+3) leshort !0xFFFF \b, invalid >4 lelong x {one-of-many}{jump-to-offset:%d} 0 beshort 0x1985 JFFS2 filesystem, big endian{filter-include} >2 beshort !0xE001 >>2 beshort !0xE002 >>>2 beshort !0x2003 >>>>2 beshort !0x2004 >>>>>2 beshort !0x2006 >>>>>>2 beshort !0xE008 >>>>>>>2 beshort !0xE009 \b, invalid >(4.L) beshort !0x1985 >>(4.L+1) beshort !0x1985 >>>(4.L+2) beshort !0x1985 >>>>(4.L+3) beshort !0x1985 >>>>>(4.L) beshort !0xFFFF >>>>>>(4.L+1) beshort !0xFFFF >>>>>>>(4.L+2) beshort !0xFFFF >>>>>>>>(4.L+3) beshort !0xFFFF \b, invalid >4 belong x {one-of-many}{jump-to-offset:%d} # Squashfs, big endian 0 string sqsh Squashfs filesystem, big endian, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >28 beshort 3 >>63 bequad x size: %lld bytes, >28 beshort >3 >>40 bequad x size: %lld bytes, >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs, little endian 0 string hsqs Squashfs filesystem, little endian, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Squashfs with LZMA compression 0 string sqlz Squashfs filesystem, big endian, lzma compression, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs 3.3 LZMA signature 0 string qshs Squashfs filesystem, big endian, lzma signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string tqsh Squashfs filesystem, big endian, DD-WRT signature, >28 beshort >10 invalid >28 beshort <1 invalid >30 beshort >10 invalid >28 beshort x version %d. >30 beshort x \b%d, >28 beshort >3 compression: >>20 beshort 1 \bgzip, >>20 beshort 2 \blzma, >>20 beshort 0 \binvalid, >>20 beshort >4 \binvalid, >28 beshort <3 >>8 belong x size: %d bytes, >>8 belong x {file-size:%d} >28 beshort 3 >>63 bequad x size: %lld bytes, >>63 bequad x {file-size:%lld} >28 beshort >3 >>40 bequad x size: %lld bytes, >>40 bequad x {file-size:%lld} >4 belong x %d inodes, >28 beshort >3 >>12 belong blocksize: %d bytes, >28 beshort <2 >>32 beshort x blocksize: %d bytes, >28 beshort 2 >>51 belong x blocksize: %d bytes, >28 beshort 3 >>51 belong x blocksize: %d bytes, >28 beshort >3 >>12 belong x blocksize: %d bytes, >28 beshort <4 >>39 bedate x created: %s >28 beshort >3 >>8 bedate x created: %s >28 beshort <3 >>8 belong x {jump-to-offset:%d} >28 beshort 3 >>63 bequad x {jump-to-offset:%lld} >28 beshort >3 >>40 bequad x {jump-to-offset:%lld} # Squashfs for DD-WRT 0 string hsqt Squashfs filesystem, little endian, DD-WRT signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # Non-standard Squashfs signature found on some D-Link routers 0 string shsq Squashfs filesystem, little endian, non-standard signature, >28 leshort >10 invalid >28 leshort <1 invalid >30 leshort >10 invalid >28 leshort x version %d. >30 leshort x \b%d, >28 leshort >3 compression: >>20 leshort 1 \bgzip, >>20 leshort 2 \blzma, >>20 leshort 0 \binvalid, >>20 leshort >4 \binvalid, >28 leshort <3 >>8 lelong x size: %d bytes, >>8 lelong x {file-size:%d} >28 leshort 3 >>63 lequad x size: %lld bytes, >>63 lequad x {file-size:%lld} >28 leshort >3 >>40 lequad x size: %lld bytes, >>40 lequad x {file-size:%lld} >4 lelong x %d inodes, >28 leshort >3 >>12 lelong blocksize: %d bytes, >28 leshort <2 >>32 leshort x blocksize: %d bytes, >28 leshort 2 >>51 lelong x blocksize: %d bytes, >28 leshort 3 >>51 lelong x blocksize: %d bytes, >28 leshort >3 >>12 lelong x blocksize: %d bytes, >28 leshort <4 >>39 ledate x created: %s >28 leshort >3 >>8 ledate x created: %s >28 leshort <3 >>8 lelong x {jump-to-offset:%d} >28 leshort 3 >>63 lequad x {jump-to-offset:%lld} >28 leshort >3 >>40 lequad x {jump-to-offset:%lld} # ext2/ext3 filesystems - Andreas Dilger # ext4 filesystem - Eric Sandeen # volume label and UUID Russell Coker # http://etbe.coker.com.au/2008/07/08/label-vs-uuid-vs-device/ 0 leshort 0xEF53 Linux EXT filesystem,{filter-include}{offset-adjust:-0x438} >2 leshort >4 invalid state >2 leshort 3 invalid state >2 leshort <0 invalid state >4 leshort >3 invalid error behavior >4 leshort <0 invalid error behavior >4 lelong >1 invalid major revision >4 lelong <0 invalid major revision >4 lelong x rev %d >6 leshort x \b.%d # No journal? ext2 >36 lelong ^0x0000004 ext2 filesystem data >>2 leshort ^0x0000001 (mounted or unclean) # Has a journal? ext3 or ext4 >36 lelong &0x0000004 # and small INCOMPAT? >>40 lelong <0x0000040 # and small RO_COMPAT? >>>44 lelong <0x0000008 ext3 filesystem data # else large RO_COMPAT? >>>44 lelong >0x0000007 ext4 filesystem data # else large INCOMPAT? >>40 lelong >0x000003f ext4 filesystem data >48 belong x \b, UUID=%08x >52 beshort x \b-%04x >54 beshort x \b-%04x >56 beshort x \b-%04x >58 belong x \b-%08x >60 beshort x \b%04x >64 string >0 \b, volume name "%s" #romfs filesystems - Juan Cespedes 0 string -rom1fs-\0 romfs filesystem, version 1 >8 belong >10000000 invalid >8 belong x size: %d bytes, >16 string x {file-name:%s} >16 string x named "%s" >8 belong x {file-size:%d} >8 belong x {jump-to-offset:%d} # Wind River MemFS file system, found in some VxWorks devices 0 string owowowowowowowowowowowowowowow Wind River management filesystem, >30 string !ow invalid, >32 belong 1 compressed, >32 belong 2 plain text, >36 belong x %d files # netboot image - Juan Cespedes 0 lelong 0x1b031336L Netboot image, >4 lelong&0xFFFFFF00 0 >>4 lelong&0x100 0x000 mode 2 >>4 lelong&0x100 0x100 mode 3 >4 lelong&0xFFFFFF00 !0 unknown mode (invalid) ================================================ FILE: src/binwalk-1.0/src/magic/firmware ================================================ #--------------------------Firmware Formats--------------------------- # uImage file # From: Craig Heffner, U-Boot image.h header definitions file 0 belong 0x27051956 uImage header, header size: 64 bytes, >4 belong x header CRC: 0x%X, >8 bedate x created: %s, >12 belong x image size: %d bytes, >16 belong x Data Address: 0x%X, >20 belong x Entry Point: 0x%X, >24 belong x data CRC: 0x%X, #>28 byte x OS type: %d, >28 byte 0 OS: invalid OS, >28 byte 1 OS: OpenBSD, >28 byte 2 OS: NetBSD, >28 byte 3 OS: FreeBSD, >28 byte 4 OS: 4.4BSD, >28 byte 5 OS: Linux, >28 byte 6 OS: SVR4, >28 byte 7 OS: Esix, >28 byte 8 OS: Solaris, >28 byte 9 OS: Irix, >28 byte 10 OS: SCO, >28 byte 11 OS: Dell, >28 byte 12 OS: NCR, >28 byte 13 OS: LynxOS, >28 byte 14 OS: VxWorks, >28 byte 15 OS: pSOS, >28 byte 16 OS: QNX, >28 byte 17 OS: Firmware, >28 byte 18 OS: RTEMS, >28 byte 19 OS: ARTOS, >28 byte 20 OS: Unity OS, #>29 byte x CPU arch: %d, >29 byte 0 CPU: invalid OS, >29 byte 1 CPU: Alpha, >29 byte 2 CPU: ARM, >29 byte 3 CPU: Intel x86, >29 byte 4 CPU: IA64, >29 byte 5 CPU: MIPS, >29 byte 6 CPU: MIPS 64 bit, >29 byte 7 CPU: PowerPC, >29 byte 8 CPU: IBM S390, >29 byte 9 CPU: SuperH, >29 byte 10 CPU: Sparc, >29 byte 11 CPU: Sparc 64 bit, >29 byte 12 CPU: M68K, >29 byte 13 CPU: Nios-32, >29 byte 14 CPU: MicroBlaze, >29 byte 15 CPU: Nios-II, >29 byte 16 CPU: Blackfin, >29 byte 17 CPU: AVR, >29 byte 18 CPU: STMicroelectronics ST200, #>30 byte x image type: %d, >30 byte 0 image type: invalid Image, >30 byte 1 image type: Standalone Program, >30 byte 2 image type: OS Kernel Image, >30 byte 3 image type: RAMDisk Image, >30 byte 4 image type: Multi-File Image, >30 byte 5 image type: Firmware Image, >30 byte 6 image type: Script file, >30 byte 7 image type: Filesystem Image, >30 byte 8 image type: Binary Flat Device Tree Blob #>31 byte x compression type: %d, >31 byte 0 compression type: none, >31 byte 1 compression type: gzip, >31 byte 2 compression type: bzip2, >31 byte 3 compression type: lzma, >32 string x image name: "%s" #IMG0 header, found in VxWorks-based Mercury router firmware 0 string IMG0 IMG0 (VxWorks) header, >4 belong x size: %d #Mediatek bootloader signature #From xp-dev.com 0 string BOOTLOADER! Mediatek bootloader #CSYS header formats 0 string CSYS\x00 CSYS header, little endian, >8 lelong x size: %d 0 string CSYS\x80 CSYS header, big endian, >8 belong x size: %d # wrgg firmware image 0 string wrgg02 WRGG firmware header, >6 string x name: "%s", >48 string x root device: "%s" # trx image file 0 string HDR0 TRX firmware header, little endian, header size: 28 bytes, >4 lelong x image size: %d bytes, >8 lelong x CRC32: 0x%X >12 lelong x flags/version: 0x%X 0 string 0RDH TRX firmware header, big endian, header size: 28 bytes, >4 belong x image size: %d bytes, >8 belong x CRC32: 0x%X >12 belong x flags/version: 0x%X # Ubicom firmware image 0 belong 0xFA320080 Ubicom firmware header, >12 belong x checksum: 0x%X, >24 belong x image size: %d # The ROME bootloader is used by several RealTek-based products. # Unfortunately, the magic bytes are specific to each product, so # separate signatures must be created for each one. # Netgear KWGR614 ROME image 0 string G614 Realtek firmware header (ROME bootloader), >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # Linksys WRT54GX ROME image 0 belong 0x59a0e842 Realtek firmware header (ROME bootloader) >4 beshort 0xd92f image type: KFS, >4 beshort 0xb162 image type: RDIR, >4 beshort 0xea43 image type: BOOT, >4 beshort 0x8dc9 image type: RUN, >4 beshort 0x2a05 image type: CCFG, >4 beshort 0x6ce8 image type: DCFG, >4 beshort 0xc371 image type: LOG, >6 byte x header version: %d, #month >10 byte x created: %d/ #day >12 byte x \b%d/ #year >8 beshort x \b%d, >16 belong x image size: %d bytes, >22 byte x body checksum: 0x%X, >23 byte x header checksum: 0x%X # PackImg tag, somtimes used as a delimiter between the kernel and rootfs in firmware images. 0 string --PaCkImGs-- PackImg section delimiter tag, >16 lelong x little endian size: %d bytes; >16 belong x big endian size: %d bytes #------------------------------------------------------------------------------ # Broadcom header format # 0 string BCRM Broadcom header, >4 lelong x number of sections: %d, >>8 lelong 18 first section type: flash >>8 lelong 19 first section type: disk >>8 lelong 21 first section type: tag # Berkeley Lab Checkpoint Restart (BLCR) checkpoint context files # http://ftg.lbl.gov/checkpoint 0 string Ck0\0\0R\0\0\0 BLCR >16 lelong 1 x86 >16 lelong 3 alpha >16 lelong 5 x86-64 >16 lelong 7 ARM >8 lelong x context data (little endian, version %d) 0 string \0\0\0C\0\0\0R BLCR >16 belong 2 SPARC >16 belong 4 ppc >16 belong 6 ppc64 >16 belong 7 ARMEB >16 belong 8 SPARC64 >8 belong x context data (big endian, version %d) # Aculab VoIP firmware # From: Mark Brown 0 string VoIP\x20Startup\x20and Aculab VoIP firmware >35 string x format "%s" #------------------------------------------------------------------------------ # HP LaserJet 1000 series downloadable firmware file 0 string \xbe\xefABCDEFGH HP LaserJet 1000 series downloadable firmware # From Albert Cahalan # really le32 operation,destination,payloadsize (but quite predictable) # 01 00 00 00 00 00 00 c0 00 02 00 00 0 string \1\0\0\0\0\0\0\300\0\2\0\0 Marvell Libertas firmware #--------------------------------------------------------------------------- # The following entries have been tested by Duncan Laurie (a # lead Sun/Cobalt developer) who agrees that they are good and worthy of # inclusion. # Boot ROM images for Sun/Cobalt Linux server appliances 0 string Cobalt\x20Networks\x20Inc.\nFirmware\x20v Paged COBALT boot rom >38 string x V%.4s # New format for Sun/Cobalt boot ROMs is annoying, it stores the version code # at the very end where file(1) can't get it. 0 string CRfs COBALT boot rom data (Flat boot rom or file system) # # Motorola S-Records, from Gerd Truschinski 0 string S0 Motorola S-Record; binary data in text format # -------------------------------- # Microsoft Xbox data file formats 0 string XIP0 XIP, Microsoft Xbox data 0 string XTF0 XTF, Microsoft Xbox data #Windows CE 0 string CECE Windows CE RTOS{offset-adjust:-64} # -------------------------------- # ZynOS ROM header format # From openwrt zynos.h. 0 string SIG ZynOS header, header size: 48 bytes,{offset-adjust:-6} #>0 belong x load address 0x%X, >3 byte <0x7F rom image type: >>3 byte <1 invalid, >>3 byte >7 invalid, >>3 byte 1 ROMIMG, >>3 byte 2 ROMBOOT, >>3 byte 3 BOOTEXT, >>3 byte 4 ROMBIN, >>3 byte 5 ROMDIR, >>3 byte 6 6, >>3 byte 7 ROMMAP, >3 byte >0x7F ram image type: >>3 byte >0x82 invalid, >>3 byte 0x80 RAM, >>3 byte 0x81 RAMCODE, >>3 byte 0x82 RAMBOOT, >4 belong >0x40000000 invalid >4 belong <0 invalid >4 belong 0 invalid >4 belong x uncompressed size: %d, >8 belong >0x40000000 invalid >8 belong <0 invalid >8 belong 0 invalid >8 belong x compressed size: %d, >14 beshort x uncompressed checksum: 0x%X, >16 beshort x compressed checksum: 0x%X, >12 byte x flags: 0x%X, >12 byte &0x40 uncompressed checksum is valid, >12 byte &0x80 the binary is compressed, >>12 byte &0x20 compressed checksum is valid, >35 belong x memory map table address: 0x%X # Firmware header used by some VxWorks-based Cisco products 0 string CI032.00 Cisco VxWorks firmware header, >8 lelong >1024 invalid >8 lelong <0 invalid >8 lelong x header size: %d bytes, >32 lelong >1024 invalid >32 lelong <0 invalid >32 lelong x number of files: %d, >48 lelong <0 invalid >48 lelong x image size: %d, >64 string x firmware version: "%s" # Firmware header used by some TV's 0 string FNIB ZBOOT firmware header, header size: 32 bytes, >8 lelong x load address: 0x%.8X, >12 lelong x start address: 0x%.8X, >16 lelong x checksum: 0x%.8X, >20 lelong x version: 0x%.8X, >24 lelong <1 invalid >24 lelong x image size: %d bytes # Firmware header used by several D-Link routers (and probably others) 0 string \x5e\xa3\xa4\x17 DLOB firmware header, >(7.b+12) string !\x5e\xa3\xa4\x17 invalid, #>>12 string x %s, >(7.b+40) string x boot partition: "%s" # TP-Link firmware header structure; thanks to Jonathan McGowan for reversing and documenting this format 0 string TP-LINK\x20Technologies TP-Link firmware header,{offset-adjust:-4} #>-4 lelong x header version: %d, >0x94 beshort x firmware version: %d. >0x96 beshort x \b%d. >0x98 beshort x \b%d, >0x18 string x image version: "%s", #>0x74 belong x image size: %d bytes, >0x3C belong x product ID: 0x%X, >0x40 belong x product version: %d, >0x70 belong x kernel load address: 0x%X, >0x74 belong x kernel entry point: 0x%X, >0x7C belong x kernel offset: %d, >0x80 belong x kernel length: %d, >0x84 belong x rootfs offset: %d, >0x88 belong x rootfs length: %d, >0x8C belong x bootloader offset: %d, >0x90 belong x bootloader length: %d ================================================ FILE: src/binwalk-1.0/src/magic/images ================================================ # Tag Image File Format, from Daniel Quinlan (quinlan@yggdrasil.com) # The second word of TIFF files is the TIFF version number, 42, which has # never changed. The TIFF specification recommends testing for it. 0 string MM\x00\x2a TIFF image data, big-endian 0 string II\x2a\x00 TIFF image data, little-endian # PNG [Portable Network Graphics, or "PNG's Not GIF"] images # (Greg Roelofs, newt@uchicago.edu) # (Albert Cahalan, acahalan@cs.uml.edu) # # 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ... # 0 string \x89PNG\x0d\x0a\x1a\x0a PNG image >16 belong x \b, %ld x >20 belong x %ld, >24 byte x %d-bit >25 byte 0 grayscale, >25 byte 2 \b/color RGB, >25 byte 3 colormap, >25 byte 4 gray+alpha, >25 byte 6 \b/color RGBA, #>26 byte 0 deflate/32K, >28 byte 0 non-interlaced >28 byte 1 interlaced # GIF 0 string GIF8 GIF image data >4 string 7a \b, version 8"%s", >4 string 9a \b, version 8"%s", >6 leshort >0 %hd x >8 leshort >0 %hd #>10 byte &0x80 color mapped, #>10 byte&0x07 =0x00 2 colors #>10 byte&0x07 =0x01 4 colors #>10 byte&0x07 =0x02 8 colors #>10 byte&0x07 =0x03 16 colors #>10 byte&0x07 =0x04 32 colors #>10 byte&0x07 =0x05 64 colors #>10 byte&0x07 =0x06 128 colors #>10 byte&0x07 =0x07 256 colors # PC bitmaps (OS/2, Windows BMP files) (Greg Roelofs, newt@uchicago.edu) 0 string BM >14 leshort 12 PC bitmap, OS/2 1.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 64 PC bitmap, OS/2 2.x format >>18 leshort x \b, %d x >>20 leshort x %d >14 leshort 40 PC bitmap, Windows 3.x format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d >14 leshort 128 PC bitmap, Windows NT/2000 format >>18 lelong x \b, %d x >>22 lelong x %d x >>28 leshort x %d #------------------------------------------------------------------------------ # JPEG images # SunOS 5.5.1 had # # 0 string \377\330\377\340 JPEG file # 0 string \377\330\377\356 JPG file # # both of which turn into "JPEG image data" here. # 0 beshort 0xffd8 JPEG image data >6 string JFIF \b, JFIF standard # The following added by Erik Rossen 1999-09-06 # in a vain attempt to add image size reporting for JFIF. Note that these # tests are not fool-proof since some perfectly valid JPEGs are currently # impossible to specify in magic(4) format. # First, a little JFIF version info: >>11 byte x \b %d. >>12 byte x \b%02d # Next, the resolution or aspect ratio of the image: #>>13 byte 0 \b, aspect ratio #>>13 byte 1 \b, resolution (DPI) #>>13 byte 2 \b, resolution (DPCM) #>>4 beshort x \b, segment length %d # Next, show thumbnail info, if it exists: >>18 byte !0 \b, thumbnail %dx >>>19 byte x \b%d # EXIF moved down here to avoid reporting a bogus version number, # and EXIF version number printing added. # - Patrik R=E5dman >6 string Exif \b, EXIF standard # Look for EXIF IFD offset in IFD 0, and then look for EXIF version tag in EXIF IFD. # All possible combinations of entries have to be enumerated, since no looping # is possible. And both endians are possible... # The combinations included below are from real-world JPEGs. # Little-endian >>12 string II # IFD 0 Entry #5: >>>70 leshort 0x8769 # EXIF IFD Entry #1: >>>>(78.l+14) leshort 0x9000 >>>>>(78.l+23) byte x %c >>>>>(78.l+24) byte x \b.%c >>>>>(78.l+25) byte !0x30 \b%c # IFD 0 Entry #9: >>>118 leshort 0x8769 # EXIF IFD Entry #3: >>>>(126.l+38) leshort 0x9000 >>>>>(126.l+47) byte x %c >>>>>(126.l+48) byte x \b.%c >>>>>(126.l+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 leshort 0x8769 # EXIF IFD Entry #3: >>>>(138.l+38) leshort 0x9000 >>>>>(138.l+47) byte x %c >>>>>(138.l+48) byte x \b.%c >>>>>(138.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(138.l+50) leshort 0x9000 >>>>>(138.l+59) byte x %c >>>>>(138.l+60) byte x \b.%c >>>>>(138.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.l+62) leshort 0x9000 >>>>>(138.l+71) byte x %c >>>>>(138.l+72) byte x \b.%c >>>>>(138.l+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 leshort 0x8769 # EXIF IFD Entry #3: >>>>(150.l+38) leshort 0x9000 >>>>>(150.l+47) byte x %c >>>>>(150.l+48) byte x \b.%c >>>>>(150.l+49) byte !0x30 \b%c # EXIF IFD Entry #4: >>>>(150.l+50) leshort 0x9000 >>>>>(150.l+59) byte x %c >>>>>(150.l+60) byte x \b.%c >>>>>(150.l+61) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(150.l+62) leshort 0x9000 >>>>>(150.l+71) byte x %c >>>>>(150.l+72) byte x \b.%c >>>>>(150.l+73) byte !0x30 \b%c # Big-endian >>12 string MM # IFD 0 Entry #9: >>>118 beshort 0x8769 # EXIF IFD Entry #1: >>>>(126.L+14) beshort 0x9000 >>>>>(126.L+23) byte x %c >>>>>(126.L+24) byte x \b.%c >>>>>(126.L+25) byte !0x30 \b%c # EXIF IFD Entry #3: >>>>(126.L+38) beshort 0x9000 >>>>>(126.L+47) byte x %c >>>>>(126.L+48) byte x \b.%c >>>>>(126.L+49) byte !0x30 \b%c # IFD 0 Entry #10 >>>130 beshort 0x8769 # EXIF IFD Entry #3: >>>>(138.L+38) beshort 0x9000 >>>>>(138.L+47) byte x %c >>>>>(138.L+48) byte x \b.%c >>>>>(138.L+49) byte !0x30 \b%c # EXIF IFD Entry #5: >>>>(138.L+62) beshort 0x9000 >>>>>(138.L+71) byte x %c >>>>>(138.L+72) byte x \b.%c >>>>>(138.L+73) byte !0x30 \b%c # IFD 0 Entry #11 >>>142 beshort 0x8769 # EXIF IFD Entry #4: >>>>(150.L+50) beshort 0x9000 >>>>>(150.L+59) byte x %c >>>>>(150.L+60) byte x \b.%c >>>>>(150.L+61) byte !0x30 \b%c # Here things get sticky. We can do ONE MORE marker segment with # indirect addressing, and that's all. It would be great if we could # do pointer arithemetic like in an assembler language. Christos? # And if there was some sort of looping construct to do searches, plus a few # named accumulators, it would be even more effective... # At least we can show a comment if no other segments got inserted before: >(4.S+5) byte 0xFE >>(4.S+8) string >\0 \b, comment: "%s" # FIXME: When we can do non-byte counted strings, we can use that to get # the string's count, and fix Debian bug #283760 #>(4.S+5) byte 0xFE \b, comment #>>(4.S+6) beshort x \b length=%d #>>(4.S+8) string >\0 \b, "%s" # Or, we can show the encoding type (I've included only the three most common) # and image dimensions if we are lucky and the SOFn (image segment) is here: >(4.S+5) byte 0xC0 \b, baseline >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC1 \b, extended sequential >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d >(4.S+5) byte 0xC2 \b, progressive >>(4.S+6) byte x \b, precision %d >>(4.S+7) beshort x \b, %dx >>(4.S+9) beshort x \b%d # I've commented-out quantisation table reporting. I doubt anyone cares yet. #>(4.S+5) byte 0xDB \b, quantisation table #>>(4.S+6) beshort x \b length=%d #>14 beshort x \b, %d x #>16 beshort x \b %d ================================================ FILE: src/binwalk-1.0/src/magic/kernels ================================================ #-------------------------Kernels------------------------------------- # Linux kernel boot images, from Albert Cahalan # and others such as Axel Kohlmeyer # and Nicolás Lichtmaier # All known start with: b8 c0 07 8e d8 b8 00 90 8e c0 b9 00 01 29 f6 29 0 string \xb8\xc0\x07\x8e\xd8\xb8\x00\x90\x8e\xc0\xb9\x00\x01\x29\xf6\x29 Linux kernel boot image >514 string !HdrS (invalid) # Finds and prints Linux kernel strings in raw Linux kernels (output like uname -a). # Commonly found in decompressed embedded kernel binaries. 0 string Linux\ version\ Linux kernel version >14 byte 0 invalid >14 byte !0 >>14 string x "%s >>45 string x \b%s >>76 string x \b%s >>107 string x \b%s" ================================================ FILE: src/binwalk-1.0/src/magic/lzma ================================================ # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5D # ------------------------------------------------------------------ 0 string \x5D\x00\x00 LZMA compressed data, properties: 0x5D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x01 # ------------------------------------------------------------------ 0 string \x01\x00\x00 LZMA compressed data, properties: 0x01, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x02 # ------------------------------------------------------------------ 0 string \x02\x00\x00 LZMA compressed data, properties: 0x02, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x03 # ------------------------------------------------------------------ 0 string \x03\x00\x00 LZMA compressed data, properties: 0x03, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x04 # ------------------------------------------------------------------ 0 string \x04\x00\x00 LZMA compressed data, properties: 0x04, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x09 # ------------------------------------------------------------------ 0 string \x09\x00\x00 LZMA compressed data, properties: 0x09, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0A # ------------------------------------------------------------------ 0 string \x0A\x00\x00 LZMA compressed data, properties: 0x0A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0B # ------------------------------------------------------------------ 0 string \x0B\x00\x00 LZMA compressed data, properties: 0x0B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x0C # ------------------------------------------------------------------ 0 string \x0C\x00\x00 LZMA compressed data, properties: 0x0C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x12 # ------------------------------------------------------------------ 0 string \x12\x00\x00 LZMA compressed data, properties: 0x12, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x13 # ------------------------------------------------------------------ 0 string \x13\x00\x00 LZMA compressed data, properties: 0x13, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x14 # ------------------------------------------------------------------ 0 string \x14\x00\x00 LZMA compressed data, properties: 0x14, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1B # ------------------------------------------------------------------ 0 string \x1B\x00\x00 LZMA compressed data, properties: 0x1B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x1C # ------------------------------------------------------------------ 0 string \x1C\x00\x00 LZMA compressed data, properties: 0x1C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x24 # ------------------------------------------------------------------ 0 string \x24\x00\x00 LZMA compressed data, properties: 0x24, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2D # ------------------------------------------------------------------ 0 string \x2D\x00\x00 LZMA compressed data, properties: 0x2D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2E # ------------------------------------------------------------------ 0 string \x2E\x00\x00 LZMA compressed data, properties: 0x2E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x2F # ------------------------------------------------------------------ 0 string \x2F\x00\x00 LZMA compressed data, properties: 0x2F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x30 # ------------------------------------------------------------------ 0 string \x30\x00\x00 LZMA compressed data, properties: 0x30, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x31 # ------------------------------------------------------------------ 0 string \x31\x00\x00 LZMA compressed data, properties: 0x31, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x36 # ------------------------------------------------------------------ 0 string \x36\x00\x00 LZMA compressed data, properties: 0x36, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x37 # ------------------------------------------------------------------ 0 string \x37\x00\x00 LZMA compressed data, properties: 0x37, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x38 # ------------------------------------------------------------------ 0 string \x38\x00\x00 LZMA compressed data, properties: 0x38, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x39 # ------------------------------------------------------------------ 0 string \x39\x00\x00 LZMA compressed data, properties: 0x39, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x3F # ------------------------------------------------------------------ 0 string \x3F\x00\x00 LZMA compressed data, properties: 0x3F, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x40 # ------------------------------------------------------------------ 0 string \x40\x00\x00 LZMA compressed data, properties: 0x40, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x41 # ------------------------------------------------------------------ 0 string \x41\x00\x00 LZMA compressed data, properties: 0x41, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x48 # ------------------------------------------------------------------ 0 string \x48\x00\x00 LZMA compressed data, properties: 0x48, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x49 # ------------------------------------------------------------------ 0 string \x49\x00\x00 LZMA compressed data, properties: 0x49, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x51 # ------------------------------------------------------------------ 0 string \x51\x00\x00 LZMA compressed data, properties: 0x51, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5A # ------------------------------------------------------------------ 0 string \x5A\x00\x00 LZMA compressed data, properties: 0x5A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5B # ------------------------------------------------------------------ 0 string \x5B\x00\x00 LZMA compressed data, properties: 0x5B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5C # ------------------------------------------------------------------ 0 string \x5C\x00\x00 LZMA compressed data, properties: 0x5C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x5E # ------------------------------------------------------------------ 0 string \x5E\x00\x00 LZMA compressed data, properties: 0x5E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x63 # ------------------------------------------------------------------ 0 string \x63\x00\x00 LZMA compressed data, properties: 0x63, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x64 # ------------------------------------------------------------------ 0 string \x64\x00\x00 LZMA compressed data, properties: 0x64, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x65 # ------------------------------------------------------------------ 0 string \x65\x00\x00 LZMA compressed data, properties: 0x65, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x66 # ------------------------------------------------------------------ 0 string \x66\x00\x00 LZMA compressed data, properties: 0x66, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6C # ------------------------------------------------------------------ 0 string \x6C\x00\x00 LZMA compressed data, properties: 0x6C, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6D # ------------------------------------------------------------------ 0 string \x6D\x00\x00 LZMA compressed data, properties: 0x6D, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x6E # ------------------------------------------------------------------ 0 string \x6E\x00\x00 LZMA compressed data, properties: 0x6E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x75 # ------------------------------------------------------------------ 0 string \x75\x00\x00 LZMA compressed data, properties: 0x75, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x76 # ------------------------------------------------------------------ 0 string \x76\x00\x00 LZMA compressed data, properties: 0x76, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x7E # ------------------------------------------------------------------ 0 string \x7E\x00\x00 LZMA compressed data, properties: 0x7E, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x87 # ------------------------------------------------------------------ 0 string \x87\x00\x00 LZMA compressed data, properties: 0x87, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x88 # ------------------------------------------------------------------ 0 string \x88\x00\x00 LZMA compressed data, properties: 0x88, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x89 # ------------------------------------------------------------------ 0 string \x89\x00\x00 LZMA compressed data, properties: 0x89, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8A # ------------------------------------------------------------------ 0 string \x8A\x00\x00 LZMA compressed data, properties: 0x8A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x8B # ------------------------------------------------------------------ 0 string \x8B\x00\x00 LZMA compressed data, properties: 0x8B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x90 # ------------------------------------------------------------------ 0 string \x90\x00\x00 LZMA compressed data, properties: 0x90, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x91 # ------------------------------------------------------------------ 0 string \x91\x00\x00 LZMA compressed data, properties: 0x91, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x92 # ------------------------------------------------------------------ 0 string \x92\x00\x00 LZMA compressed data, properties: 0x92, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x93 # ------------------------------------------------------------------ 0 string \x93\x00\x00 LZMA compressed data, properties: 0x93, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x99 # ------------------------------------------------------------------ 0 string \x99\x00\x00 LZMA compressed data, properties: 0x99, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9A # ------------------------------------------------------------------ 0 string \x9A\x00\x00 LZMA compressed data, properties: 0x9A, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0x9B # ------------------------------------------------------------------ 0 string \x9B\x00\x00 LZMA compressed data, properties: 0x9B, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA2 # ------------------------------------------------------------------ 0 string \xA2\x00\x00 LZMA compressed data, properties: 0xA2, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xA3 # ------------------------------------------------------------------ 0 string \xA3\x00\x00 LZMA compressed data, properties: 0xA3, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xAB # ------------------------------------------------------------------ 0 string \xAB\x00\x00 LZMA compressed data, properties: 0xAB, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB4 # ------------------------------------------------------------------ 0 string \xB4\x00\x00 LZMA compressed data, properties: 0xB4, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB5 # ------------------------------------------------------------------ 0 string \xB5\x00\x00 LZMA compressed data, properties: 0xB5, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB6 # ------------------------------------------------------------------ 0 string \xB6\x00\x00 LZMA compressed data, properties: 0xB6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB7 # ------------------------------------------------------------------ 0 string \xB7\x00\x00 LZMA compressed data, properties: 0xB7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xB8 # ------------------------------------------------------------------ 0 string \xB8\x00\x00 LZMA compressed data, properties: 0xB8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBD # ------------------------------------------------------------------ 0 string \xBD\x00\x00 LZMA compressed data, properties: 0xBD, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBE # ------------------------------------------------------------------ 0 string \xBE\x00\x00 LZMA compressed data, properties: 0xBE, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xBF # ------------------------------------------------------------------ 0 string \xBF\x00\x00 LZMA compressed data, properties: 0xBF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC0 # ------------------------------------------------------------------ 0 string \xC0\x00\x00 LZMA compressed data, properties: 0xC0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC6 # ------------------------------------------------------------------ 0 string \xC6\x00\x00 LZMA compressed data, properties: 0xC6, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC7 # ------------------------------------------------------------------ 0 string \xC7\x00\x00 LZMA compressed data, properties: 0xC7, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xC8 # ------------------------------------------------------------------ 0 string \xC8\x00\x00 LZMA compressed data, properties: 0xC8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xCF # ------------------------------------------------------------------ 0 string \xCF\x00\x00 LZMA compressed data, properties: 0xCF, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD0 # ------------------------------------------------------------------ 0 string \xD0\x00\x00 LZMA compressed data, properties: 0xD0, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes # ------------------------------------------------------------------ # Signature for LZMA compressed data with valid properties byte 0xD8 # ------------------------------------------------------------------ 0 string \xD8\x00\x00 LZMA compressed data, properties: 0xD8, # These are all the valid dictionary sizes supported by LZMA utils. >1 lelong !65536 >>1 lelong !131072 >>>1 lelong !262144 >>>>1 lelong !524288 >>>>>1 lelong !1048576 >>>>>>1 lelong !2097152 >>>>>>>1 lelong !4194304 >>>>>>>>1 lelong !8388608 >>>>>>>>>1 lelong !16777216 >>>>>>>>>>1 lelong !33554432 invalid >1 lelong x dictionary size: %d bytes, # Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely. >5 lequad <1 invalid >5 lequad >0x40000000 invalid # These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely. # Since most false positives are the result of repeating sequences of bytes (such as executable instructions), # marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives. >1 lelong 65536 >>5 lequad 65536 invalid >1 lelong 131072 >>5 lequad 131072 invalid >1 lelong 262144 >>5 lequad 262144 invalid >1 lelong 524288 >>5 lequad 524288 invalid >1 lelong 1048576 >>5 lequad 1048576 invalid >1 lelong 2097152 >>5 lequad 2097152 invalid >1 lelong 4194304 >>5 lequad 4194304 invalid >1 lelong 8388608 >>5 lequad 8388608 invalid >1 lelong 16777216 >>5 lequad 16777216 invalid >1 lelong 33554432 >>5 lequad 33554432 invalid >5 lequad x uncompressed size: %lld bytes ================================================ FILE: src/binwalk-1.0/src/magic/sql ================================================ #------------------------------------------------------------------------------ # $File: sql,v 1.6 2009/09/19 16:28:12 christos Exp $ # sql: file(1) magic for SQL files # # From: "Marty Leisner" # Recognize some MySQL files. # 0 beshort 0xfe01 MySQL table definition file >2 string <1 invalid >2 string >\11 invalid >2 byte x Version %d 0 string \xfe\xfe\x03 MySQL MISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x07 MySQL MISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x05 MySQL ISAM index file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \xfe\xfe\x06 MySQL ISAM compressed data file >3 string <1 invalid >3 string >\11 invalid >3 byte x Version %d 0 string \376bin MySQL replication log #------------------------------------------------------------------------------ # iRiver H Series database file # From Ken Guest # As observed from iRivNavi.iDB and unencoded firmware # 0 string iRivDB iRiver Database file >11 string >\0 Version "%s" >39 string iHP-100 [H Series] #------------------------------------------------------------------------------ # SQLite database files # Ken Guest , Ty Sarna, Zack Weinberg # # Version 1 used GDBM internally; its files cannot be distinguished # from other GDBM files. # # Version 2 used this format: 0 string **\x20This\x20file\x20contains\x20an\x20SQLite SQLite 2.x database # Version 3 of SQLite allows applications to embed their own "user version" # number in the database. Detect this and distinguish those files. 0 string SQLite\x20format\x203 >60 string _MTN Monotone source repository >60 belong !0 SQLite 3.x database, user version %u >60 belong 0 SQLite 3.x database ================================================ FILE: src/binwalk-1.0/src/setup.py ================================================ #!/usr/bin/env python from os import listdir, path from distutils.core import setup # Generate a new magic file from the files in the magic directory print "generating binwalk magic file" magic_files = listdir("magic") magic_files.sort() fd = open("binwalk/magic/binwalk", "wb") for magic in magic_files: fpath = path.join("magic", magic) if path.isfile(fpath): fd.write(open(fpath).read()) fd.close() # The data files to install along with the binwalk module install_data_files = ["magic/*", "config/*"] # Install the binwalk module, script and support files setup( name = "binwalk", version = "1.0", description = "Firmware analysis tool", author = "Craig Heffner", url = "http://binwalk.googlecode.com", packages = ["binwalk"], package_data = {"binwalk" : install_data_files}, scripts = ["bin/binwalk"], ) ================================================ FILE: src/binwalk-1.0/src/support/lzma_gen.py ================================================ #!/usr/bin/env python # Generates LZMA signatures for each valid LZMA property in the properties list. properties = [ 0x5D, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0A, 0x0B, 0x0C, 0x12, 0x13, 0x14, 0x1B, 0x1C, 0x24, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x36, 0x37, 0x38, 0x39, 0x3F, 0x40, 0x41, 0x48, 0x49, 0x51, 0x5A, 0x5B, 0x5C, 0x5E, 0x63, 0x64, 0x65, 0x66, 0x6C, 0x6D, 0x6E, 0x75, 0x76, 0x7E, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x90, 0x91, 0x92, 0x93, 0x99, 0x9A, 0x9B, 0xA2, 0xA3, 0xAB, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xBD, 0xBE, 0xBF, 0xC0, 0xC6, 0xC7, 0xC8, 0xCF, 0xD0, 0xD8, ] common_properties = [0x5D, 0x6D] dictionary_sizes = [ 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, ] for fbyte in properties: # if fbyte not in common_properties: # fexclude = '{filter-exclude}' # else: # fexclude = '' fexclude = '' sig = '\n# ------------------------------------------------------------------\n' sig += '# Signature for LZMA compressed data with valid properties byte 0x%.2X\n' % fbyte sig += '# ------------------------------------------------------------------\n' sig += '0\t\tstring\t\\x%.2X\\x00\\x00\tLZMA compressed data, properties: 0x%.2X,%s\n' % (fbyte, fbyte, fexclude) sig += '\n# These are all the valid dictionary sizes supported by LZMA utils.\n' for i in range(0, len(dictionary_sizes)): if i < 6: indent = '\t\t' else: indent = '\t' if i == len(dictionary_sizes)-1: invalid = 'invalid' else: invalid = '' sig += '%s1%slelong\t!%d\t%s\n' % ('>'*(i+1), indent, dictionary_sizes[i], invalid) sig += '>1\t\tlelong\tx\t\tdictionary size: %d bytes,\n' sig += '\n# Assume that a valid size will be less than 1GB. This could technically be valid, but is unlikely.\n' sig += '>5\t\tlequad\t<1\t\tinvalid\n' sig += '>5\t\tlequad\t>0x40000000\tinvalid\n' sig += '\n# These are not 100%. The uncompressed size could be exactly the same as the dicionary size, but it is unlikely.\n' sig += '# Since most false positives are the result of repeating sequences of bytes (such as executable instructions),\n' sig += '# marking matches with the same uncompressed and dictionary sizes as invalid eliminates much of these false positives.\n' for dsize in dictionary_sizes: if dsize < 16777216: indent = '\t\t' else: indent = '\t' sig += '>1\t\tlelong\t%d\n' % dsize sig += '>>5\t\tlequad\t%d%sinvalid\n' % (dsize, indent) sig += '>5\t\tlequad\tx\t\tuncompressed size: %lld bytes\n' print sig ================================================ FILE: src/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for Firmware Mod Kit 0.4.0. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: http://firmware-mod-kit.googlecode.com about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Firmware Mod Kit' PACKAGE_TARNAME='firmware-mod-kit' PACKAGE_VERSION='0.4.0' PACKAGE_STRING='Firmware Mod Kit 0.4.0' PACKAGE_BUGREPORT='http://firmware-mod-kit.googlecode.com' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS EGREP GREP CPP ac_ct_CXX CXXFLAGS CXX OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Firmware Mod Kit 0.4.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/firmware-mod-kit] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Firmware Mod Kit 0.4.0:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Firmware Mod Kit configure 0.4.0 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( cat <<\_ASBOX ## ----------------------------------------------------- ## ## Report this to http://firmware-mod-kit.googlecode.com ## ## ----------------------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Firmware Mod Kit $as_me 0.4.0, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CXX+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi for ac_header in arpa/inet.h fcntl.h stdlib.h string.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else echo "error: missing necessary header file(s)" && exit fi done for ac_func in memset malloc strstr do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else as_fn_error "\"Missing necessary function(s)\"" "$LINENO" 5 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crc32 in -lz" >&5 $as_echo_n "checking for crc32 in -lz... " >&6; } if test "${ac_cv_lib_z_crc32+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char crc32 (); int main () { return crc32 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_crc32=yes else ac_cv_lib_z_crc32=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_crc32" >&5 $as_echo "$ac_cv_lib_z_crc32" >&6; } if test "x$ac_cv_lib_z_crc32" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" else echo "error: missing zlib library" && exit fi for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ZLIB_H 1 _ACEOF else echo "error: missing zlib header files" && exit fi done for ac_header in lzma.h do : ac_fn_c_check_header_mongrel "$LINENO" "lzma.h" "ac_cv_header_lzma_h" "$ac_includes_default" if test "x$ac_cv_header_lzma_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LZMA_H 1 _ACEOF else echo "error: missing liblzma header files" && exit fi done ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Firmware Mod Kit $as_me 0.4.0, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Firmware Mod Kit config.status 0.4.0 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: src/configure.ac ================================================ AC_PREREQ([2.65]) AC_INIT([Firmware Mod Kit],[0.4.0],[http://firmware-mod-kit.googlecode.com]) AC_PROG_CC AC_PROG_CXX AC_LANG(C) AC_TYPE_SIZE_T AC_FUNC_MALLOC AC_CHECK_HEADERS([arpa/inet.h fcntl.h stdlib.h string.h unistd.h],[],[echo "error: missing necessary header file(s)" && exit]) AC_CHECK_FUNCS([memset malloc strstr],[],AC_MSG_ERROR(["Missing necessary function(s)"])) AC_CHECK_LIB([z],[crc32],[],[echo "error: missing zlib library" && exit],[]) AC_CHECK_HEADERS([zlib.h],[],[echo "error: missing zlib header files" && exit]) AC_CHECK_HEADERS([lzma.h],[],[echo "error: missing liblzma header files" && exit]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ================================================ FILE: src/cramfs-2.x/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/cramfs-2.x/GNUmakefile ================================================ CC = gcc CFLAGS = -W -Wall -O2 -g CPPFLAGS = -I. LDLIBS = -lz PROGS = mkcramfs cramfsck all: $(PROGS) distclean clean: rm -f $(PROGS) .PHONY: all clean ================================================ FILE: src/cramfs-2.x/NOTES ================================================ Notes on Filesystem Layout -------------------------- These notes describe what mkcramfs generates. Kernel requirements are a bit looser, e.g. it doesn't care if the items are swapped around (though it does care that directory entries (inodes) in a given directory are contiguous, as this is used by readdir). All data is currently in host-endian format; neither mkcramfs nor the kernel ever do swabbing. (See section `Block Size' below.) : : struct cramfs_super (see cramfs_fs.h). : For each file: struct cramfs_inode (see cramfs_fs.h). Filename. Not generally null-terminated, but it is null-padded to a multiple of 4 bytes. The order of inode traversal is described as "width-first" (not to be confused with breadth-first); i.e. like depth-first but listing all of a directory's entries before recursing down its subdirectories: the same order as `ls -AUR' (but without the /^\..*:$/ directory header lines); put another way, the same order as `find -type d -exec ls -AU1 {} \;'. Beginning in 2.4.7, directory entries are sorted. This optimization allows cramfs_lookup to return more quickly when a filename does not exist, speeds up user-space directory sorts, etc. : One for each file that's either a symlink or a regular file of non-zero st_size. : nblocks * (where nblocks = (st_size - 1) / blksize + 1) nblocks * padding to multiple of 4 bytes The i'th for a file stores the byte offset of the *end* of the i'th (i.e. one past the last byte, which is the same as the start of the (i+1)'th if there is one). The first immediately follows the last for the file. s are each 32 bits long. The order of 's is a depth-first descent of the directory tree, i.e. the same order as `find -size +0 \( -type f -o -type l \) -print'. : The i'th is the output of zlib's compress function applied to the i'th blksize-sized chunk of the input data. (For the last of the file, the input may of course be smaller.) Each may be a different size. (See above.) s are merely byte-aligned, not generally u32-aligned. Holes ----- This kernel supports cramfs holes (i.e. [efficient representation of] blocks in uncompressed data consisting entirely of NUL bytes), but by default mkcramfs doesn't test for & create holes, since cramfs in kernels up to at least 2.3.39 didn't support holes. Run mkcramfs with -z if you want it to create files that can have holes in them. Tools ----- The cramfs user-space tools, including mkcramfs and cramfsck, are located at . Future Development ================== Block Size ---------- (Block size in cramfs refers to the size of input data that is compressed at a time. It's intended to be somewhere around PAGE_CACHE_SIZE for cramfs_readpage's convenience.) The superblock ought to indicate the block size that the fs was written for, since comments in indicate that PAGE_CACHE_SIZE may grow in future (if I interpret the comment correctly). Currently, mkcramfs #define's PAGE_CACHE_SIZE as 4096 and uses that for blksize, whereas Linux-2.3.39 uses its PAGE_CACHE_SIZE, which in turn is defined as PAGE_SIZE (which can be as large as 32KB on arm). This discrepancy is a bug, though it's not clear which should be changed. One option is to change mkcramfs to take its PAGE_CACHE_SIZE from . Personally I don't like this option, but it does require the least amount of change: just change `#define PAGE_CACHE_SIZE (4096)' to `#include '. The disadvantage is that the generated cramfs cannot always be shared between different kernels, not even necessarily kernels of the same architecture if PAGE_CACHE_SIZE is subject to change between kernel versions (currently possible with arm and ia64). The remaining options try to make cramfs more sharable. One part of that is addressing endianness. The two options here are `always use little-endian' (like ext2fs) or `writer chooses endianness; kernel adapts at runtime'. Little-endian wins because of code simplicity and little CPU overhead even on big-endian machines. The cost of swabbing is changing the code to use the le32_to_cpu etc. macros as used by ext2fs. We don't need to swab the compressed data, only the superblock, inodes and block pointers. The other part of making cramfs more sharable is choosing a block size. The options are: 1. Always 4096 bytes. 2. Writer chooses blocksize; kernel adapts but rejects blocksize > PAGE_CACHE_SIZE. 3. Writer chooses blocksize; kernel adapts even to blocksize > PAGE_CACHE_SIZE. It's easy enough to change the kernel to use a smaller value than PAGE_CACHE_SIZE: just make cramfs_readpage read multiple blocks. The cost of option 1 is that kernels with a larger PAGE_CACHE_SIZE value don't get as good compression as they can. The cost of option 2 relative to option 1 is that the code uses variables instead of #define'd constants. The gain is that people with kernels having larger PAGE_CACHE_SIZE can make use of that if they don't mind their cramfs being inaccessible to kernels with smaller PAGE_CACHE_SIZE values. Option 3 is easy to implement if we don't mind being CPU-inefficient: e.g. get readpage to decompress to a buffer of size MAX_BLKSIZE (which must be no larger than 32KB) and discard what it doesn't need. Getting readpage to read into all the covered pages is harder. The main advantage of option 3 over 1, 2, is better compression. The cost is greater complexity. Probably not worth it, but I hope someone will disagree. (If it is implemented, then I'll re-use that code in e2compr.) Another cost of 2 and 3 over 1 is making mkcramfs use a different block size, but that just means adding and parsing a -b option. Inode Size ---------- Given that cramfs will probably be used for CDs etc. as well as just silicon ROMs, it might make sense to expand the inode a little from its current 12 bytes. Inodes other than the root inode are followed by filename, so the expansion doesn't even have to be a multiple of 4 bytes. ================================================ FILE: src/cramfs-2.x/README ================================================ Cramfs - cram a filesystem onto a small ROM cramfs is designed to be simple and small, and to compress things well. It uses the zlib routines to compress a file one page at a time, and allows random page access. The meta-data is not compressed, but is expressed in a very terse representation to make it use much less diskspace than traditional filesystems. You can't write to a cramfs filesystem (making it compressible and compact also makes it _very_ hard to update on-the-fly), so you have to create the disk image with the "mkcramfs" utility. Usage Notes ----------- File sizes are limited to less than 16MB. Maximum filesystem size is a little over 256MB. (The last file on the filesystem is allowed to extend past 256MB.) Only the low 8 bits of gid are stored. The current version of mkcramfs simply truncates to 8 bits, which is a potential security issue. Hard links are supported, but hard linked files will still have a link count of 1 in the cramfs image. Cramfs directories have no `.' or `..' entries. Directories (like every other file on cramfs) always have a link count of 1. (There's no need to use -noleaf in `find', btw.) No timestamps are stored in a cramfs, so these default to the epoch (1970 GMT). Recently-accessed files may have updated timestamps, but the update lasts only as long as the inode is cached in memory, after which the timestamp reverts to 1970, i.e. moves backwards in time. Currently, cramfs must be written and read with architectures of the same endianness, and can be read only by kernels with PAGE_CACHE_SIZE == 4096. At least the latter of these is a bug, but it hasn't been decided what the best fix is. For the moment if you have larger pages you can just change the #define in mkcramfs.c, so long as you don't mind the filesystem becoming unreadable to future kernels. For /usr/share/magic -------------------- 0 ulelong 0x28cd3d45 Linux cramfs offset 0 >4 ulelong x size %d >8 ulelong x flags 0x%x >12 ulelong x future 0x%x >16 string >\0 signature "%.16s" >32 ulelong x fsid.crc 0x%x >36 ulelong x fsid.edition %d >40 ulelong x fsid.blocks %d >44 ulelong x fsid.files %d >48 string >\0 name "%.16s" 512 ulelong 0x28cd3d45 Linux cramfs offset 512 >516 ulelong x size %d >520 ulelong x flags 0x%x >524 ulelong x future 0x%x >528 string >\0 signature "%.16s" >544 ulelong x fsid.crc 0x%x >548 ulelong x fsid.edition %d >552 ulelong x fsid.blocks %d >556 ulelong x fsid.files %d >560 string >\0 name "%.16s" Hacker Notes ------------ See fs/cramfs/README for filesystem layout and implementation notes. ================================================ FILE: src/cramfs-2.x/cramfsck.c ================================================ /* * cramfsck - check a cramfs file system * * Copyright (C) 2000-2002 Transmeta Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 1999/12/03: Linus Torvalds (cramfs tester and unarchive program) * 2000/06/03: Daniel Quinlan (CRC and length checking program) * 2000/06/04: Daniel Quinlan (merged programs, added options, support * for special files, preserve permissions and * ownership, cramfs superblock v2, bogus mode * test, pathname length test, etc.) * 2000/06/06: Daniel Quinlan (support for holes, pretty-printing, * symlink size test) * 2000/07/11: Daniel Quinlan (file length tests, start at offset 0 or 512, * fsck-compatible exit codes) * 2000/07/15: Daniel Quinlan (initial support for block devices) * 2002/01/10: Daniel Quinlan (additional checks, test more return codes, * use read if mmap fails, standardize messages) */ /* compile-time options */ #define INCLUDE_FS_TESTS /* include cramfs checking and extraction */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _LINUX_STRING_H_ #include #include #include /* Exit codes used by fsck-type programs */ #define FSCK_OK 0 /* No errors */ #define FSCK_NONDESTRUCT 1 /* File system errors corrected */ #define FSCK_REBOOT 2 /* System should be rebooted */ #define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */ #define FSCK_ERROR 8 /* Operational error */ #define FSCK_USAGE 16 /* Usage or syntax error */ #define FSCK_LIBRARY 128 /* Shared library error */ #define PAD_SIZE 512 #define PAGE_CACHE_SIZE (4096) static const char *progname = "cramfsck"; static int fd; /* ROM image file descriptor */ static char *filename; /* ROM image filename */ struct cramfs_super super; /* just find the cramfs superblock once */ static int opt_verbose = 0; /* 1 = verbose (-v), 2+ = very verbose (-vv) */ #ifdef INCLUDE_FS_TESTS static int opt_extract = 0; /* extract cramfs (-x) */ static char *extract_dir = "root"; /* extraction directory (-x) */ static uid_t euid; /* effective UID */ /* (cramfs_super + start) <= start_dir < end_dir <= start_data <= end_data */ static unsigned long start_dir = ~0UL; /* start of first non-root inode */ static unsigned long end_dir = 0; /* end of the directory structure */ static unsigned long start_data = ~0UL; /* start of the data (256 MB = max) */ static unsigned long end_data = 0; /* end of the data */ /* Guarantee access to at least 8kB at a time */ #define ROMBUFFER_BITS 13 #define ROMBUFFERSIZE (1 << ROMBUFFER_BITS) #define ROMBUFFERMASK (ROMBUFFERSIZE-1) static char read_buffer[ROMBUFFERSIZE * 2]; static unsigned long read_buffer_block = ~0UL; /* Uncompressing data structures... */ static char outbuffer[PAGE_CACHE_SIZE*2]; static z_stream stream; /* Prototypes */ static void expand_fs(char *, struct cramfs_inode *); #endif /* INCLUDE_FS_TESTS */ /* Input status of 0 to print help and exit without an error. */ static void usage(int status) { FILE *stream = status ? stderr : stdout; fprintf(stream, "usage: %s [-hv] [-x dir] file\n" " -h print this help\n" " -x dir extract into dir\n" " -v be more verbose\n" " file file to test\n", progname); exit(status); } static void die(int status, int syserr, const char *fmt, ...) { va_list arg_ptr; int save = errno; fflush(0); va_start(arg_ptr, fmt); fprintf(stderr, "%s: ", progname); vfprintf(stderr, fmt, arg_ptr); if (syserr) { fprintf(stderr, ": %s", strerror(save)); } fprintf(stderr, "\n"); va_end(arg_ptr); exit(status); } static void test_super(int *start, size_t *length) { struct stat st; /* find the physical size of the file or block device */ if (stat(filename, &st) < 0) { die(FSCK_ERROR, 1, "stat failed: %s", filename); } fd = open(filename, O_RDONLY); if (fd < 0) { die(FSCK_ERROR, 1, "open failed: %s", filename); } if (S_ISBLK(st.st_mode)) { if (ioctl(fd, BLKGETSIZE, length) < 0) { die(FSCK_ERROR, 1, "ioctl failed: unable to determine device size: %s", filename); } *length = *length * 512; } else if (S_ISREG(st.st_mode)) { *length = st.st_size; } else { die(FSCK_ERROR, 0, "not a block device or file: %s", filename); } if (*length < sizeof(struct cramfs_super)) { die(FSCK_UNCORRECTED, 0, "file length too short"); } /* find superblock */ if (read(fd, &super, sizeof(super)) != sizeof(super)) { die(FSCK_ERROR, 1, "read failed: %s", filename); } if (super.magic == CRAMFS_MAGIC) { *start = 0; } else if (*length >= (PAD_SIZE + sizeof(super))) { lseek(fd, PAD_SIZE, SEEK_SET); if (read(fd, &super, sizeof(super)) != sizeof(super)) { die(FSCK_ERROR, 1, "read failed: %s", filename); } if (super.magic == CRAMFS_MAGIC) { *start = PAD_SIZE; } } /* superblock tests */ if (super.magic != CRAMFS_MAGIC) { die(FSCK_UNCORRECTED, 0, "superblock magic not found"); } if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { die(FSCK_ERROR, 0, "unsupported filesystem features"); } if (super.size < PAGE_CACHE_SIZE) { die(FSCK_UNCORRECTED, 0, "superblock size (%d) too small", super.size); } if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { if (super.fsid.files == 0) { die(FSCK_UNCORRECTED, 0, "zero file count"); } if (*length < super.size) { die(FSCK_UNCORRECTED, 0, "file length too short"); } else if (*length > super.size) { fprintf(stderr, "warning: file extends past end of filesystem\n"); } } else { fprintf(stderr, "warning: old cramfs format\n"); } } static void test_crc(int start) { void *buf; u32 crc; if (!(super.flags & CRAMFS_FLAG_FSID_VERSION_2)) { #ifdef INCLUDE_FS_TESTS return; #else /* not INCLUDE_FS_TESTS */ die(FSCK_USAGE, 0, "unable to test CRC: old cramfs format"); #endif /* not INCLUDE_FS_TESTS */ } crc = crc32(0L, Z_NULL, 0); buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) { buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf != MAP_FAILED) { lseek(fd, 0, SEEK_SET); read(fd, buf, super.size); } } if (buf != MAP_FAILED) { ((struct cramfs_super *) (buf+start))->fsid.crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, buf+start, super.size-start); munmap(buf, super.size); } else { int retval; size_t length = 0; buf = malloc(4096); if (!buf) { die(FSCK_ERROR, 1, "malloc failed"); } lseek(fd, start, SEEK_SET); for (;;) { retval = read(fd, buf, 4096); if (retval < 0) { die(FSCK_ERROR, 1, "read failed: %s", filename); } else if (retval == 0) { break; } if (length == 0) { ((struct cramfs_super *) buf)->fsid.crc = crc32(0L, Z_NULL, 0); } length += retval; if (length > (super.size-start)) { crc = crc32(crc, buf, retval - (length - (super.size-start))); break; } crc = crc32(crc, buf, retval); } free(buf); } if (crc != super.fsid.crc) { die(FSCK_UNCORRECTED, 0, "crc error"); } } #ifdef INCLUDE_FS_TESTS static void print_node(char type, struct cramfs_inode *i, char *name) { char info[10]; if (S_ISCHR(i->mode) || (S_ISBLK(i->mode))) { /* major/minor numbers can be as high as 2^12 or 4096 */ snprintf(info, 10, "%4d,%4d", major(i->size), minor(i->size)); } else { /* size be as high as 2^24 or 16777216 */ snprintf(info, 10, "%9d", i->size); } printf("%c %04o %s %5d:%-3d %s\n", type, i->mode & ~S_IFMT, info, i->uid, i->gid, name); } /* * Create a fake "blocked" access */ static void *romfs_read(unsigned long offset) { unsigned int block = offset >> ROMBUFFER_BITS; if (block != read_buffer_block) { read_buffer_block = block; lseek(fd, block << ROMBUFFER_BITS, SEEK_SET); read(fd, read_buffer, ROMBUFFERSIZE * 2); } return read_buffer + (offset & ROMBUFFERMASK); } static struct cramfs_inode *cramfs_iget(struct cramfs_inode * i) { struct cramfs_inode *inode = malloc(sizeof(struct cramfs_inode)); if (!inode) { die(FSCK_ERROR, 1, "malloc failed"); } *inode = *i; return inode; } static struct cramfs_inode *iget(unsigned int ino) { return cramfs_iget(romfs_read(ino)); } static void iput(struct cramfs_inode *inode) { free(inode); } /* * Return the offset of the root directory */ static struct cramfs_inode *read_super(void) { unsigned long offset = super.root.offset << 2; if (!S_ISDIR(super.root.mode)) die(FSCK_UNCORRECTED, 0, "root inode is not directory"); if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((offset != sizeof(struct cramfs_super)) && (offset != PAD_SIZE + sizeof(struct cramfs_super)))) { die(FSCK_UNCORRECTED, 0, "bad root offset (%lu)", offset); } return cramfs_iget(&super.root); } static int uncompress_block(void *src, int len) { int err; stream.next_in = src; stream.avail_in = len; stream.next_out = (unsigned char *) outbuffer; stream.avail_out = PAGE_CACHE_SIZE*2; inflateReset(&stream); if (len > PAGE_CACHE_SIZE*2) { die(FSCK_UNCORRECTED, 0, "data block too large"); } err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { die(FSCK_UNCORRECTED, 0, "decompression error %p(%d): %s", zError(err), src, len); } return stream.total_out; } static void do_uncompress(char *path, int fd, unsigned long offset, unsigned long size) { unsigned long curr = offset + 4 * ((size + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE); do { unsigned long out = PAGE_CACHE_SIZE; unsigned long next = *(u32 *) romfs_read(offset); if (next > end_data) { end_data = next; } offset += 4; if (curr == next) { if (opt_verbose > 1) { printf(" hole at %ld (%d)\n", curr, PAGE_CACHE_SIZE); } if (size < PAGE_CACHE_SIZE) out = size; memset(outbuffer, 0x00, out); } else { if (opt_verbose > 1) { printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); } out = uncompress_block(romfs_read(curr), next - curr); } if (size >= PAGE_CACHE_SIZE) { if (out != PAGE_CACHE_SIZE) { die(FSCK_UNCORRECTED, 0, "non-block (%ld) bytes", out); } } else { if (out != size) { die(FSCK_UNCORRECTED, 0, "non-size (%ld vs %ld) bytes", out, size); } } size -= out; if (opt_extract) { if (write(fd, outbuffer, out) < 0) { die(FSCK_ERROR, 1, "write failed: %s", path); } } curr = next; } while (size); } static void change_file_status(char *path, struct cramfs_inode *i) { struct utimbuf epoch = { 0, 0 }; if (euid == 0) { if (lchown(path, i->uid, i->gid) < 0) { die(FSCK_ERROR, 1, "lchown failed: %s", path); } if (S_ISLNK(i->mode)) return; if ((S_ISUID | S_ISGID) & i->mode) { if (chmod(path, i->mode) < 0) { die(FSCK_ERROR, 1, "chown failed: %s", path); } } } if (S_ISLNK(i->mode)) return; if (utime(path, &epoch) < 0) { die(FSCK_ERROR, 1, "utime failed: %s", path); } } static void do_directory(char *path, struct cramfs_inode *i) { int pathlen = strlen(path); int count = i->size; unsigned long offset = i->offset << 2; char *newpath = malloc(pathlen + 256); if (!newpath) { die(FSCK_ERROR, 1, "malloc failed"); } if (offset == 0 && count != 0) { die(FSCK_UNCORRECTED, 0, "directory inode has zero offset and non-zero size: %s", path); } if (offset != 0 && offset < start_dir) { start_dir = offset; } /* TODO: Do we need to check end_dir for empty case? */ memcpy(newpath, path, pathlen); newpath[pathlen] = '/'; pathlen++; if (opt_verbose) { print_node('d', i, path); } if (opt_extract) { if (mkdir(path, i->mode) < 0) { die(FSCK_ERROR, 1, "mkdir failed: %s", path); } change_file_status(path, i); } while (count > 0) { struct cramfs_inode *child = iget(offset); int size; int newlen = child->namelen << 2; size = sizeof(struct cramfs_inode) + newlen; count -= size; offset += sizeof(struct cramfs_inode); memcpy(newpath + pathlen, romfs_read(offset), newlen); newpath[pathlen + newlen] = 0; if (newlen == 0) { die(FSCK_UNCORRECTED, 0, "filename length is zero"); } if ((pathlen + newlen) - strlen(newpath) > 3) { die(FSCK_UNCORRECTED, 0, "bad filename length"); } expand_fs(newpath, child); offset += newlen; if (offset <= start_dir) { die(FSCK_UNCORRECTED, 0, "bad inode offset"); } if (offset > end_dir) { end_dir = offset; } iput(child); /* free(child) */ } free(newpath); } static void do_file(char *path, struct cramfs_inode *i) { unsigned long offset = i->offset << 2; int fd = 0; if (offset == 0 && i->size != 0) { die(FSCK_UNCORRECTED, 0, "file inode has zero offset and non-zero size"); } if (i->size == 0 && offset != 0) { die(FSCK_UNCORRECTED, 0, "file inode has zero size and non-zero offset"); } if (offset != 0 && offset < start_data) { start_data = offset; } if (opt_verbose) { print_node('f', i, path); } if (opt_extract) { fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode); if (fd < 0) { die(FSCK_ERROR, 1, "open failed: %s", path); } } if (i->size) { do_uncompress(path, fd, offset, i->size); } if (opt_extract) { close(fd); change_file_status(path, i); } } static void do_symlink(char *path, struct cramfs_inode *i) { unsigned long offset = i->offset << 2; unsigned long curr = offset + 4; unsigned long next = *(u32 *) romfs_read(offset); unsigned long size; if (offset == 0) { die(FSCK_UNCORRECTED, 0, "symbolic link has zero offset"); } if (i->size == 0) { die(FSCK_UNCORRECTED, 0, "symbolic link has zero size"); } if (offset < start_data) { start_data = offset; } if (next > end_data) { end_data = next; } size = uncompress_block(romfs_read(curr), next - curr); if (size != i->size) { die(FSCK_UNCORRECTED, 0, "size error in symlink: %s", path); } outbuffer[size] = 0; if (opt_verbose) { char *str; asprintf(&str, "%s -> %s", path, outbuffer); print_node('l', i, str); if (opt_verbose > 1) { printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); } free(str); } if (opt_extract) { if (symlink(outbuffer, path) < 0) { die(FSCK_ERROR, 1, "symlink failed: %s", path); } change_file_status(path, i); } } static void do_special_inode(char *path, struct cramfs_inode *i) { dev_t devtype = 0; char type; if (i->offset) { /* no need to shift offset */ die(FSCK_UNCORRECTED, 0, "special file has non-zero offset: %s", path); } if (S_ISCHR(i->mode)) { devtype = i->size; type = 'c'; } else if (S_ISBLK(i->mode)) { devtype = i->size; type = 'b'; } else if (S_ISFIFO(i->mode)) { if (i->size != 0) { die(FSCK_UNCORRECTED, 0, "fifo has non-zero size: %s", path); } type = 'p'; } else if (S_ISSOCK(i->mode)) { if (i->size != 0) { die(FSCK_UNCORRECTED, 0, "socket has non-zero size: %s", path); } type = 's'; } else { die(FSCK_UNCORRECTED, 0, "bogus mode: %s (%o)", path, i->mode); return; /* not reached */ } if (opt_verbose) { print_node(type, i, path); } if (opt_extract) { if (mknod(path, i->mode, devtype) < 0) { die(FSCK_ERROR, 1, "mknod failed: %s", path); } change_file_status(path, i); } } static void expand_fs(char *path, struct cramfs_inode *inode) { if (S_ISDIR(inode->mode)) { do_directory(path, inode); } else if (S_ISREG(inode->mode)) { do_file(path, inode); } else if (S_ISLNK(inode->mode)) { do_symlink(path, inode); } else { do_special_inode(path, inode); } } static void test_fs(int start) { struct cramfs_inode *root; root = read_super(); umask(0); euid = geteuid(); stream.next_in = NULL; stream.avail_in = 0; inflateInit(&stream); expand_fs(extract_dir, root); inflateEnd(&stream); if (start_data != ~0UL) { if (start_data < (sizeof(struct cramfs_super) + start)) { die(FSCK_UNCORRECTED, 0, "directory data start (%ld) < sizeof(struct cramfs_super) + start (%ld)", start_data, sizeof(struct cramfs_super) + start); } if (end_dir != start_data) { die(FSCK_UNCORRECTED, 0, "directory data end (%ld) != file data start (%ld)", end_dir, start_data); } } if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { if (end_data > super.size) { die(FSCK_UNCORRECTED, 0, "invalid file data offset"); } } iput(root); /* free(root) */ } #endif /* INCLUDE_FS_TESTS */ int main(int argc, char **argv) { int c; /* for getopt */ int start = 0; size_t length; if (argc) progname = argv[0]; /* command line options */ while ((c = getopt(argc, argv, "hx:v")) != EOF) { switch (c) { case 'h': usage(FSCK_OK); case 'x': #ifdef INCLUDE_FS_TESTS opt_extract = 1; extract_dir = optarg; break; #else /* not INCLUDE_FS_TESTS */ die(FSCK_USAGE, 0, "compiled without -x support"); #endif /* not INCLUDE_FS_TESTS */ case 'v': opt_verbose++; break; } } if ((argc - optind) != 1) usage(FSCK_USAGE); filename = argv[optind]; test_super(&start, &length); test_crc(start); #ifdef INCLUDE_FS_TESTS test_fs(start); #endif /* INCLUDE_FS_TESTS */ if (opt_verbose) { printf("%s: OK\n", filename); } exit(FSCK_OK); } /* * Local variables: * c-file-style: "linux" * End: */ ================================================ FILE: src/cramfs-2.x/linux/cramfs_fs.h ================================================ #ifndef __CRAMFS_H #define __CRAMFS_H #ifndef __KERNEL__ typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; #endif #define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ #define CRAMFS_SIGNATURE "Compressed ROMFS" /* * Width of various bitfields in struct cramfs_inode. * Primarily used to generate warnings in mkcramfs. */ #define CRAMFS_MODE_WIDTH 16 #define CRAMFS_UID_WIDTH 16 #define CRAMFS_SIZE_WIDTH 24 #define CRAMFS_GID_WIDTH 8 #define CRAMFS_NAMELEN_WIDTH 6 #define CRAMFS_OFFSET_WIDTH 26 /* * Since inode.namelen is a unsigned 6-bit number, the maximum cramfs * path length is 63 << 2 = 252. */ #define CRAMFS_MAXPATHLEN (((1 << CRAMFS_NAMELEN_WIDTH) - 1) << 2) /* * Reasonably terse representation of the inode data. */ struct cramfs_inode { u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH; /* SIZE for device files is i_rdev */ u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH; /* NAMELEN is the length of the file name, divided by 4 and rounded up. (cramfs doesn't support hard links.) */ /* OFFSET: For symlinks and non-empty regular files, this contains the offset (divided by 4) of the file data in compressed form (starting with an array of block pointers; see README). For non-empty directories it is the offset (divided by 4) of the inode of the first file in that directory. For anything else, offset is zero. */ u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH; }; struct cramfs_info { u32 crc; u32 edition; u32 blocks; u32 files; }; /* * Superblock information at the beginning of the FS. */ struct cramfs_super { u32 magic; /* 0x28cd3d45 - random number */ u32 size; /* length in bytes */ u32 flags; /* feature flags */ u32 future; /* reserved for future use */ u8 signature[16]; /* "Compressed ROMFS" */ struct cramfs_info fsid; /* unique filesystem info */ u8 name[16]; /* user-defined name */ struct cramfs_inode root; /* root inode data */ }; /* * Feature flags * * 0x00000000 - 0x000000ff: features that work for all past kernels * 0x00000100 - 0xffffffff: features that don't work for past kernels */ #define CRAMFS_FLAG_FSID_VERSION_2 0x00000001 /* fsid version #2 */ #define CRAMFS_FLAG_SORTED_DIRS 0x00000002 /* sorted dirs */ #define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */ #define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */ #define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */ /* * Valid values in super.flags. Currently we refuse to mount * if (flags & ~CRAMFS_SUPPORTED_FLAGS). Maybe that should be * changed to test super.future instead. */ #define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \ | CRAMFS_FLAG_HOLES \ | CRAMFS_FLAG_WRONG_SIGNATURE \ | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) /* Uncompression interfaces to the underlying zlib */ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen); int cramfs_uncompress_init(void); int cramfs_uncompress_exit(void); #endif ================================================ FILE: src/cramfs-2.x/linux/cramfs_fs_sb.h ================================================ #ifndef _CRAMFS_FS_SB #define _CRAMFS_FS_SB /* * cramfs super-block data in memory */ struct cramfs_sb_info { unsigned long magic; unsigned long size; unsigned long blocks; unsigned long files; unsigned long flags; }; #endif ================================================ FILE: src/cramfs-2.x/mkcramfs.c ================================================ /* * mkcramfs - make a cramfs file system * * Copyright (C) 1999-2002 Transmeta Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * If you change the disk format of cramfs, please update fs/cramfs/README. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Exit codes used by mkfs-type programs */ #define MKFS_OK 0 /* No errors */ #define MKFS_ERROR 8 /* Operational error */ #define MKFS_USAGE 16 /* Usage or syntax error */ /* The kernel only supports PAD_SIZE of 0 and 512. */ #define PAD_SIZE 512 /* The kernel assumes PAGE_CACHE_SIZE as block size. */ #define PAGE_CACHE_SIZE (4096) /* * The longest filename component to allow for in the input directory tree. * ext2fs (and many others) allow up to 255 bytes. A couple of filesystems * allow longer (e.g. smbfs 1024), but there isn't much use in supporting * >255-byte names in the input directory tree given that such names get * truncated to CRAMFS_MAXPATHLEN (252 bytes) when written to cramfs. * * Old versions of mkcramfs generated corrupted filesystems if any input * filenames exceeded CRAMFS_MAXPATHLEN (252 bytes), however old * versions of cramfsck seem to have been able to detect the corruption. */ #define MAX_INPUT_NAMELEN 255 /* * Maximum size fs you can create is roughly 256MB. (The last file's * data must begin within 256MB boundary but can extend beyond that.) * * Note that if you want it to fit in a ROM then you're limited to what the * hardware and kernel can support. */ #define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \ + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \ + (1 << CRAMFS_SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ ) static const char *progname = "mkcramfs"; static unsigned int blksize = PAGE_CACHE_SIZE; static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */ static int image_length = 0; /* * If opt_holes is set, then mkcramfs can create explicit holes in the * data, which saves 26 bytes per hole (which is a lot smaller a * saving than most most filesystems). * * Note that kernels up to at least 2.3.39 don't support cramfs holes, * which is why this is turned off by default. * * If opt_verbose is 1, be verbose. If it is higher, be even more verbose. */ static u32 opt_edition = 0; static int opt_errors = 0; static int opt_holes = 0; static int opt_pad = 0; static int opt_verbose = 0; static char *opt_image = NULL; static char *opt_name = NULL; static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid; /* In-core version of inode / directory entry. */ struct entry { /* stats */ unsigned char *name; unsigned int mode, size, uid, gid; /* these are only used for non-empty files */ char *path; /* always null except non-empty files */ int fd; /* temporarily open files while mmapped */ /* FS data */ void *uncompressed; /* points to other identical file */ struct entry *same; unsigned int offset; /* pointer to compressed data in archive */ unsigned int dir_offset; /* Where in the archive is the directory entry? */ /* organization */ struct entry *child; /* null for non-directories and empty directories */ struct entry *next; }; /* Input status of 0 to print help and exit without an error. */ static void usage(int status) { FILE *stream = status ? stderr : stdout; fprintf(stream, "usage: %s [-h] [-e edition] [-i file] [-n name] dirname outfile\n" " -h print this help\n" " -E make all warnings errors (non-zero exit status)\n" " -e edition set edition number (part of fsid)\n" " -i file insert a file image into the filesystem (requires >= 2.4.0)\n" " -n name set name of cramfs filesystem\n" " -p pad by %d bytes for boot code\n" " -s sort directory entries (old option, ignored)\n" " -v be more verbose\n" " -z make explicit holes (requires >= 2.3.39)\n" " dirname root of the directory tree to be compressed\n" " outfile output file\n", progname, PAD_SIZE); exit(status); } static void die(int status, int syserr, const char *fmt, ...) { va_list arg_ptr; int save = errno; fflush(0); va_start(arg_ptr, fmt); fprintf(stderr, "%s: ", progname); vfprintf(stderr, fmt, arg_ptr); if (syserr) { fprintf(stderr, ": %s", strerror(save)); } fprintf(stderr, "\n"); va_end(arg_ptr); exit(status); } static void map_entry(struct entry *entry) { if (entry->path) { entry->fd = open(entry->path, O_RDONLY); if (entry->fd < 0) { die(MKFS_ERROR, 1, "open failed: %s", entry->path); } entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, entry->fd, 0); if (entry->uncompressed == MAP_FAILED) { die(MKFS_ERROR, 1, "mmap failed: %s", entry->path); } } } static void unmap_entry(struct entry *entry) { if (entry->path) { if (munmap(entry->uncompressed, entry->size) < 0) { die(MKFS_ERROR, 1, "munmap failed: %s", entry->path); } close(entry->fd); } } static int find_identical_file(struct entry *orig, struct entry *newfile) { if (orig == newfile) return 1; if (!orig) return 0; if (orig->size == newfile->size && (orig->path || orig->uncompressed)) { map_entry(orig); map_entry(newfile); if (!memcmp(orig->uncompressed, newfile->uncompressed, orig->size)) { newfile->same = orig; unmap_entry(newfile); unmap_entry(orig); return 1; } unmap_entry(newfile); unmap_entry(orig); } return (find_identical_file(orig->child, newfile) || find_identical_file(orig->next, newfile)); } static void eliminate_doubles(struct entry *root, struct entry *orig) { if (orig) { if (orig->size && (orig->path || orig->uncompressed)) find_identical_file(root, orig); eliminate_doubles(root, orig->child); eliminate_doubles(root, orig->next); } } /* * We define our own sorting function instead of using alphasort which * uses strcoll and changes ordering based on locale information. */ static int cramsort (const void *a, const void *b) { return strcmp ((*(const struct dirent **) a)->d_name, (*(const struct dirent **) b)->d_name); } static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub) { struct dirent **dirlist; int totalsize = 0, dircount, dirindex; char *path, *endpath; size_t len = strlen(name); /* Set up the path. */ /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */ path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1); if (!path) { die(MKFS_ERROR, 1, "malloc failed"); } memcpy(path, name, len); endpath = path + len; *endpath = '/'; endpath++; /* read in the directory and sort */ dircount = scandir(name, &dirlist, 0, cramsort); if (dircount < 0) { die(MKFS_ERROR, 1, "scandir failed: %s", name); } /* process directory */ for (dirindex = 0; dirindex < dircount; dirindex++) { struct dirent *dirent; struct entry *entry; struct stat st; int size; size_t namelen; dirent = dirlist[dirindex]; /* Ignore "." and ".." - we won't be adding them to the archive */ if (dirent->d_name[0] == '.') { if (dirent->d_name[1] == '\0') continue; if (dirent->d_name[1] == '.') { if (dirent->d_name[2] == '\0') continue; } } namelen = strlen(dirent->d_name); if (namelen > MAX_INPUT_NAMELEN) { die(MKFS_ERROR, 0, "very long (%u bytes) filename found: %s\n" "please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile", namelen, dirent->d_name); } memcpy(endpath, dirent->d_name, namelen + 1); if (lstat(path, &st) < 0) { warn_skip = 1; continue; } entry = calloc(1, sizeof(struct entry)); if (!entry) { die(MKFS_ERROR, 1, "calloc failed"); } entry->name = strdup(dirent->d_name); if (!entry->name) { die(MKFS_ERROR, 1, "strdup failed"); } /* truncate multi-byte UTF-8 filenames on character boundary */ if (namelen > CRAMFS_MAXPATHLEN) { namelen = CRAMFS_MAXPATHLEN; warn_namelen = 1; /* the first lost byte must not be a trail byte */ while ((entry->name[namelen] & 0xc0) == 0x80) { namelen--; /* are we reasonably certain it was UTF-8 ? */ if (entry->name[namelen] < 0x80 || !namelen) { die(MKFS_ERROR, 0, "cannot truncate filenames not encoded in UTF-8"); } } entry->name[namelen] = '\0'; } entry->mode = st.st_mode; entry->size = st.st_size; entry->uid = st.st_uid; if (entry->uid >= 1 << CRAMFS_UID_WIDTH) warn_uid = 1; entry->gid = st.st_gid; if (entry->gid >= 1 << CRAMFS_GID_WIDTH) /* TODO: We ought to replace with a default gid instead of truncating; otherwise there are security problems. Maybe mode should be &= ~070. Same goes for uid once Linux supports >16-bit uids. */ warn_gid = 1; size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3); *fslen_ub += size; if (S_ISDIR(st.st_mode)) { entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub); } else if (S_ISREG(st.st_mode)) { if (entry->size) { if (access(path, R_OK) < 0) { warn_skip = 1; continue; } entry->path = strdup(path); if (!entry->path) { die(MKFS_ERROR, 1, "strdup failed"); } if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) { warn_size = 1; entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1; } } } else if (S_ISLNK(st.st_mode)) { entry->uncompressed = malloc(entry->size); if (!entry->uncompressed) { die(MKFS_ERROR, 1, "malloc failed"); } if (readlink(path, entry->uncompressed, entry->size) < 0) { warn_skip = 1; continue; } } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { /* maybe we should skip sockets */ entry->size = 0; } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { entry->size = st.st_rdev; if (entry->size & -(1<name); } if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { int blocks = ((entry->size - 1) / blksize + 1); /* block pointers & data expansion allowance + data */ if (entry->size) *fslen_ub += (4+26)*blocks + entry->size + 3; } /* Link it into the list */ *prev = entry; prev = &entry->next; totalsize += size; } free(path); free(dirlist); /* allocated by scandir() with malloc() */ return totalsize; } /* Returns sizeof(struct cramfs_super), which includes the root inode. */ static unsigned int write_superblock(struct entry *root, char *base, int size) { struct cramfs_super *super = (struct cramfs_super *) base; unsigned int offset = sizeof(struct cramfs_super) + image_length; offset += opt_pad; /* 0 if no padding */ super->magic = CRAMFS_MAGIC; super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS; if (opt_holes) super->flags |= CRAMFS_FLAG_HOLES; if (image_length > 0) super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET; super->size = size; memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature)); super->fsid.crc = crc32(0L, Z_NULL, 0); super->fsid.edition = opt_edition; super->fsid.blocks = total_blocks; super->fsid.files = total_nodes; memset(super->name, 0x00, sizeof(super->name)); if (opt_name) strncpy(super->name, opt_name, sizeof(super->name)); else strncpy(super->name, "Compressed", sizeof(super->name)); super->root.mode = root->mode; super->root.uid = root->uid; super->root.gid = root->gid; super->root.size = root->size; super->root.offset = offset >> 2; return offset; } static void set_data_offset(struct entry *entry, char *base, unsigned long offset) { struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset); if ((offset & 3) != 0) { die(MKFS_ERROR, 0, "illegal offset of %lu bytes", offset); } if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) { die(MKFS_ERROR, 0, "filesystem too big"); } inode->offset = (offset >> 2); } /* * TODO: Does this work for chars >= 0x80? Most filesystems use UTF-8 * encoding for filenames, whereas the console is a single-byte * character set like iso-latin-1. */ static void print_node(struct entry *e) { char info[10]; char type = '?'; if (S_ISREG(e->mode)) type = 'f'; else if (S_ISDIR(e->mode)) type = 'd'; else if (S_ISLNK(e->mode)) type = 'l'; else if (S_ISCHR(e->mode)) type = 'c'; else if (S_ISBLK(e->mode)) type = 'b'; else if (S_ISFIFO(e->mode)) type = 'p'; else if (S_ISSOCK(e->mode)) type = 's'; if (S_ISCHR(e->mode) || (S_ISBLK(e->mode))) { /* major/minor numbers can be as high as 2^12 or 4096 */ snprintf(info, 10, "%4d,%4d", major(e->size), minor(e->size)); } else { /* size be as high as 2^24 or 16777216 */ snprintf(info, 10, "%9d", e->size); } printf("%c %04o %s %5d:%-3d %s\n", type, e->mode & ~S_IFMT, info, e->uid, e->gid, e->name); } /* * We do a width-first printout of the directory * entries, using a stack to remember the directories * we've seen. */ static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset) { int stack_entries = 0; int stack_size = 64; struct entry **entry_stack; entry_stack = malloc(stack_size * sizeof(struct entry *)); if (!entry_stack) { die(MKFS_ERROR, 1, "malloc failed"); } if (opt_verbose) { printf("root:\n"); } for (;;) { int dir_start = stack_entries; while (entry) { struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset); size_t len = strlen(entry->name); entry->dir_offset = offset; inode->mode = entry->mode; inode->uid = entry->uid; inode->gid = entry->gid; inode->size = entry->size; inode->offset = 0; /* Non-empty directories, regfiles and symlinks will write over inode->offset later. */ offset += sizeof(struct cramfs_inode); total_nodes++; /* another node */ memcpy(base + offset, entry->name, len); /* Pad up the name to a 4-byte boundary */ while (len & 3) { *(base + offset + len) = '\0'; len++; } inode->namelen = len >> 2; offset += len; if (opt_verbose) print_node(entry); if (entry->child) { if (stack_entries >= stack_size) { stack_size *= 2; entry_stack = realloc(entry_stack, stack_size * sizeof(struct entry *)); if (!entry_stack) { die(MKFS_ERROR, 1, "realloc failed"); } } entry_stack[stack_entries] = entry; stack_entries++; } entry = entry->next; } /* * Reverse the order the stack entries pushed during * this directory, for a small optimization of disk * access in the created fs. This change makes things * `ls -UR' order. */ { struct entry **lo = entry_stack + dir_start; struct entry **hi = entry_stack + stack_entries; struct entry *tmp; while (lo < --hi) { tmp = *lo; *lo++ = *hi; *hi = tmp; } } /* Pop a subdirectory entry from the stack, and recurse. */ if (!stack_entries) break; stack_entries--; entry = entry_stack[stack_entries]; set_data_offset(entry, base, offset); if (opt_verbose) { printf("%s:\n", entry->name); } entry = entry->child; } free(entry_stack); return offset; } static int is_zero(char const *begin, unsigned len) { /* Returns non-zero iff the first LEN bytes from BEGIN are all NULs. */ return (len-- == 0 || (begin[0] == '\0' && (len-- == 0 || (begin[1] == '\0' && (len-- == 0 || (begin[2] == '\0' && (len-- == 0 || (begin[3] == '\0' && memcmp(begin, begin + 4, len) == 0)))))))); } /* * One 4-byte pointer per block and then the actual blocked * output. The first block does not need an offset pointer, * as it will start immediately after the pointer block; * so the i'th pointer points to the end of the i'th block * (i.e. the start of the (i+1)'th block or past EOF). * * Note that size > 0, as a zero-sized file wouldn't ever * have gotten here in the first place. */ static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size) { unsigned long original_size = size; unsigned long original_offset = offset; unsigned long new_size; unsigned long blocks = (size - 1) / blksize + 1; unsigned long curr = offset + 4 * blocks; int change; total_blocks += blocks; do { unsigned long len = 2 * blksize; unsigned int input = size; int err; if (input > blksize) input = blksize; size -= input; if (!(opt_holes && is_zero (uncompressed, input))) { err = compress2(base + curr, &len, uncompressed, input, Z_BEST_COMPRESSION); if (err != Z_OK) { die(MKFS_ERROR, 0, "compression error: %s", zError(err)); } curr += len; } uncompressed += input; if (len > blksize*2) { /* (I don't think this can happen with zlib.) */ die(MKFS_ERROR, 0, "AIEEE: block \"compressed\" to > 2*blocklength (%ld)", len); } *(u32 *) (base + offset) = curr; offset += 4; } while (size); curr = (curr + 3) & ~3; new_size = curr - original_offset; /* TODO: Arguably, original_size in these 2 lines should be st_blocks * 512. But if you say that then perhaps administrative data should also be included in both. */ change = new_size - original_size; if (opt_verbose > 1) { printf("%6.2f%% (%+d bytes)\t%s\n", (change * 100) / (double) original_size, change, name); } return curr; } /* * Traverse the entry tree, writing data for every item that has * non-null entry->path (i.e. every non-empty regfile) and non-null * entry->uncompressed (i.e. every symlink). */ static unsigned int write_data(struct entry *entry, char *base, unsigned int offset) { do { if (entry->path || entry->uncompressed) { if (entry->same) { set_data_offset(entry, base, entry->same->offset); entry->offset = entry->same->offset; } else { set_data_offset(entry, base, offset); entry->offset = offset; map_entry(entry); offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size); unmap_entry(entry); } } else if (entry->child) offset = write_data(entry->child, base, offset); entry=entry->next; } while (entry); return offset; } static unsigned int write_file(char *file, char *base, unsigned int offset) { int fd; char *buf; fd = open(file, O_RDONLY); if (fd < 0) { die(MKFS_ERROR, 1, "open failed: %s", file); } buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) { die(MKFS_ERROR, 1, "mmap failed"); } memcpy(base + offset, buf, image_length); munmap(buf, image_length); close (fd); /* Pad up the image_length to a 4-byte boundary */ while (image_length & 3) { *(base + offset + image_length) = '\0'; image_length++; } return (offset + image_length); } int main(int argc, char **argv) { struct stat st; /* used twice... */ struct entry *root_entry; char *rom_image; ssize_t offset, written; int fd; /* initial guess (upper-bound) of required filesystem size */ loff_t fslen_ub = sizeof(struct cramfs_super); char const *dirname, *outfile; u32 crc; int c; /* for getopt */ char *ep; /* for strtoul */ total_blocks = 0; if (argc) progname = argv[0]; /* command line options */ while ((c = getopt(argc, argv, "hEe:i:n:psvz")) != EOF) { switch (c) { case 'h': usage(MKFS_OK); case 'E': opt_errors = 1; break; case 'e': errno = 0; opt_edition = strtoul(optarg, &ep, 10); if (errno || optarg[0] == '\0' || *ep != '\0') usage(MKFS_USAGE); break; case 'i': opt_image = optarg; if (lstat(opt_image, &st) < 0) { die(MKFS_ERROR, 1, "lstat failed: %s", opt_image); } image_length = st.st_size; /* may be padded later */ fslen_ub += (image_length + 3); /* 3 is for padding */ break; case 'n': opt_name = optarg; break; case 'p': opt_pad = PAD_SIZE; fslen_ub += PAD_SIZE; break; case 's': /* old option, ignored */ break; case 'v': opt_verbose++; break; case 'z': opt_holes = 1; break; } } if ((argc - optind) != 2) usage(MKFS_USAGE); dirname = argv[optind]; outfile = argv[optind + 1]; if (stat(dirname, &st) < 0) { die(MKFS_USAGE, 1, "stat failed: %s", dirname); } fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { die(MKFS_USAGE, 1, "open failed: %s", outfile); } root_entry = calloc(1, sizeof(struct entry)); if (!root_entry) { die(MKFS_ERROR, 1, "calloc failed"); } root_entry->mode = st.st_mode; root_entry->uid = st.st_uid; root_entry->gid = st.st_gid; root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub); /* always allocate a multiple of blksize bytes because that's what we're going to write later on */ fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1; if (fslen_ub > MAXFSLEN) { fprintf(stderr, "warning: estimate of required size (upper bound) is %LdMB, but maximum image size is %uMB, we might die prematurely\n", fslen_ub >> 20, MAXFSLEN >> 20); fslen_ub = MAXFSLEN; } /* find duplicate files. TODO: uses the most inefficient algorithm possible. */ eliminate_doubles(root_entry, root_entry); /* TODO: Why do we use a private/anonymous mapping here followed by a write below, instead of just a shared mapping and a couple of ftruncate calls? Is it just to save us having to deal with removing the file afterwards? If we really need this huge anonymous mapping, we ought to mmap in smaller chunks, so that the user doesn't need nn MB of RAM free. If the reason is to be able to write to un-mmappable block devices, then we could try shared mmap and revert to anonymous mmap if the shared mmap fails. */ rom_image = mmap(NULL, fslen_ub?fslen_ub:1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (rom_image == MAP_FAILED) { die(MKFS_ERROR, 1, "mmap failed"); } /* Skip the first opt_pad bytes for boot loader code */ offset = opt_pad; memset(rom_image, 0x00, opt_pad); /* Skip the superblock and come back to write it later. */ offset += sizeof(struct cramfs_super); /* Insert a file image. */ if (opt_image) { printf("Including: %s\n", opt_image); offset = write_file(opt_image, rom_image, offset); } offset = write_directory_structure(root_entry->child, rom_image, offset); printf("Directory data: %d bytes\n", offset); offset = write_data(root_entry, rom_image, offset); /* We always write a multiple of blksize bytes, so that losetup works. */ offset = ((offset - 1) | (blksize - 1)) + 1; printf("Everything: %d kilobytes\n", offset >> 10); /* Write the superblock now that we can fill in all of the fields. */ write_superblock(root_entry, rom_image+opt_pad, offset); printf("Super block: %d bytes\n", sizeof(struct cramfs_super)); /* Put the checksum in. */ crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, (rom_image+opt_pad), (offset-opt_pad)); ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc; printf("CRC: %x\n", crc); /* Check to make sure we allocated enough space. */ if (fslen_ub < offset) { die(MKFS_ERROR, 0, "not enough space allocated for ROM image (%Ld allocated, %d used)", fslen_ub, offset); } written = write(fd, rom_image, offset); if (written < 0) { die(MKFS_ERROR, 1, "write failed"); } if (offset != written) { die(MKFS_ERROR, 0, "ROM image write failed (wrote %d of %d bytes)", written, offset); } /* (These warnings used to come at the start, but they scroll off the screen too quickly.) */ if (warn_namelen) fprintf(stderr, /* bytes, not chars: think UTF-8. */ "warning: filenames truncated to %d bytes (possibly less if multi-byte UTF-8)\n", CRAMFS_MAXPATHLEN); if (warn_skip) fprintf(stderr, "warning: files were skipped due to errors\n"); if (warn_size) fprintf(stderr, "warning: file sizes truncated to %luMB (minus 1 byte)\n", 1L << (CRAMFS_SIZE_WIDTH - 20)); if (warn_uid) /* (not possible with current Linux versions) */ fprintf(stderr, "warning: uids truncated to %u bits (this may be a security concern)\n", CRAMFS_UID_WIDTH); if (warn_gid) fprintf(stderr, "warning: gids truncated to %u bits (this may be a security concern)\n", CRAMFS_GID_WIDTH); if (warn_dev) fprintf(stderr, "WARNING: device numbers truncated to %u bits (this almost certainly means\n" "that some device files will be wrong)\n", CRAMFS_OFFSET_WIDTH); if (opt_errors && (warn_namelen||warn_skip||warn_size||warn_uid||warn_gid||warn_dev)) exit(MKFS_ERROR); exit(MKFS_OK); } /* * Local variables: * c-file-style: "linux" * End: */ ================================================ FILE: src/cramfsswap/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/cramfsswap/Makefile ================================================ #!/usr/bin/make -f all: cramfsswap strip debian: cramfsswap cramfsswap: cramfsswap.c gcc -Wall -g -O -o cramfsswap cramfsswap.c -lz strip: strip cramfsswap install: cramfsswap install cramfsswap $(DESTDIR)/usr/bin clean: rm -f cramfsswap ================================================ FILE: src/cramfsswap/README ================================================ cramfsswap - swap endianess of a cram filesystem (cramfs) version 1.1 cramfs is a highly compressed and size optimized linux filesystem which is mainly used for embedded applications. the problem with cramfs is that it is endianess sensitive, meaning you can't mount a cramfs for a big endian target on a little endian machine and vice versa. this is often especially a problem in the development phase. cramfsswap solves that problem by allowing you to swap to endianess of a cramfs filesystem. changelog: v1.0 2004-12-01 first release v1.1 2005-01-04 added correct recalculation of crc, thanks to joerg dorchain ================================================ FILE: src/cramfsswap/cramfsswap.1 ================================================ .TH cramfsswap 1 "4 Jan 2005" Linux "User Manuals" .SH NAME cramfsswap \- swap endianess of a cram filesystem (cramfs) .SH SYNOPSIS .B cramfsswap .SH DESCRIPTION cramfs is a highly compressed and size optimized linux filesystem which is mainly used for embedded applications. the problem with cramfs is that it is endianess sensitive, meaning you can't mount a cramfs for a big endian target on a little endian machine and vice versa. this is often especially a problem in the development phase. cramfsswap solves that problem by allowing you to swap to endianess of a cramfs filesystem. .SH AUTHOR Michael Holzt .SH VERSION 20050104 ================================================ FILE: src/cramfsswap/cramfsswap.c ================================================ /* cramfsswap - swaps endian of a cramfs file last modified on 2006-11-08 by kju Copyright (c) 2004-2006 by Michael Holzt, kju -at- fqdn.org To be distributed under the terms of the GPL2 license. */ #include #include #include #include #include #include /* for crc32 */ #include #include #include #include #define BUFFERSIZE 16384 #define MAXFILES 4096 #define BLKSIZE 4096 /* Should this be a command line option? */ int main(int argc, char *argv[]) { uint32_t superblock_in[16], superblock_out[16], flags, blockpointer_in, blockpointer_out, blockpointer_last, crc, *mapping; uint16_t endiantest; uint8_t inode_in[12], inode_out[12]; struct cramfs_inode inode; unsigned int filecnt, file, filepos, remaining, nblocks, copybytes, readbytes, x; unsigned int *fileoffset, *filesize; unsigned char buffer[BUFFERSIZE], is_hostorder, host_is_le, file_is_le; int infile, outfile; int size; if ( argc != 3 ) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } if ( (infile=open(argv[1],O_RDONLY)) < 0 ) { perror("while trying to open binary input file"); exit(1); } if ( (outfile=open(argv[2], O_RDWR|O_TRUNC|O_CREAT, 0644)) < 0 ) { perror("while trying to open image output file"); exit(1); } if ( read(infile, &superblock_in, sizeof(superblock_in)) != sizeof(superblock_in) ) { perror("while trying to read superblock"); exit(1); } /* Detect endianness of host */ endiantest = 1; if ( ((uint8_t *)&endiantest)[0] == 1 ) host_is_le = 1; else host_is_le = 0; /* Detect endianness of file */ if ( superblock_in[0] == CRAMFS_MAGIC ) { is_hostorder = 1; file_is_le = host_is_le; } else if ( superblock_in[0] == bswap_32(CRAMFS_MAGIC) ) { is_hostorder = 0; file_is_le = !(host_is_le); } else { fprintf(stderr, "cramfs magic not detected\n"); exit(1); } if ( file_is_le ) printf("Filesystem is little endian, will be converted to big endian.\n"); else printf("Filesystem is big endian, will be converted to little endian.\n"); /* Swap Superblock */ superblock_out[ 0] = bswap_32(superblock_in[ 0]); /* Magic */ superblock_out[ 1] = bswap_32(superblock_in[ 1]); /* Size */ superblock_out[ 2] = bswap_32(superblock_in[ 2]); /* Flags */ superblock_out[ 3] = bswap_32(superblock_in[ 3]); /* Future Use */ superblock_out[ 4] = superblock_in[ 4] ; /* Sig 1/4 */ superblock_out[ 5] = superblock_in[ 5] ; /* Sig 2/4 */ superblock_out[ 6] = superblock_in[ 6] ; /* Sig 3/4 */ superblock_out[ 7] = superblock_in[ 7] ; /* Sig 4/4 */ superblock_out[ 8] = bswap_32(superblock_in[ 8]); /* fsid crc */ superblock_out[ 9] = bswap_32(superblock_in[ 9]); /* fsid edition */ superblock_out[10] = bswap_32(superblock_in[10]); /* fsid blocks */ superblock_out[11] = bswap_32(superblock_in[11]); /* fsid files */ superblock_out[12] = superblock_in[12] ; /* Name 1/4 */ superblock_out[13] = superblock_in[13] ; /* Name 2/4 */ superblock_out[14] = superblock_in[14] ; /* Name 3/4 */ superblock_out[15] = superblock_in[15] ; /* Name 4/4 */ write(outfile, &superblock_out, sizeof(superblock_out)); /* Check Flags */ if ( is_hostorder) flags = superblock_in[2]; else flags = superblock_out[2]; /* I'm not sure about the changes between v1 and v2. So for now don't support v1. */ if ( (flags & 0x1) == 0 ) { fprintf(stderr,"Error: Not cramfs version 2!\n"); exit(1); } /* This should be done later */ if ( flags & 0x100 ) { fprintf(stderr,"Error: Filesystem contains holes (not supported yet)\n"); exit(1); } /* Do we really need this? */ if ( flags & 0x400 ) { fprintf(stderr,"Error: Filesystem has shifted root fs flag (not supported)\n"); exit(1); } /* Something else? */ if ( flags & 0xFFFFFFFC ) { fprintf(stderr,"Error: Filesystem has unknown/unsupported flag set!\n"); exit(1); } /* Get Filecounter (which is number of file entries plus 1 (for the root inode) */ if ( is_hostorder ) filecnt = superblock_in[11]; else filecnt = superblock_out[11]; printf("Filesystem contains %d files.\n", filecnt-1); fileoffset = (unsigned int*)malloc( filecnt * sizeof( *fileoffset )); if( fileoffset == NULL ){ perror("fileoffset malloc error"); exit(1); } filesize = (unsigned int*)malloc( filecnt * sizeof( *filesize )); if( filesize == NULL ){ free( fileoffset ); fileoffset = NULL; perror("filesize malloc error"); exit(1); } /* Set filepos (in words) */ filepos = 16; /* Initialise the counter for the "real" (stored) files */ remaining = 0; /* Read directory entries (first one is the root inode) */ for ( file=0; file> 6 ); inode_out[ 9] = ( (inode_in[11]&0x3F) << 2 ) | ( (inode_in[10]&0xC0) >> 6 ); inode_out[10] = ( (inode_in[10]&0x3F) << 2 ) | ( (inode_in[ 9]&0xC0) >> 6 ); inode_out[11] = ( (inode_in[ 9]&0x3F) << 2 ) | ( (inode_in[ 8]&0xC0) >> 6 ); } else { inode_out[ 8] = ( (inode_in[ 8]&0xFD) >> 2 ) | ( (inode_in[11]&0x03) << 6 ); inode_out[ 9] = ( (inode_in[11]&0xFD) >> 2 ) | ( (inode_in[10]&0x03) << 6 ); inode_out[10] = ( (inode_in[10]&0xFD) >> 2 ) | ( (inode_in[ 9]&0x03) << 6 ); inode_out[11] = ( (inode_in[ 9]&0xFD) >> 2 ) | ( (inode_in[ 8]&0x03) << 6 ); } if ( is_hostorder ) { /* copy the input for our use */ memcpy(&inode, &inode_in, sizeof(inode_in)); } else { /* copy the output for our use */ memcpy(&inode, &inode_out, sizeof(inode_in)); } /* write the converted inode */ write(outfile, &inode_out, sizeof(inode_out)); /* Copy filename */ if ( read(infile, &buffer, inode.namelen<<2) != inode.namelen<<2 ) { perror("while trying to read filename"); exit(1); } write(outfile, &buffer, inode.namelen<<2); /* Store the file size and file offset */ filesize [file] = inode.size; fileoffset[file] = inode.offset; /* filepos is increased by namelen words + 3 words for the inode */ filepos += inode.namelen + 3; /* Has this entry a data chunk? */ if ( ( S_ISREG(inode.mode) || S_ISLNK(inode.mode) ) && inode.size > 0 ) { remaining++; } } /* Now process the individual files data. Because cramfs will share the compressed data for two identical input files, we do this by starting at the begin of the data, identifiying the accompanying file, process the file data, and move to the next until no file is left */ while ( remaining ) { /* Find the file */ for ( file=1; fileoffset[file]!=filepos&&file0) { readbytes = (copybytes>BUFFERSIZE) ? BUFFERSIZE : copybytes; if ( read(infile, &buffer, readbytes) != readbytes ) { perror("while trying to read file data"); exit(1); } write(outfile, &buffer, readbytes); copybytes -= readbytes; } /* Set new filepos */ filepos = (blockpointer_last)>>2; } /* Copy the remaining data (padding) */ do { readbytes = read(infile, &buffer, BUFFERSIZE); write(outfile, &buffer, readbytes); } while ( readbytes>0 ); /* recalculate the crc */ size = lseek(outfile, 0, SEEK_CUR); /* should not fail */ mapping = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, outfile, 0); if (mapping != MAP_FAILED) { crc = crc32(0L, Z_NULL, 0); mapping[8] = is_hostorder?bswap_32(crc):crc; crc = crc32(crc, (unsigned char *)mapping, size); printf("CRC: 0x%08x\n", crc); mapping[8] = is_hostorder?bswap_32(crc):crc; munmap(mapping, size); } else { perror("mapping failed"); } /* Done! */ close(infile); close(outfile); exit(0); } ================================================ FILE: src/cramfsswap/debian/changelog ================================================ cramfsswap (1.4.1) unstable; urgency=low * Changed build rules: Do not strip in makefile when building for debian, instead will be stripped by dh_strip invocation in debian/rules thus honoring nostrip option correctly (closes: Bug#436671). -- Michael Holzt Sun, 14 Oct 2007 23:38:41 +0200 cramfsswap (1.4) unstable; urgency=low * cramfsswap can now handle cramfs filesystems with more than 4095 files thanks to a patch by Nobuhiro Iwamatsu (closes: Bug#440060). -- Michael Holzt Sun, 14 Oct 2007 22:03:07 +0200 cramfsswap (1.3.1) unstable; urgency=low * Corrected beginning of source (GPL-Notice, last modified) -- Michael Holzt Wed, 8 Nov 2006 16:36:19 +0100 cramfsswap (1.3) unstable; urgency=low * Corrected swapping on big endian architecture (closes: Bug#345723). * Skipped version 1.2 due to incorrectly handled NMU. :-( * Clarified license information. Only GPL2 does apply, no GPL3! -- Michael Holzt Wed, 8 Nov 2006 14:10:27 +0100 cramfsswap (1.2) unstable; urgency=low * NMU * Patch from Andreas Jochens to fix FTBFS on unstable due to missing u32 declaration. Closes: #392166 -- Joey Hess Tue, 17 Oct 2006 15:50:08 -0400 cramfsswap (1.1) unstable; urgency=low * Initial Release. -- Michael Holzt Tue, 4 Jan 2005 12:26:00 +0100 ================================================ FILE: src/cramfsswap/debian/compat ================================================ 4 ================================================ FILE: src/cramfsswap/debian/control ================================================ Source: cramfsswap Section: utils Priority: extra Maintainer: Michael Holzt Build-Depends: debhelper (>= 4.1.16), zlib1g-dev Standards-Version: 3.7.2 Package: cramfsswap Architecture: any Depends: ${shlibs:Depends} Description: swap endianess of a cram filesystem (cramfs) cramfs is a highly compressed and size optimized linux filesystem which is mainly used for embedded applications. the problem with cramfs is that it is endianess sensitive, meaning you can't mount a cramfs for a big endian target on a little endian machine and vice versa. this is often especially a problem in the development phase. . cramfsswap solves that problem by allowing you to swap to endianess of a cramfs filesystem. ================================================ FILE: src/cramfsswap/debian/copyright ================================================ This package was debianized by Michael Holzt on Tue, 4 Jan 2005 12:26:00 +0100. This is a native debian package, debian maintainer and upstream author are the same person. The source can be downloaded from http://kju.de/projekte/cramfsswap/ (sorry, German only) License: cramfsswap is released under the GNU GPL license as free, open source software. Hopefully it will seem useful to someone. NO WARRANTY. GPL2 only! On Debian GNU/Linux systems, the complete text of the GNU General Public License can be found in '/usr/share/common-licenses/GPL'. ================================================ FILE: src/cramfsswap/debian/dirs ================================================ usr/bin usr/sbin ================================================ FILE: src/cramfsswap/debian/docs ================================================ README ================================================ FILE: src/cramfsswap/debian/rules ================================================ #!/usr/bin/make -f # # debian/rules for cramfsswap # # modelled after the debhelper example # # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 build: build-stamp build-stamp: dh_testdir $(MAKE) debian touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp -$(MAKE) clean dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs $(MAKE) install DESTDIR=$(CURDIR)/debian/cramfsswap # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installchangelogs dh_installdocs dh_installman cramfsswap.1 dh_link dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install ================================================ FILE: src/crcalc/Makefile ================================================ CC=gcc CFLAGS=-Wall TARGET=crcalc $(TARGET): patch.o $(CC) $(CFLAGS) $(LDFLAGS) $(TARGET).c *.o -o $(TARGET) patch.o: crc.o md5.o $(CC) $(CFLAGS) $(LDFLAGS) patch.c -c crc.o: $(CC) $(CFLAGS) $(LDFLAGS) crc.c -c md5.o: $(CC) $(CFLAGS) $(LDFLAGS) md5.c -c clean: rm -f *.o $(TARGET) ================================================ FILE: src/crcalc/README ================================================ DESCRIPTION CRCalc re-calculates and updates the CRC fields of uImage, TRX, and DLOB firmware headers. CRCalc can update multiple headers inside a firmware image if you provide it with a list of offsets for each header inside the firmware image. The list file can be a binwalk log or just a list of decimal offsets (one offset per line). If no binwalk log or list file is provided, CRCalc assumes that there is only one header at the very beginning of the target firmware image. USAGE Basic usage: $ crcalc firmware.img Usage with a binwalk log / offset list file: $ crcalc firmware.img binwalk.log ================================================ FILE: src/crcalc/crc.c ================================================ #include "crc.h" /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32(char *buf, size_t len) { uint32_t crc; crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc; } ================================================ FILE: src/crcalc/crc.h ================================================ #ifndef _CRC_H_ #define _CRC_H_ #include #include uint32_t crc32(char *buf, size_t len); #endif ================================================ FILE: src/crcalc/crcalc.c ================================================ /* * Utility for calculating and patching checksums in various files. */ #include #include #include #include #include #include #include #include "crcalc.h" #include "patch.h" int main(int argc, char *argv[]) { int retval = EXIT_FAILURE, ok = 0, fail = 1, n = 0, i = 0, offset = 0; int offsets[MAX_HEAD_SIZE] = { 0 }; char *buf = NULL, *ptr = NULL, *fname = NULL, *log = NULL; size_t size = 0, nsize = 0; /* Check usage */ if(argc < 2 || argv[1][0] == '-') { fprintf(stderr, USAGE, argv[0]); goto end; } else { fname = argv[1]; if(argc == 3) { log = argv[2]; } } /* Read in target file */ buf = file_read(fname, &size); if(buf && size > MIN_FILE_SIZE) { /* Parse in the log file, if any */ n = parse_log(log, offsets); fprintf(stderr, "Processing %d header(s) from %s...\n", n, fname); /* Loop through each offset in the integer array */ for(i=0; i= MIN_NON_WHITE) { retval = 0; break; } } return retval; } /* Reads in and returns the contents and size of a given file */ char *file_read(char *file, size_t *fsize) { int fd = 0; struct stat _fstat = { 0 }; char *buffer = NULL; if(stat(file, &_fstat) == -1) { perror(file); goto end; } if(_fstat.st_size == 0) { fprintf(stderr, "%s: zero size file\n", file); goto end; } fd = open(file,O_RDONLY); if(!fd) { perror(file); goto end; } buffer = malloc(_fstat.st_size); if(!buffer) { perror("malloc"); goto end; } memset(buffer, 0 ,_fstat.st_size); if(read(fd, buffer, _fstat.st_size) != _fstat.st_size) { perror(file); if(buffer) free(buffer); buffer = NULL; } else { *fsize = _fstat.st_size; } end: if(fd) close(fd); return buffer; } /* Write size bytes from buf to file fname */ int file_write(char *fname, char *buf, size_t size) { FILE *fp = NULL; int retval = 0; fp = fopen(fname, "w"); if(fp) { if(fwrite(buf, 1, size, fp) == size) { retval = 1; } fclose(fp); } else { perror("fopen"); } return retval; } /* Identifies the header type used in the supplied file */ enum header_type identify_header(char *buf) { enum header_type retval = UNKNOWN; uint32_t *sig = NULL; sig = (uint32_t *) buf; switch(*sig) { case TRX_MAGIC: retval = TRX; break; case UIMAGE_MAGIC: retval = UIMAGE; break; case DLOB_MAGIC: retval = DLOB; break; default: break; } return retval; } ================================================ FILE: src/crcalc/crcalc.h ================================================ #ifndef _CRCALC_H_ #define _CRCALC_H_ #include #define MIN_FILE_SIZE 4 #define MAX_LINE_SIZE 8096 #define MAX_HEAD_SIZE 512 #define HEADER_ID_STR "header" #define MIN_NON_WHITE '!' #define MAX_STR_SIZE 10 #define MIN_STR_SIZE 1 #define USAGE "\n\ crcalc v0.2 - (c) 2011, Craig Heffner\n\ Re-calculates firmware header checksusms for TRX and uImage firmware headers.\n\ \n\ Usage: %s [binwalk log file]\n\ \n\ If no binwalk log file is specified, the header is assumed to be at the beginning of the firmware image.\n\ \n" enum header_type { UNKNOWN, TRX, UIMAGE, DLOB, }; int parse_log(char *file, int offsets[MAX_HEAD_SIZE]); int is_whitespace(char *string); char *file_read(char *file, size_t *fsize); int file_write(char *fname, char *buf, size_t size); enum header_type identify_header(char *buf); #endif ================================================ FILE: src/crcalc/md5.c ================================================ /* * Added md5_string function for ease of use with Binwalk. * * Original file obtained from: http://cr.yp.to/2004-494/gaim/0.81-src/md5.c * * Craig Heffner */ /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321. It is derived directly from the text of the RFC and not from the reference implementation. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include "md5.h" #include #include /* Needed for snprintf call in md5_string() */ #ifdef TEST /* * Compile with -DTEST to create a self-contained executable test program. * The test program should print out the same values as given in section * A.5 of RFC 1321, reproduced below. */ #include main() { static const char *const test[7] = { "", /*d41d8cd98f00b204e9800998ecf8427e*/ "945399884.61923487334tuvga", /*0cc175b9c0f1b6a831c399e269772661*/ "abc", /*900150983cd24fb0d6963f7d28e17f72*/ "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/ "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", /*d174ab98d277d9f5a5611c2c9f419d9f*/ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/ }; int i; for (i = 0; i < 7; ++i) { md5_state_t state; md5_byte_t digest[16]; int di; md5_init(&state); md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); md5_finish(&state, digest); printf("MD5 (\"%s\") = ", test[i]); for (di = 0; di < 16; ++di) printf("%02x", digest[di]); printf(" :: MD5 string: %s", md5_string((void *) test[i],strlen(test[i]))); printf("\n"); } return 0; } #endif /* TEST */ /* Returns the MD5 checksum string of a given file */ char *md5_string(void *data, size_t data_size) { int i = 0; int byte_str_size = 2; int md5_hash_length = 16; int str_size = ((md5_hash_length*byte_str_size)+1); /* MD5 is 16 bytes at 2 characters per byte, plus trailing NULL */ char *md5str = NULL; md5_state_t state; md5_byte_t digest[md5_hash_length]; md5str = malloc(str_size); if(!md5str) { perror("malloc"); } else { memset(md5str,0,str_size); md5_init(&state); md5_append(&state, (const md5_byte_t *) data, data_size); md5_finish(&state, digest); for(i = 0; i < md5_hash_length; i++) { snprintf(md5str+(byte_str_size*i),byte_str_size+1,"%02x",digest[i]); } } return md5str; } /* * For reference, here is the program that computed the T values. */ #if 0 #include main() { int i; for (i = 1; i <= 64; ++i) { unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); printf("#define T%d 0x%08lx\n", i, v); } return 0; } #endif /* * End of T computation program. */ #define T1 0xd76aa478 #define T2 0xe8c7b756 #define T3 0x242070db #define T4 0xc1bdceee #define T5 0xf57c0faf #define T6 0x4787c62a #define T7 0xa8304613 #define T8 0xfd469501 #define T9 0x698098d8 #define T10 0x8b44f7af #define T11 0xffff5bb1 #define T12 0x895cd7be #define T13 0x6b901122 #define T14 0xfd987193 #define T15 0xa679438e #define T16 0x49b40821 #define T17 0xf61e2562 #define T18 0xc040b340 #define T19 0x265e5a51 #define T20 0xe9b6c7aa #define T21 0xd62f105d #define T22 0x02441453 #define T23 0xd8a1e681 #define T24 0xe7d3fbc8 #define T25 0x21e1cde6 #define T26 0xc33707d6 #define T27 0xf4d50d87 #define T28 0x455a14ed #define T29 0xa9e3e905 #define T30 0xfcefa3f8 #define T31 0x676f02d9 #define T32 0x8d2a4c8a #define T33 0xfffa3942 #define T34 0x8771f681 #define T35 0x6d9d6122 #define T36 0xfde5380c #define T37 0xa4beea44 #define T38 0x4bdecfa9 #define T39 0xf6bb4b60 #define T40 0xbebfbc70 #define T41 0x289b7ec6 #define T42 0xeaa127fa #define T43 0xd4ef3085 #define T44 0x04881d05 #define T45 0xd9d4d039 #define T46 0xe6db99e5 #define T47 0x1fa27cf8 #define T48 0xc4ac5665 #define T49 0xf4292244 #define T50 0x432aff97 #define T51 0xab9423a7 #define T52 0xfc93a039 #define T53 0x655b59c3 #define T54 0x8f0ccc92 #define T55 0xffeff47d #define T56 0x85845dd1 #define T57 0x6fa87e4f #define T58 0xfe2ce6e0 #define T59 0xa3014314 #define T60 0x4e0811a1 #define T61 0xf7537e82 #define T62 0xbd3af235 #define T63 0x2ad7d2bb #define T64 0xeb86d391 static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #ifndef ARCH_IS_BIG_ENDIAN # define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ #endif #if ARCH_IS_BIG_ENDIAN /* * On big-endian machines, we must arrange the bytes in the right * order. (This also works on machines of unknown byte order.) */ md5_word_t X[16]; const md5_byte_t *xp = data; int i; for (i = 0; i < 16; ++i, xp += 4) X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); #else /* !ARCH_IS_BIG_ENDIAN */ /* * On little-endian machines, we can process properly aligned data * without copying it. */ md5_word_t xbuf[16]; const md5_word_t *X; if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } #endif #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = 0xefcdab89; pms->abcd[2] = 0x98badcfe; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } ================================================ FILE: src/crcalc/md5.h ================================================ /* * Added md5_string function prototype for ease of use with Binwalk. * * Original file obtained from: http://cr.yp.to/2004-494/gaim/0.81-src/md5.h * * Craig Heffner */ /* Copyright (C) 1999 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321. It is derived directly from the text of the RFC and not from the reference implementation. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #ifndef md5_INCLUDED # define md5_INCLUDED /* * This code has some adaptations for the Ghostscript environment, but it * will compile and run correctly in any environment with 8-bit chars and * 32-bit ints. Specifically, it assumes that if the following are * defined, they have the same meaning as in Ghostscript: P1, P2, P3, * ARCH_IS_BIG_ENDIAN. */ #include typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #ifdef __cplusplus extern "C" { #endif /* Initialize the algorithm. */ #ifdef P1 void md5_init(P1(md5_state_t *pms)); #else void md5_init(md5_state_t *pms); #endif /* Append a string to the message. */ #ifdef P3 void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes)); #else void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); #endif /* Finish the message and return the digest. */ #ifdef P2 void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16])); #else void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); #endif /* Returns the MD5 checksum string of a given file */ char *md5_string(void *data, size_t data_size); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ ================================================ FILE: src/crcalc/patch.c ================================================ #include #include #include "patch.h" #include "crc.h" #include "md5.h" /* Update the CRC for a TRX file */ int patch_trx(char *buf, size_t size) { int retval = 0; struct trx_header *header = NULL; header = (struct trx_header *) buf; header->crc32 = 0; /* Sanity check on the header length field */ if(header->len <= size) { /* Checksum is calculated over the image, plus the header offsets (12 bytes into the TRX header) */ header->crc32 = crc32(buf+12, (header->len-12)); if(header->crc32 != 0) { retval = 1; } } return retval; } /* Update both CRCs for uImage files */ int patch_uimage(char *buf, size_t size) { int retval = 0; uint32_t hlen = 0; struct uimage_header *header = NULL; header = (struct uimage_header *) buf; hlen = ntohl(header->ih_size); if(hlen <= size) { header->ih_hcrc = 0; header->ih_dcrc = 0; header->ih_dcrc = crc32(buf+sizeof(struct uimage_header), hlen) ^ 0xFFFFFFFFL; header->ih_dcrc = htonl(header->ih_dcrc); header->ih_hcrc = crc32(buf, sizeof(struct uimage_header)) ^ 0xFFFFFFFFL; header->ih_hcrc = htonl(header->ih_hcrc); if(header->ih_dcrc != 0 && header->ih_hcrc != 0) { retval = 1; } } return retval; } /* Update the MD5 checksum in the DLOB header */ int patch_dlob(char *buf, size_t size) { md5_state_t state; md5_byte_t digest[16]; int i = 0, retval = 0; uint32_t cksum_header_offset = 0, data_size = 0, data_offset = 0; struct dlob_header *sig_header = NULL, *cksum_header = NULL; sig_header = (struct dlob_header *) buf; cksum_header_offset = sizeof(struct dlob_header) + ntohl(sig_header->header_size) + ntohl(sig_header->data_size); if(cksum_header_offset < size) { cksum_header = (struct dlob_header *) (buf + cksum_header_offset); data_size = ntohl(cksum_header->data_size); data_offset = cksum_header_offset + sizeof(struct dlob_header) + ntohl(cksum_header->header_size) + DLOB_TYPE_STRING_LENGTH; if(data_size < size && (data_size + data_offset) <= size) { md5_init(&state); md5_append(&state, (const md5_byte_t *) (buf + data_offset), data_size); md5_finish(&state, digest); for(i=0; i<16; i++) { buf[cksum_header_offset+sizeof(struct dlob_header)+i] = digest[i]; } retval = 1; } } return retval; } ================================================ FILE: src/crcalc/patch.h ================================================ #ifndef _PATCH_H_ #define _PATCH_H_ #include #define TRX_MAGIC 0x30524448 struct trx_header { uint32_t magic; /* "HDR0" */ uint32_t len; /* Length of file including header */ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[3]; /* Offsets of partitions from start of header */ }; /* Magic bytes are compared in *little* endian */ #define UIMAGE_MAGIC 0x56190527 struct uimage_header { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ uint32_t ih_time; /* Image Creation Timestamp */ uint32_t ih_size; /* Image Data Size */ uint32_t ih_load; /* Data Load Address */ uint32_t ih_ep; /* Entry Point Address */ uint32_t ih_dcrc; /* Image Data CRC Checksum */ uint8_t ih_os; /* Operating System */ uint8_t ih_arch; /* CPU architecture */ uint8_t ih_type; /* Image Type */ uint8_t ih_comp; /* Compression Type */ uint8_t ih_name[32]; /* Image Name */ }; #define DLOB_MAGIC 0x17A4A35E #define DLOB_TYPE_STRING_LENGTH 16 struct dlob_header { uint32_t sig_magic; /* DLOB_MAGIC */ uint32_t header_size; /* Size of the signature header */ uint32_t data_size; /* Flags or an ID value maybe? */ }; int patch_trx(char *buf, size_t size); int patch_uimage(char *buf, size_t size); int patch_dlob(char *buf, size_t size); #endif ================================================ FILE: src/firmware-tools/Makefile ================================================ CC=gcc CFLAGS=-g -Wall TARGET=buffalo-enc $(TARGET): buffalo-enc.o $(CC) $(CFLAGS) $(LDFLAGS) $(TARGET).c *.o -o $(TARGET) buffalo-enc.o: $(CC) $(CFLAGS) $(LDFLAGS) buffalo-lib.c -c clean: rm -f buffalo-enc.o buffalo-lib.o $(TARGET) distclean: clean ================================================ FILE: src/firmware-tools/add_header.c ================================================ /* * add_header.c - partially based on OpenWrt's motorola-bin.c * * Copyright (C) 2008 Imre Kaloz * Gabor Juhos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * The add_header utility used by various vendors preprends the buf * image with a header containing a CRC32 value which is generated for the * model id + reserved space for CRC32 + buf, then replaces the reserved * area with the actual CRC32. This replacement tool mimics this behavior. */ #include #include #include #include #include #include #include #include #include #include #define BPB 8 /* bits/byte */ static uint32_t crc32[1<> 1)) : (crc >> 1); crc32[n] = crc; } } static uint32_t crc32buf(unsigned char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for (; len; len--, buf++) crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB); return ~crc; } struct header { unsigned char model[16]; uint32_t crc; }; static void usage(const char *) __attribute__ (( __noreturn__ )); static void usage(const char *mess) { fprintf(stderr, "Error: %s\n", mess); fprintf(stderr, "Usage: add_header model_id input_file output_file\n"); fprintf(stderr, "\n"); exit(1); } int main(int argc, char **argv) { off_t len; // of original buf off_t buflen; // of the output file int fd; void *input_file; // pointer to the input file (mmmapped) struct header header; unsigned char *buf; // pointer to prefix + copy of original buf // verify parameters if (argc != 4) usage("wrong number of arguments"); // mmap input_file if ((fd = open(argv[2], O_RDONLY)) < 0 || (len = lseek(fd, 0, SEEK_END)) < 0 || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) || close(fd) < 0) { fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno)); exit(1); } buflen = len + sizeof(header); init_crc32(); // copy model name into header strncpy(header.model, argv[1], sizeof(header.model)); header.crc = 0; // create a firmware image in memory and copy the input_file to it buf = malloc(buflen); memcpy(buf, &header, sizeof(header)); memcpy(&buf[sizeof(header)], input_file, len); // CRC of temporary header + buf header.crc = htonl(crc32buf(buf, buflen)); memcpy(buf, &header, sizeof(header)); // write the buf if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0 || write(fd, buf, buflen) != buflen || close(fd) < 0) { fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno)); exit(2); } free(buf); munmap(input_file,len); return 0; } ================================================ FILE: src/firmware-tools/addpattern.c ================================================ /* * Copyright (C) 2004 Manuel Novoa III * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* July 29, 2004 * * This is a hacked replacement for the 'addpattern' utility used to * create wrt54g .bin firmware files. It isn't pretty, but it does * the job for me. * * Extensions: * -v allows setting the version string on the command line. * -{0|1} sets the (currently ignored) hw_ver flag in the header * to 0 or 1 respectively. */ /* January 12, 2005 * * Modified by rodent at rodent dot za dot net * Support added for the new WRT54G v2.2 and WRT54GS v1.1 "flags" * Without the flags set to 0x7, the above units will refuse to flash. * * Extensions: * -{0|1|2} sets {0|1} sets hw_ver flag to 0/1. {2} sets hw_ver to 1 * and adds the new hardware "flags" for the v2.2/v1.1 units */ /* January 1, 2007 * * Modified by juan.i.gonzalez at subdown dot net * Support added for the AG241v2 and similar * * Extensions: * -r #.# adds revision hardware flags. AG241v2 and similar. * * AG241V2 firmware sets the hw_ver to 0x44. * * Example: -r 2.0 * * Convert 2.0 to 20 to be an integer, and add 0x30 to skip special ASCII * #define HW_Version ((HW_REV * 10) + 0x30) -> from cyutils.h */ #include #include #include #include #include #include /**********************************************************************/ #define CODE_ID "U2ND" /* from code_pattern.h */ #define CODE_PATTERN "W54S" /* from code_pattern.h */ #define PBOT_PATTERN "PBOT" #define CYBERTAN_VERSION "v3.37.2" /* from cyutils.h */ /* WRT54G v2.2 and WRT54GS v1.1 "flags" (from 3.37.32 firmware cyutils.h) */ #define SUPPORT_4712_CHIP 0x0001 #define SUPPORT_INTEL_FLASH 0x0002 #define SUPPORT_5325E_SWITCH 0x0004 /* (from 3.00.24 firmware cyutils.h) */ #define SUPPORT_4704_CHIP 0x0008 #define SUPPORT_5352E_CHIP 0x0010 struct code_header { /* from cyutils.h */ char magic[4]; char res1[4]; /* for extra magic */ char fwdate[3]; char fwvern[3]; char id[4]; /* U2ND */ char hw_ver; /* 0: for 4702, 1: for 4712 -- new in 2.04.3 */ unsigned char sn; // Serial Number unsigned char flags[2]; /* SUPPORT_ flags new for 3.37.2 (WRT54G v2.2 and WRT54GS v1.1) */ unsigned char stable[2]; // The image is stable (for dual image) unsigned char try1[2]; // Try to boot image first time (for dual image) unsigned char try2[2]; // Try to boot image second time (for dual image) unsigned char try3[2]; // Try to boot image third time (for dual_image) unsigned char res3[2]; } ; struct board_info { char *id; char *pattern; char hw_ver; char sn; char flags[2]; }; struct board_info boards[] = { { .id = "WRT160NL", .pattern = "NL16", .hw_ver = 0x00, .sn = 0x0f, .flags = {0x3f, 0x00}, }, { /* Terminating entry */ .id = NULL, } }; /**********************************************************************/ void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Usage: addpattern [-i trxfile] [-o binfile] [-B board_id] [-p pattern] [-s serial] [-g] [-b] [-v v#.#.#] [-r #.#] [-{0|1|2|4|5}] -h\n"); exit(EXIT_FAILURE); } struct board_info *find_board(char *id) { struct board_info *board; for (board = boards; board->id != NULL; board++) if (strcasecmp(id, board->id) == 0) return board; return NULL; } int main(int argc, char **argv) { char buf[1024]; /* keep this at 1k or adjust garbage calc below */ struct code_header *hdr; FILE *in = stdin; FILE *out = stdout; char *ifn = NULL; char *ofn = NULL; char *pattern = CODE_PATTERN; char *pbotpat = PBOT_PATTERN; char *version = CYBERTAN_VERSION; char *board_id = NULL; struct board_info *board = NULL; int gflag = 0; int pbotflag = 0; int c; int v0, v1, v2; size_t off, n; time_t t; struct tm *ptm; fprintf(stderr, "mjn3's addpattern replacement - v0.81\n"); hdr = (struct code_header *) buf; memset(hdr, 0, sizeof(struct code_header)); while ((c = getopt(argc, argv, "i:o:p:s:gbv:01245hr:B:")) != -1) { switch (c) { case 'i': ifn = optarg; break; case 'o': ofn = optarg; break; case 'p': pattern = optarg; break; case 's': hdr->sn = (unsigned char) atoi (optarg); break; case 'g': gflag = 1; break; case 'b': pbotflag = 1; break; case 'v': /* extension to allow setting version */ version = optarg; break; case '0': hdr->hw_ver = 0; break; case '1': hdr->hw_ver = 1; break; case '2': /* new 54G v2.2 and 54GS v1.1 flags */ hdr->hw_ver = 1; hdr->flags[0] |= SUPPORT_4712_CHIP; hdr->flags[0] |= SUPPORT_INTEL_FLASH; hdr->flags[0] |= SUPPORT_5325E_SWITCH; break; case '4': /* V4 firmware sets the flags to 0x1f */ hdr->hw_ver = 0; hdr->flags[0] = 0x1f; break; case '5': /* V5 is appended to trxV2 image */ hdr->stable[0] = 0x73; // force image to be stable hdr->stable[1] = 0x00; hdr->try1[0] = 0x74; // force try1 to be set hdr->try1[1] = 0x00; hdr->try2[0] = hdr->try2[1] = 0xFF; hdr->try3[0] = hdr->try3[1] = 0xFF; break; case 'r': hdr->hw_ver = (char)(atof(optarg)*10)+0x30; break; case 'B': board_id = optarg; break; case 'h': default: usage(); } } if (optind != argc || optind == 1) { fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); usage(); } if (board_id) { board = find_board(board_id); if (board == NULL) { fprintf(stderr, "unknown board \"%s\"\n", board_id); usage(); } pattern = board->pattern; hdr->hw_ver = board->hw_ver; hdr->sn = board->sn; hdr->flags[0] = board->flags[0]; hdr->flags[1] = board->flags[1]; } if (strlen(pattern) != 4) { fprintf(stderr, "illegal pattern \"%s\": length != 4\n", pattern); usage(); } if (ifn && !(in = fopen(ifn, "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", ifn); usage(); } if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } if (time(&t) == (time_t)(-1)) { fprintf(stderr, "time call failed\n"); return EXIT_FAILURE; } ptm = localtime(&t); if (3 != sscanf(version, "v%d.%d.%d", &v0, &v1, &v2)) { fprintf(stderr, "bad version string \"%s\"\n", version); return EXIT_FAILURE; } memcpy(&hdr->magic, pattern, 4); if (pbotflag) memcpy(&hdr->res1, pbotpat, 4); hdr->fwdate[0] = ptm->tm_year % 100; hdr->fwdate[1] = ptm->tm_mon + 1; hdr->fwdate[2] = ptm->tm_mday; hdr->fwvern[0] = v0; hdr->fwvern[1] = v1; hdr->fwvern[2] = v2; memcpy(&hdr->id, CODE_ID, strlen(CODE_ID)); off = sizeof(struct code_header); fprintf(stderr, "writing firmware v%d.%d.%d on %d/%d/%d (y/m/d)\n", v0, v1, v2, hdr->fwdate[0], hdr->fwdate[1], hdr->fwdate[2]); while ((n = fread(buf + off, 1, sizeof(buf)-off, in) + off) > 0) { off = 0; if (n < sizeof(buf)) { if (ferror(in)) { FREAD_ERROR: fprintf(stderr, "fread error\n"); return EXIT_FAILURE; } if (gflag) { gflag = sizeof(buf) - n; memset(buf + n, 0xff, gflag); fprintf(stderr, "adding %d bytes of garbage\n", gflag); n = sizeof(buf); } } if (!fwrite(buf, n, 1, out)) { FWRITE_ERROR: fprintf(stderr, "fwrite error\n"); return EXIT_FAILURE; } } if (ferror(in)) { goto FREAD_ERROR; } if (fflush(out)) { goto FWRITE_ERROR; } fclose(in); fclose(out); return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/airlink.c ================================================ /* * Thanks to Vassily Galinsky for this tool ***************************************************************************** AIRLINK AR525W firmware image structure -8:-5 Extended (httpd) header checksum - sum2 -4:-1 Extended (httpd) header magic - "ARRN" - 0x4e525241 0: 3 Standard (tftpd) header magic - "GMTK" - 0x4b544d47 4: 7 Standard (tftpd) header checksum - sum1 8: b 0 c: f Size of compressed linux kernel 10:13 Size of firmware image file with standard header 14:17 Product code - 0x5 18:1b Bootloader checksum - sum0 1c:1f 0 20: Compressed linux kernel - Squashfs or jffs2 file system - kernel dependent - either 32 bytes or sector aligned *****************************************************************************/ #include #include #include #include #include #include #include #include #include typedef unsigned char uchar; uint32_t crctab[257] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 0 }; uint32_t header[] = { 0x00000000, 0x4e525241, 0x4b544d47, 0x00000000, 0x00000000, 0x000afd4a, 0x00000000, 0x00000005, 0x00000000, 0x00000000 }; static int JFFS2 = 0; int generate_image(char *kname, char *fsname, char *fname, int EHDR) { int i; uint32_t lenk, lens; uchar *bk, *bs; int fkd, ffd, fsd; fkd = open(kname, O_RDONLY); ffd = creat(fname, 0644); if ((fkd < 0) || (ffd < 0)) return -1; if (fsname) { fsd = open(fsname, O_RDONLY); if (fsd < 0) return -1; } lenk = lseek(fkd, 0, SEEK_END); header[5] = lenk; bk = (uchar *) mmap(NULL, lenk, PROT_READ, MAP_SHARED, fkd, 0); if (bk == MAP_FAILED) return -1; if (fsname) { lens = lseek(fsd, 0, SEEK_END); bs = (uchar *) mmap(NULL, lens, PROT_READ, MAP_SHARED, fsd, 0); if (bs == MAP_FAILED) return -1; } if (EHDR) write(ffd, header, 0x28); else write(ffd, header + 2, 0x20); write(ffd, bk, lenk); lenk += 0x20; if (!JFFS2) JFFS2 = 0x20; printf("Padding header+kernel - 0x%x + 0x%x = 0x%x\n", lenk, ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk, ((lenk - 1 + JFFS2) / JFFS2) * JFFS2); for (i = 0; i < ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk; i++) write(ffd, header, 1); if (fsname) { write(ffd, bs, lens); close(fsd); } close(ffd); close(fkd); return 0; } uint32_t crc32(uchar * buf, uint32_t len) { register int i; uint32_t sum; register uint32_t s0; s0 = ~0; for (i = 0; i < len; i++) { s0 = (s0 >> 8) ^ crctab[(uchar) (s0 & 0xFF) ^ buf[i]]; } sum = ~s0; return sum; } void usage(char *prog) { printf("Usage: %s [-b 0/1] image_filename \n", prog); printf(" update checksums for firmware file\n"); printf ("Usage: %s [-b 0/1] [-j erasesize_in_kibytes] [-e] kernel filesystem image_filename \n", prog); printf(" generate firmware file and update checksums\n"); printf("--------------------------------------------------\n"); printf(" -e - generate header for web upload\n"); printf(" -b 0/1 - clear/update bootloader checksum\n"); printf(" -j erasesize_in_kibytes - generate header for jffs2 filesystem\n"); } int main(int argc, char **argv) { uchar b[0x400]; char EHDR = 0; char BHDR = 0; int c, fd; extern char *optarg; extern int optind, optopt; while ((c = getopt(argc, argv, "b:ej:")) != -1) { switch (c) { case 'b': if (optarg[0] == '1') BHDR = 1; break; case 'e': EHDR = 1; break; case 'j': sscanf(optarg, "%i", &JFFS2); JFFS2 *= 1024; break; case '?': fprintf(stderr, "\nError: unknown arg %c\n\n\n", optopt); usage(argv[0]); exit(-1); } } if (((argc - optind) < 1) && ((argc - optind) > 3)) { usage(argv[0]); exit(-1); } if ((argc - optind) == 3) if (generate_image (argv[optind], argv[optind + 1], argv[optind + 2], EHDR)) { fprintf(stderr, "\nError generating image file %s\n\n\n", argv[argc - 1]); usage(argv[0]); exit(-1); } if ((argc - optind) == 2) if (generate_image (argv[optind], NULL, argv[optind + 1], EHDR)) { fprintf(stderr, "\nError generating image file %s\n\n\n", argv[argc - 1]); usage(argv[0]); exit(-1); } fd = open(argv[argc - 1], O_RDWR); if (fd < 0) { fprintf(stderr, "\nImage file not found %s\n\n\n", argv[argc - 1]); usage(argv[0]); exit(-1); } long i, len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); uchar *buf = malloc(len); read(fd, buf, len); uint32_t sum, l0; uint32_t MagicS = 0x474d544b; uint32_t MagicE = 0x4152524e; if (ntohl(*((uint32_t *) buf)) == MagicS) { fprintf(stderr, "Image without extra 8 bytes - Standard header\n"); buf[0x10] = len & 0xff; buf[0x11] = (len >> 8) & 0xff; buf[0x12] = (len >> 16) & 0xff; buf[0x13] = (len >> 24) & 0xff; lseek(fd, 0x10, SEEK_SET); write(fd, buf + 0x10, 0x4); EHDR = 0; } else if ((ntohl(*((uint32_t *) (buf + 0x8))) == MagicS) && ((ntohl(*((uint32_t *) (buf + 0x4))) == MagicE))) { fprintf(stderr, "Image with extra 8 bytes - Extended header\n"); *((uint32_t *) (buf + 0x18)) = len - 8; buf[0x18] = (len - 8) & 0xff; buf[0x19] = ((len - 8) >> 8) & 0xff; buf[0x1a] = ((len - 8) >> 16) & 0xff; buf[0x1b] = ((len - 8) >> 24) & 0xff; lseek(fd, 0x18, SEEK_SET); write(fd, buf + 0x18, 0x4); buf += 8; EHDR = 1; } else if (len == buf[0x10] | ((uint32_t)buf[0x11] << 8) | ((uint32_t)buf[0x12] << 16) | ((uint32_t)buf[0x13] << 24)) { fprintf(stderr, "Image without extra 8 bytes - Standard header\n"); EHDR = 0; } else if (len == (buf[0x18] | ((uint32_t)buf[0x19] << 8) | ((uint32_t)buf[0x1a] << 16) | ((uint32_t)buf[0x1b] << 24)) + 8) { fprintf(stderr, "Image with extra 8 bytes - Extended header\n"); buf += 8; EHDR = 1; } else { fprintf(stderr, "ERROR: Wrong image size\n"); exit(-1); } l0 = buf[0x10] | ((uint32_t)buf[0x11] << 8) | ((uint32_t)buf[0x12] << 16) | ((uint32_t)buf[0x13] << 24); if (!BHDR) *((uint32_t *) & buf[0x18]) = 0; unsigned long sum0 = buf[0x18] | ((uint32_t)buf[0x19] << 8) | ((uint32_t)buf[0x1a] << 16) | ((uint32_t)buf[0x1b] << 24); unsigned long sum1 = buf[0x4] | ((uint32_t)buf[0x5] << 8) | ((uint32_t)buf[0x6] << 16) | ((uint32_t)buf[0x7] << 24); *((uint32_t *) & buf[0x4]) = 0x0L; memcpy(b, buf, 0x100); memcpy(b + 0x100, buf + ((l0 >> 1) - ((l0 & 0x6) >> 1)), 0x100); memcpy(b + 0x200, buf + (l0 - 0x200), 0x200); *((uint32_t *) & b[0x18]) = 0x0L; sum = crc32(b, 0x400); printf("CRC32 sum0 - (%x, %x, %x)\n", sum, sum0, 0x400); if (EHDR) lseek(fd, 0x20, SEEK_SET); else lseek(fd, 0x18, SEEK_SET); buf[0x18] = (BHDR ? sum : sum0) & 0xff; buf[0x19] = ((BHDR ? sum : sum0) >> 8) & 0xff; buf[0x1a] = ((BHDR ? sum : sum0) >> 16) & 0xff; buf[0x1b] = ((BHDR ? sum : sum0) >> 24) & 0xff; write(fd, &buf[0x18], 0x4); sum = crc32(buf, l0); printf("CRC32 sum1 - (%x, %x, %x)\n", sum, sum1, l0); if (EHDR) lseek(fd, 0xC, SEEK_SET); else lseek(fd, 0x4, SEEK_SET); buf[0x4] = sum & 0xff; buf[0x5] = (sum >> 8) & 0xff; buf[0x6] = (sum >> 16) & 0xff; buf[0x7] = (sum >> 24) & 0xff; write(fd, &buf[0x4], 0x4); if (EHDR) { unsigned long sum2 = buf[-0x8] | ((uint32_t)buf[-0x7] << 8) | ((uint32_t)buf[-0x6] << 16) | ((uint32_t)buf[-0x5] << 24); *((uint32_t *) & buf[-0x8]) = 0L; sum = crc32(buf - 0x4, len - 0x4); printf("CRC32 sum2 - (%x, %x, %x)\n", sum, sum2, len - 0x4); lseek(fd, 0, SEEK_SET); *((uint32_t *) & buf[-0x8]) = htonl(sum); write(fd, &buf[-0x8], 0x4); buf -= 8; } close(fd); free(buf); return 0; } ================================================ FILE: src/firmware-tools/bcm_tag.h ================================================ #ifndef __BCM63XX_TAG_H #define __BCM63XX_TAG_H #define TAGVER_LEN 4 /* Length of Tag Version */ #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ #define SIG1_LEN 20 /* Company Signature 1 Length */ #define SIG2_LEN 14 /* Company Signature 2 Lenght */ #define BOARDID_LEN 16 /* Length of BoardId */ #define ENDIANFLAG_LEN 2 /* Endian Flag Length */ #define CHIPID_LEN 6 /* Chip Id Length */ #define IMAGE_LEN 10 /* Length of Length Field */ #define ADDRESS_LEN 12 /* Length of Address field */ #define DUALFLAG_LEN 2 /* Dual Image flag Length */ #define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ #define RSASIG_LEN 20 /* Length of RSA Signature in tag */ #define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ #define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ #define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ #define CRC_LEN 4 /* Length of CRC in bytes */ #define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ #define NUM_PIRELLI 2 #define IMAGETAG_CRC_START 0xFFFFFFFF #define PIRELLI_BOARDS { \ "AGPF-S0", \ "DWV-S0", \ } /* * The broadcom firmware assumes the rootfs starts the image, * therefore uses the rootfs start (flashImageAddress) * to determine where to flash the image. Since we have the kernel first * we have to give it the kernel address, but the crc uses the length * associated with this address (rootLength), which is added to the kernel * length (kernelLength) to determine the length of image to flash and thus * needs to be rootfs + deadcode (jffs2 EOF marker) */ struct bcm_tag { char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag char sig_1[SIG1_LEN]; // 4-23: Company Line 1 char sig_2[SIG2_LEN]; // 24-37: Company Line 2 char chipid[CHIPID_LEN]; // 38-43: Chip this image is for char boardid[BOARDID_LEN]; // 44-59: Board name char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE char totalLength[IMAGE_LEN]; // 62-71: Total length of image char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware) char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this) char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT) char flashLayoutVer[FLASHLAYOUTVER_LEN];// 192-195: Version flash layout char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32 char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate) char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition char imageSequence[4]; // 228-231: Image sequence number char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion char reserved2[16]; // 240-255: Unused at present }; #endif /* __BCM63XX_TAG_H */ ================================================ FILE: src/firmware-tools/buffalo-enc.c ================================================ /* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include /* for getopt() */ #include #include "buffalo-lib.h" #define ERR(fmt, args...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## args ); \ } while (0) static char *progname; static char *ifname; static char *ofname; static char *crypt_key = "Buffalo"; static char *magic = "start"; static int longstate; static unsigned char seed = 'O'; static char *product; static char *version; static int do_decrypt; void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -d decrypt instead of encrypt\n" " -i read input from the file \n" " -o write output to the file \n" " -l use longstate {en,de}cryption method\n" " -k use for encryption (default: Buffalo)\n" " -m set magic to \n" " -p set product name to \n" " -v set version to \n" " -h show this screen\n" ); exit(status); } static int decrypt_file(void) { struct enc_param ep; ssize_t src_len; unsigned char *buf = NULL; int err; int ret = -1; src_len = get_file_size(ifname); if (src_len < 0) { ERR("unable to get size of '%s'", ifname); goto out; } buf = malloc(src_len); if (buf == NULL) { ERR("no memory for the buffer"); goto out; } err = read_file_to_buf(ifname, buf, src_len); if (err) { ERR("unable to read from file '%s'", ifname); goto out; } memset(&ep, '\0', sizeof(ep)); ep.key = (unsigned char *) crypt_key; err = decrypt_buf(&ep, buf, src_len); if (err) { ERR("unable to decrypt '%s'", ifname); goto out; } printf("Magic\t\t: '%s'\n", ep.magic); printf("Seed\t\t: 0x%02x\n", ep.seed); printf("Product\t\t: '%s'\n", ep.product); printf("Version\t\t: '%s'\n", ep.version); printf("Data len\t: %u\n", ep.datalen); printf("Checksum\t: 0x%08x\n", ep.csum); err = write_buf_to_file(ofname, buf, ep.datalen); if (err) { ERR("unable to write to file '%s'", ofname); goto out; } ret = 0; out: free(buf); return ret; } static int encrypt_file(void) { struct enc_param ep; ssize_t src_len; unsigned char *buf; uint32_t hdrlen; ssize_t totlen = 0; int err; int ret = -1; src_len = get_file_size(ifname); if (src_len < 0) { ERR("unable to get size of '%s'", ifname); goto out; } totlen = enc_compute_buf_len(product, version, src_len); hdrlen = enc_compute_header_len(product, version); buf = malloc(totlen); if (buf == NULL) { ERR("no memory for the buffer"); goto out; } err = read_file_to_buf(ifname, &buf[hdrlen], src_len); if (err) { ERR("unable to read from file '%s'", ofname); goto free_buf; } memset(&ep, '\0', sizeof(ep)); ep.key = (unsigned char *) crypt_key; ep.seed = seed; ep.longstate = longstate; ep.csum = buffalo_csum(src_len, &buf[hdrlen], src_len); ep.datalen = src_len; strcpy((char *) ep.magic, magic); strcpy((char *) ep.product, product); strcpy((char *) ep.version, version); err = encrypt_buf(&ep, buf, &buf[hdrlen]); if (err) { ERR("invalid input file"); goto free_buf; } err = write_buf_to_file(ofname, buf, totlen); if (err) { ERR("unable to write to file '%s'", ofname); goto free_buf; } ret = 0; free_buf: free(buf); out: return ret; } static int check_params(void) { int ret = -1; if (ifname == NULL) { ERR("no input file specified"); goto out; } if (ofname == NULL) { ERR("no output file specified"); goto out; } if (crypt_key == NULL) { ERR("no key specified"); goto out; } else if (strlen(crypt_key) > BCRYPT_MAX_KEYLEN) { ERR("key '%s' is too long", crypt_key); goto out; } if (strlen(magic) != (ENC_MAGIC_LEN - 1)) { ERR("length of magic must be %d", ENC_MAGIC_LEN - 1); goto out; } if (!do_decrypt) { if (product == NULL) { ERR("no product specified"); goto out; } if (version == NULL) { ERR("no version specified"); goto out; } if (strlen(product) > (ENC_PRODUCT_LEN - 1)) { ERR("product name '%s' is too long", product); goto out; } if (strlen(version) > (ENC_VERSION_LEN - 1)) { ERR("version '%s' is too long", version); goto out; } } ret = 0; out: return ret; } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int err; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "adi:m:o:hp:v:k:r:s:"); if (c == -1) break; switch (c) { case 'd': do_decrypt = 1; break; case 'i': ifname = optarg; break; case 'l': longstate = 1; break; case 'm': magic = optarg; break; case 'o': ofname = optarg; break; case 'p': product = optarg; break; case 'v': version = optarg; break; case 'k': crypt_key = optarg; break; case 's': seed = strtoul(optarg, NULL, 16); break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } err = check_params(); if (err) goto out; if (do_decrypt) err = decrypt_file(); else err = encrypt_file(); if (err) goto out; res = EXIT_SUCCESS; out: return res; } ================================================ FILE: src/firmware-tools/buffalo-lib.c ================================================ /* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include #include "buffalo-lib.h" static uint32_t crc32_table[256] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; int bcrypt_init(struct bcrypt_ctx *ctx, void *key, int keylen, unsigned long state_len) { unsigned char *state; unsigned char *p = key; unsigned long i, j; unsigned long k = 0; state = malloc(state_len); if (state == NULL) return -1; ctx->i = 0; ctx->j = 0; ctx->state = state; ctx->state_len = state_len; for (i = 0; i < state_len; i++) state[i] = i; for(i = 0, j = 0; i < state_len; i++, j = (j + 1) % keylen) { unsigned char t; t = state[i]; k = (k + p[j] + t) % state_len; state[i] = state[k]; state[k] = t; } return 0; } int bcrypt_process(struct bcrypt_ctx *ctx, unsigned char *src, unsigned char *dst, unsigned long len) { unsigned char *state = ctx->state; unsigned long state_len = ctx->state_len; unsigned char i, j; unsigned long k; i = ctx->i; j = ctx->j; for (k = 0; k < len; k++) { unsigned char t; i = (i + 1) % state_len; j = (j + state[i]) % state_len; t = state[j]; state[j] = state[i]; state[i] = t; dst[k] = src[k] ^ state[(state[i] + state[j]) % state_len]; } ctx->i = i; ctx->j = j; return len; } void bcrypt_finish(struct bcrypt_ctx *ctx) { if (ctx->state) free(ctx->state); } int bcrypt_buf(unsigned char seed, unsigned char *key, unsigned char *src, unsigned char *dst, unsigned long len, int longstate) { unsigned char bckey[BCRYPT_MAX_KEYLEN + 1]; unsigned int keylen; struct bcrypt_ctx ctx; int ret; /* setup decryption key */ keylen = strlen((char *) key); bckey[0] = seed; memcpy(&bckey[1], key, keylen); keylen++; ret = bcrypt_init(&ctx, bckey, keylen, (longstate) ? len : BCRYPT_DEFAULT_STATE_LEN); if (ret) return ret; bcrypt_process(&ctx, src, dst, len); bcrypt_finish(&ctx); return 0; } uint32_t buffalo_csum(uint32_t csum, void *buf, unsigned long len) { char *p = buf; while (len--) { int i; csum ^= *p++; for (i = 0; i < 8; i++) csum = (csum >> 1) ^ ((csum & 1) ? 0xedb88320ul : 0); } return csum; } uint32_t buffalo_crc(void *buf, unsigned long len) { unsigned char *p = buf; unsigned long t = len; uint32_t crc = 0; while (len--) crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *p++) & 0xFF]; while (t) { crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ t) & 0xFF]; t >>= 8; } return ~crc; } unsigned long enc_compute_header_len(char *product, char *version) { return ENC_MAGIC_LEN + 1 + strlen(product) + 1 + strlen(version) + 1 + 3 * sizeof(uint32_t); } unsigned long enc_compute_buf_len(char *product, char *version, unsigned long datalen) { unsigned long ret; ret = enc_compute_header_len(product, version); ret += datalen + sizeof(uint32_t); ret += (4 - ret % 4); return ret; } static void put_be32(void *data, uint32_t val) { unsigned char *p = data; p[0] = (val >> 24) & 0xff; p[1] = (val >> 16) & 0xff; p[2] = (val >> 8) & 0xff; p[3] = val & 0xff; } static uint32_t get_be32(void *data) { unsigned char *p = data; return (((uint32_t)p[0]) << 24) | (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | ((uint32_t)p[3]); } static int check_magic(void *magic) { if (!memcmp("start", magic, ENC_MAGIC_LEN)); return 0; if (!memcmp("asar1", magic, ENC_MAGIC_LEN)); return 0; return -1; } int encrypt_buf(struct enc_param *ep, unsigned char *hdr, unsigned char *data) { unsigned char *p; uint32_t len; int err; int ret = -1; unsigned char s; p = (unsigned char *) hdr; /* setup magic */ len = strlen((char *) ep->magic) + 1; memcpy(p, ep->magic, len); p += len; /* setup seed */ *p++ = ep->seed; /* put product len */ len = strlen((char *) ep->product) + 1; put_be32(p, len); p += sizeof(uint32_t); /* copy and crypt product name */ memcpy(p, ep->product, len); err = bcrypt_buf(ep->seed, ep->key, p, p, len, ep->longstate); if (err) goto out; s = *p; p += len; /* put version length */ len = strlen((char *) ep->version) + 1; put_be32(p, len); p += sizeof(uint32_t); /* copy and crypt version */ memcpy(p, ep->version, len); err = bcrypt_buf(s, ep->key, p, p, len, ep->longstate); if (err) goto out; s = *p; p += len; /* put data length */ put_be32(p, ep->datalen); /* encrypt data */ err = bcrypt_buf(s, ep->key, data, data, ep->datalen, ep->longstate); if (err) goto out; /* put checksum */ put_be32(&data[ep->datalen], ep->csum); ret = 0; out: return ret; } int decrypt_buf(struct enc_param *ep, unsigned char *data, unsigned long datalen) { unsigned char *p; uint32_t prod_len; uint32_t ver_len; uint32_t len; uint32_t csum; ssize_t remain; int err; int ret = -1; #define CHECKLEN(_l) do { \ len = (_l); \ if (remain < len) { \ goto out; \ } \ } while (0) #define INCP() do { \ p += len; \ remain -= len; \ } while (0) remain = datalen; p = data; CHECKLEN(ENC_MAGIC_LEN); err = check_magic(p); if (err) goto out; memcpy(ep->magic, p, ENC_MAGIC_LEN); INCP(); CHECKLEN(1); ep->seed = *p; INCP(); CHECKLEN(sizeof(uint32_t)); prod_len = get_be32(p); if (prod_len > ENC_PRODUCT_LEN) goto out; INCP(); CHECKLEN(prod_len); memcpy(ep->product, p, prod_len); INCP(); CHECKLEN(sizeof(uint32_t)); ver_len = get_be32(p); if (ver_len > ENC_VERSION_LEN) goto out; INCP(); CHECKLEN(ver_len); memcpy(ep->version, p, ver_len); INCP(); CHECKLEN(sizeof(uint32_t)); ep->datalen = get_be32(p); INCP(); /* decrypt data */ CHECKLEN(ep->datalen); err = bcrypt_buf(ep->version[0], ep->key, p, data, ep->datalen, ep->longstate); if (err) goto out; INCP(); CHECKLEN(sizeof(uint32_t)); ep->csum = get_be32(p); INCP(); csum = buffalo_csum(ep->datalen, data, ep->datalen); if (csum != ep->csum) goto out; /* decrypt product name */ err = bcrypt_buf(ep->product[0], ep->key, ep->version, ep->version, ver_len, ep->longstate); if (err) goto out; /* decrypt version */ err = bcrypt_buf(ep->seed, ep->key, ep->product, ep->product, prod_len, ep->longstate); if (err) goto out; ret = 0; out: return ret; #undef CHECKLEN #undef INCP } ssize_t get_file_size(char *name) { struct stat st; int err; err = stat(name, &st); if (err) return -1; return st.st_size; } int read_file_to_buf(char *name, void *buf, ssize_t buflen) { FILE *f; size_t done; int ret = -1; f = fopen(name, "r"); if (f == NULL) goto out; errno = 0; done = fread(buf, buflen, 1, f); if (done != 1) goto close; ret = 0; close: fclose(f); out: return ret; } int write_buf_to_file(char *name, void *buf, ssize_t buflen) { FILE *f; size_t done; int ret = -1; f = fopen(name, "w"); if (f == NULL) goto out; errno = 0; done = fwrite(buf, buflen, 1, f); if (done != 1) goto close; ret = 0; close: fflush(f); fclose(f); if (ret) unlink(name); out: return ret; } ================================================ FILE: src/firmware-tools/buffalo-lib.h ================================================ /* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #ifndef _BUFFALO_LIB_H #define _BUFFALO_LIB_H #include #define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0])) #define BIT(_x) (1UL << (_x)) #define TAG_BRAND_LEN 32 #define TAG_PRODUCT_LEN 32 #define TAG_VERSION_LEN 8 #define TAG_REGION_LEN 2 #define TAG_LANGUAGE_LEN 8 #define TAG_PLATFORM_LEN 8 #define TAG_HWVER_LEN 4 #define TAG_HWVER_VAL_LEN 4 struct buffalo_tag { unsigned char product[TAG_PRODUCT_LEN]; unsigned char brand[TAG_BRAND_LEN]; unsigned char ver_major[TAG_VERSION_LEN]; unsigned char ver_minor[TAG_VERSION_LEN]; unsigned char region_code[2]; uint32_t region_mask; unsigned char unknown0[2]; unsigned char language[TAG_LANGUAGE_LEN]; unsigned char platform[TAG_PLATFORM_LEN]; unsigned char hwv[TAG_HWVER_LEN]; unsigned char hwv_val[TAG_HWVER_VAL_LEN]; uint8_t unknown1[24]; uint32_t len; uint32_t crc; uint32_t base1; uint32_t base2; uint32_t data_len; uint8_t flag; uint8_t unknown2[3]; } __attribute ((packed)); struct buffalo_tag2 { unsigned char product[TAG_PRODUCT_LEN]; unsigned char brand[TAG_BRAND_LEN]; unsigned char ver_major[TAG_VERSION_LEN]; unsigned char ver_minor[TAG_VERSION_LEN]; unsigned char region_code[2]; uint32_t region_mask; unsigned char unknown0[2]; unsigned char language[TAG_LANGUAGE_LEN]; unsigned char platform[TAG_PLATFORM_LEN]; unsigned char hwv[TAG_HWVER_LEN]; unsigned char hwv_val[TAG_HWVER_VAL_LEN]; uint8_t unknown1[24]; uint32_t total_len; uint32_t crc; uint32_t len1; uint32_t len2; uint8_t flag; uint8_t unknown2[3]; } __attribute ((packed)); #define ENC_PRODUCT_LEN 32 #define ENC_VERSION_LEN 8 #define ENC_MAGIC_LEN 6 unsigned long enc_compute_header_len(char *product, char *version); unsigned long enc_compute_buf_len(char *product, char *version, unsigned long datalen); struct enc_param { unsigned char *key; unsigned char magic[ENC_MAGIC_LEN]; unsigned char product[ENC_PRODUCT_LEN]; unsigned char version[ENC_VERSION_LEN]; unsigned char seed; int longstate; unsigned datalen; uint32_t csum; }; int encrypt_buf(struct enc_param *ep, unsigned char *hdr, unsigned char *data); int decrypt_buf(struct enc_param *ep, unsigned char *data, unsigned long datalen); #define BCRYPT_DEFAULT_STATE_LEN 256 #define BCRYPT_MAX_KEYLEN 254 struct bcrypt_ctx { unsigned long i; unsigned long j; unsigned char *state; unsigned long state_len; }; int bcrypt_init(struct bcrypt_ctx *ctx, void *key, int keylen, unsigned long state_len); int bcrypt_process(struct bcrypt_ctx *ctx, unsigned char *src, unsigned char *dst, unsigned long len); void bcrypt_finish(struct bcrypt_ctx *ctx); int bcrypt_buf(unsigned char seed, unsigned char *key, unsigned char *src, unsigned char *dst, unsigned long len, int longstate); uint32_t buffalo_csum(uint32_t csum, void *buf, unsigned long len); uint32_t buffalo_crc(void *buf, unsigned long len); ssize_t get_file_size(char *name); int read_file_to_buf(char *name, void *buf, ssize_t buflen); int write_buf_to_file(char *name, void *buf, ssize_t buflen); #endif /* _BUFFALO_LIB_H */ ================================================ FILE: src/firmware-tools/buffalo-tag.c ================================================ /* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include /* for getopt() */ #include #include "buffalo-lib.h" #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) static char *region_table[] = { "JP", "US", "EU", "AP", "TW", "KR" }; #define MAX_INPUT_FILES 2 static char *progname; static char *ifname[MAX_INPUT_FILES]; static ssize_t fsize[MAX_INPUT_FILES]; static int num_files; static char *ofname; static char *product; static char *brand; static char *language; static char *hwver; static char *platform; static int flag; static char *major; static char *minor = "1.01"; static int skipcrc; static uint32_t base1; static uint32_t base2; static char *region_code; static uint32_t region_mask; static int num_regions; void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -a set platform to \n" " -b set brand to \n" " -c \n" " -d \n" " -f set flag to \n" " -i read input from the file \n" " -l set language to \n" " -m set minor version to \n" " -o write output to the file \n" " -p set product to \n" " -r set image region to \n" " valid regions: JP, US, EU, AP, TW, KR, M_\n" " -s skip CRC calculation\n" " -v set major version to \n" " -w set harwdware version to \n" " -h show this screen\n" ); exit(status); } static int check_params(void) { #define CHECKSTR(_var, _name, _len) do { \ if ((_var) == NULL) { \ ERR("no %s specified", (_name)); \ return -1; \ } \ if ((_len) > 0 && \ strlen((_var)) > ((_len) - 1)) { \ ERR("%s is too long", (_name)); \ return -1; \ } \ } while (0) if (num_files == 0) ERR("no input files specified"); CHECKSTR(ofname, "output file", 0); CHECKSTR(brand, "brand", TAG_BRAND_LEN); CHECKSTR(product, "product", TAG_PRODUCT_LEN); CHECKSTR(platform, "platform", TAG_PLATFORM_LEN); CHECKSTR(major, "major version", TAG_VERSION_LEN); CHECKSTR(minor, "minor version", TAG_VERSION_LEN); CHECKSTR(language, "language", TAG_LANGUAGE_LEN); if (hwver) CHECKSTR(hwver, "hardware version", 2); if (num_regions == 0) { ERR("no region code specified"); return -1; } return 0; #undef CHECKSTR } static int process_region(char *reg) { int i; if (strlen(reg) != 2) { ERR("invalid region code '%s'", reg); return -1; } if (strcmp(reg, "M_") == 0) { region_code = reg; region_mask |= ~0; num_regions = 32; return 0; } for (i = 0; i < ARRAY_SIZE(region_table); i++) if (strcmp(reg, region_table[i]) == 0) { region_code = reg; region_mask |= 1 << i; num_regions++; return 0; } ERR("unknown region code '%s'", reg); return -1; } static int process_ifname(char *name) { if (num_files >= ARRAY_SIZE(ifname)) { ERR("too many input files specified"); return -1; } ifname[num_files++] = name; return 0; } static void fixup_tag(unsigned char *buf, ssize_t buflen) { struct buffalo_tag *tag = (struct buffalo_tag *) buf; memset(tag, '\0', sizeof(*tag)); memcpy(tag->brand, brand, strlen(brand)); memcpy(tag->product, product, strlen(product)); memcpy(tag->platform, platform, strlen(platform)); memcpy(tag->ver_major, major, strlen(major)); memcpy(tag->ver_minor, minor, strlen(minor)); memcpy(tag->language, language, strlen(language)); if (num_regions > 1) { tag->region_code[0] = 'M'; tag->region_code[1] = '_'; tag->region_mask = htonl(region_mask); } else { memcpy(tag->region_code, region_code, 2); } tag->len = htonl(buflen); tag->data_len = htonl(fsize[0]); tag->base1 = htonl(base1); tag->base2 = htonl(base2); tag->flag = flag; if (hwver) { memcpy(tag->hwv, "hwv", 3); memcpy(tag->hwv_val, hwver, strlen(hwver)); } if (!skipcrc) tag->crc = htonl(buffalo_crc(buf, buflen)); } static void fixup_tag2(unsigned char *buf, ssize_t buflen) { struct buffalo_tag2 *tag = (struct buffalo_tag2 *) buf; memset(tag, '\0', sizeof(*tag)); memcpy(tag->brand, brand, strlen(brand)); memcpy(tag->product, product, strlen(product)); memcpy(tag->platform, platform, strlen(platform)); memcpy(tag->ver_major, major, strlen(major)); memcpy(tag->ver_minor, minor, strlen(minor)); memcpy(tag->language, language, strlen(language)); if (num_regions > 1) { tag->region_code[0] = 'M'; tag->region_code[1] = '_'; tag->region_mask = htonl(region_mask); } else { memcpy(tag->region_code, region_code, 2); } tag->total_len = htonl(buflen); tag->len1 = htonl(fsize[0]); tag->len2 = htonl(fsize[1]); tag->flag = flag; if (hwver) { memcpy(tag->hwv, "hwv", 3); memcpy(tag->hwv_val, hwver, strlen(hwver)); } if (!skipcrc) tag->crc = htonl(buffalo_crc(buf, buflen)); } static int tag_file(void) { unsigned char *buf; ssize_t offset; ssize_t hdrlen; ssize_t buflen; int err; int ret = -1; int i; if (num_files == 1) hdrlen = sizeof(struct buffalo_tag); else hdrlen = sizeof(struct buffalo_tag2); buflen = hdrlen; for (i = 0; i < num_files; i++) { fsize[i] = get_file_size(ifname[i]); if (fsize[i] < 0) { ERR("unable to get size of '%s'", ifname[i]); goto out; } buflen += fsize[i]; } buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } offset = hdrlen; for (i = 0; i < num_files; i++) { err = read_file_to_buf(ifname[i], buf + offset, fsize[i]); if (err) { ERR("unable to read from file '%s'", ifname[i]); goto free_buf; } offset += fsize[i]; } if (num_files == 1) fixup_tag(buf, buflen); else fixup_tag2(buf, buflen); err = write_buf_to_file(ofname, buf, buflen); if (err) { ERR("unable to write to file '%s'", ofname); goto free_buf; } ret = 0; free_buf: free(buf); out: return ret; } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int err; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "a:b:c:d:f:hi:l:m:o:p:r:sv:w:"); if (c == -1) break; switch (c) { case 'a': platform = optarg; break; case 'b': brand = optarg; break; case 'c': base1 = strtoul(optarg, NULL, 16); break; case 'd': base2 = strtoul(optarg, NULL, 16); break; case 'f': flag = strtoul(optarg, NULL, 2); break; case 'i': err = process_ifname(optarg); if (err) goto out; break; case 'l': language = optarg; break; case 'm': minor = optarg; break; case 'o': ofname = optarg; break; case 'p': product = optarg; break; case 'r': err = process_region(optarg); if (err) goto out; break; case 's': skipcrc = 1; break; case 'v': major = optarg; break; case 'w': hwver = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } err = check_params(); if (err) goto out; err = tag_file(); if (err) goto out; res = EXIT_SUCCESS; out: return res; } ================================================ FILE: src/firmware-tools/buffalo-tftp.c ================================================ /* * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include /* for getopt() */ #include #include "buffalo-lib.h" #define ERR(fmt, args...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## args ); \ } while (0) static char *progname; static char *ifname; static char *ofname; static int do_decrypt; void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -d decrypt instead of encrypt\n" " -i read input from the file \n" " -o write output to the file \n" " -h show this screen\n" ); exit(status); } static const unsigned char *crypt_key1 = (unsigned char *) "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const unsigned char *crypt_key2 = (unsigned char *) "XYZ0123hijklmnopqABCDEFGHrstuvabcdefgwxyzIJKLMSTUVW456789NOPQR"; static void crypt_header(unsigned char *buf, ssize_t len, const unsigned char *key1, const unsigned char *key2) { ssize_t i; for (i = 0; i < len; i++) { unsigned int j; for (j = 0; key1[j]; j++) if (buf[i] == key1[j]) { buf[i] = key2[j]; break; } } } static int crypt_file(void) { unsigned char *buf = NULL; ssize_t src_len; ssize_t crypt_len; int err; int ret = -1; src_len = get_file_size(ifname); if (src_len < 0) { ERR("unable to get size of '%s'", ifname); goto out; } buf = malloc(src_len); if (buf == NULL) { ERR("no memory for the buffer"); goto out; } err = read_file_to_buf(ifname, buf, src_len); if (err) { ERR("unable to read from file '%s'", ifname); goto out; } crypt_len = (src_len > 512) ? 512 : src_len; if (do_decrypt) crypt_header(buf, 512, crypt_key2, crypt_key1); else crypt_header(buf, 512, crypt_key1, crypt_key2); err = write_buf_to_file(ofname, buf, src_len); if (err) { ERR("unable to write to file '%s'", ofname); goto out; } ret = 0; out: free(buf); return ret; } static int check_params(void) { int ret = -1; if (ifname == NULL) { ERR("no input file specified"); goto out; } if (ofname == NULL) { ERR("no output file specified"); goto out; } ret = 0; out: return ret; } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int err; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "di:o:h"); if (c == -1) break; switch (c) { case 'd': do_decrypt = 1; break; case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } err = check_params(); if (err) goto out; err = crypt_file(); if (err) goto out; res = EXIT_SUCCESS; out: return res; } ================================================ FILE: src/firmware-tools/csysimg.h ================================================ /* * * Copyright (C) 2007,2009 Gabor Juhos * * This program was based on the code found in various Linux * source tarballs released by Edimax for it's devices. * Original author: David Hsu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #define SIG_LEN 4 #define ADM_CODE_ADDR 0x80500000 #define ADM_WEBP_ADDR 0x10000 #define ADM_WEBP_SIZE 0x10000 #define ADM_BOOT_SIZE 0x8000 #define ADM_CONF_SIZE 0x8000 #define ADM_BOOT_SIG "\x00\x60\x1A\x40" /* * Generic signatures */ #define SIG_CSYS "CSYS" #define SIG_CONF "HS\x00\x00" #define SIG_BOOT_RTL "\x00\x00\x40\x21" /* * Web page signatures */ #define SIG_BR6104K "WB4K" #define SIG_BR6104KP "WBKP" #define SIG_BR6104Wg "WBGW" #define SIG_BR6104IPC "WBIP" #define SIG_BR6114WG SIG_BR6104IPC #define SIG_BR6524K "2-K-" #define SIG_BR6524KP "2-KP" /* FIXME: valid? */ #define SIG_BR6524WG "2-WG" /* FIXME: valid? */ #define SIG_BR6524WP "2-WP" /* FIXME: valid? */ #define SIG_BR6541K "4--K" #define SIG_BR6541KP "4-KP" /* FIXME: valid? */ #define SIG_BR6541WP "4-WP" /* FIXME: valid? */ #define SIG_C54BSR4 SIG_BR6104IPC #define SIG_EW7207APg "EWAS" #define SIG_PS1205UWg "4000" #define SIG_PS3205U "5010" #define SIG_PS3205UWg "5011" #define SIG_RALINK "RNRA" #define SIG_5GXI "5GXI" /* fake signature */ #define SIG_H2BR4 SIG_BR6524K #define SIG_H2WR54G SIG_BR6524WG #define SIG_XRT401D SIG_BR6104K #define SIG_XRT402D SIG_BR6524K /* * CSYS image file header */ struct csys_header { unsigned char sig[SIG_LEN]; uint32_t addr; uint32_t size; }; ================================================ FILE: src/firmware-tools/cyg_crc.h ================================================ //========================================================================== // // crc.h // // Interface for the CRC algorithms. // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 2002 Andrew Lunn // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): Andrew Lunn // Contributors: Andrew Lunn // Date: 2002-08-06 // Purpose: // Description: // // This code is part of eCos (tm). // //####DESCRIPTIONEND#### // //========================================================================== #ifndef _SERVICES_CRC_CRC_H_ #define _SERVICES_CRC_CRC_H_ #if 0 #include #else #include typedef uint32_t cyg_uint32; typedef uint16_t cyg_uint16; #endif #ifndef __externC # ifdef __cplusplus # define __externC extern "C" # else # define __externC extern # endif #endif // Compute a CRC, using the POSIX 1003 definition __externC cyg_uint32 cyg_posix_crc32(unsigned char *s, int len); // Gary S. Brown's 32 bit CRC __externC cyg_uint32 cyg_crc32(unsigned char *s, int len); // Gary S. Brown's 32 bit CRC, but accumulate the result from a // previous CRC calculation __externC cyg_uint32 cyg_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len); // Ethernet FCS Algorithm __externC cyg_uint32 cyg_ether_crc32(unsigned char *s, int len); // Ethernet FCS algorithm, but accumulate the result from a previous // CRC calculation. __externC cyg_uint32 cyg_ether_crc32_accumulate(cyg_uint32 crc, unsigned char *s, int len); // 16 bit CRC with polynomial x^16+x^12+x^5+1 __externC cyg_uint16 cyg_crc16(unsigned char *s, int len); #endif // _SERVICES_CRC_CRC_H_ ================================================ FILE: src/firmware-tools/cyg_crc16.c ================================================ //========================================================================== // // crc16.c // // 16 bit CRC with polynomial x^16+x^12+x^5+1 // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // Copyright (C) 2002 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): gthomas // Contributors: gthomas,asl // Date: 2001-01-31 // Purpose: // Description: // // This code is part of eCos (tm). // //####DESCRIPTIONEND#### // //========================================================================== #if 0 #include #else #include "cyg_crc.h" #endif // Table of CRC constants - implements x^16+x^12+x^5+1 static const cyg_uint16 crc16_tab[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, }; cyg_uint16 cyg_crc16(unsigned char *buf, int len) { int i; cyg_uint16 cksum; cksum = 0; for (i = 0; i < len; i++) { cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xFF] ^ (cksum << 8); } return cksum; } ================================================ FILE: src/firmware-tools/cyg_crc32.c ================================================ //========================================================================== // // crc32.c // // Gary S. Brown's 32 bit CRC // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // Copyright (C) 2002 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): gthomas // Contributors: gthomas,asl // Date: 2001-01-31 // Purpose: // Description: // // This code is part of eCos (tm). // //####DESCRIPTIONEND#### // //========================================================================== #if 0 #include #else #include "cyg_crc.h" #endif /* ====================================================================== */ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ /* code or tables extracted from it, as desired without restriction. */ /* */ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* */ /* ====================================================================== */ static const cyg_uint32 crc32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; /* This is the standard Gary S. Brown's 32 bit CRC algorithm, but accumulate the CRC into the result of a previous CRC. */ cyg_uint32 cyg_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len) { int i; for (i = 0; i < len; i++) { crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); } return crc32val; } /* This is the standard Gary S. Brown's 32 bit CRC algorithm */ cyg_uint32 cyg_crc32(unsigned char *s, int len) { return (cyg_crc32_accumulate(0,s,len)); } /* Return a 32-bit CRC of the contents of the buffer accumulating the result from a previous CRC calculation. This uses the Ethernet FCS algorithm.*/ cyg_uint32 cyg_ether_crc32_accumulate(cyg_uint32 crc32val, unsigned char *s, int len) { int i; if (s == 0) return 0L; crc32val = crc32val ^ 0xffffffff; for (i = 0; i < len; i++) { crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8); } return crc32val ^ 0xffffffff; } /* Return a 32-bit CRC of the contents of the buffer, using the Ethernet FCS algorithm. */ cyg_uint32 cyg_ether_crc32(unsigned char *s, int len) { return cyg_ether_crc32_accumulate(0,s,len); } ================================================ FILE: src/firmware-tools/dgfirmware.c ================================================ #include #include #define IMG_SIZE 0x3e0000 #define KERNEL_START 0x020000 #define KERNEL_SIZE 0x0b0000 #define ROOTFS_START 0x0d0000 #define ROOTFS_SIZE 0x30ffb2 char* app_name; void print_usage(void) { fprintf(stderr, "usage: dgfirmware [] \n"); fprintf(stderr, " firmware image filename\n"); fprintf(stderr, " -h print this message\n"); fprintf(stderr, " -f fix the checksum\n"); fprintf(stderr, " -x extract the rootfs file to \n"); fprintf(stderr, " -xk extract the kernel to \n"); fprintf(stderr, " -m merge in rootfs fil\e from \n"); fprintf(stderr, " -k merge in kernel from \n"); fprintf(stderr, " -w write back the modified firmware\n"); } unsigned char* read_img(const char *fname) { FILE *fp; int size; unsigned char *img; fp = fopen(fname, "rb"); if (fp == NULL) { perror(app_name); exit(-1); } fseek(fp, 0, SEEK_END); size = ftell(fp); if (size != IMG_SIZE) { fprintf(stderr, "%s: image file has wrong size\n", app_name); fclose(fp); exit(-1); } rewind(fp); img = malloc(IMG_SIZE); if (img == NULL) { perror(app_name); fclose(fp); exit(-1); } if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) { fprintf(stderr, "%s: can't read image file\n", app_name); fclose(fp); exit(-1); } fclose(fp); return img; } void write_img(unsigned char* img, const char *fname) { FILE *fp; fp = fopen(fname, "wb"); if (fp == NULL) { perror(app_name); exit(-1); } if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) { fprintf(stderr, "%s: can't write image file\n", app_name); fclose(fp); exit(-1); } } void write_rootfs(unsigned char* img, const char *fname) { FILE *fp; fp = fopen(fname, "wb"); if (fp == NULL) { perror(app_name); exit(-1); } if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) { fprintf(stderr, "%s: can't write image file\n", app_name); fclose(fp); exit(-1); } } void write_kernel(unsigned char* img, const char *fname) { FILE *fp; fp = fopen(fname, "wb"); if (fp == NULL) { perror(app_name); exit(-1); } if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) { fprintf(stderr, "%s: can't write kernel file\n", app_name); fclose(fp); exit(-1); } } unsigned char* read_rootfs(unsigned char* img, const char *fname) { FILE *fp; int size; int i; for (i=ROOTFS_START; i ROOTFS_SIZE) { fprintf(stderr, "%s: rootfs image file is too big\n", app_name); fclose(fp); exit(-1); } rewind(fp); if (fread(img+ROOTFS_START, 1, size, fp) != size) { fprintf(stderr, "%s: can't read rootfs image file\n", app_name); fclose(fp); exit(-1); } fclose(fp); return img; } unsigned char* read_kernel(unsigned char* img, const char *fname) { FILE *fp; int size; int i; for (i=KERNEL_START; i KERNEL_SIZE) { fprintf(stderr, "%s: kernel binary file is too big\n", app_name); fclose(fp); exit(-1); } rewind(fp); if (fread(img+KERNEL_START, 1, size, fp) != size) { fprintf(stderr, "%s: can't read kernel file\n", app_name); fclose(fp); exit(-1); } fclose(fp); return img; } int get_checksum(unsigned char* img) { short unsigned s; s = img[0x3dfffc] + (img[0x3dfffd]<<8); return s; } void set_checksum(unsigned char*img, unsigned short sum) { img[0x3dfffc] = sum & 0xff; img[0x3dfffd] = (sum>>8) & 0xff; } int compute_checksum(unsigned char* img) { int i; short s=0; for (i=0; i<0x3dfffc; i++) s += img[i]; return s; } int main(int argc, char* argv[]) { char *img_fname = NULL; char *rootfs_fname = NULL; char *kernel_fname = NULL; char *new_img_fname = NULL; int do_fix_checksum = 0; int do_write = 0; int do_write_rootfs = 0; int do_read_rootfs = 0; int do_write_kernel = 0; int do_read_kernel = 0; int i; unsigned char *img; unsigned short img_checksum; unsigned short real_checksum; app_name = argv[0]; for (i=1; i= argc) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } do_write_rootfs = 1; rootfs_fname = argv[i+1]; i++; } else if (!strcmp(argv[i], "-xk")) { if (i+1 >= argc) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } do_write_kernel = 1; kernel_fname = argv[i+1]; i++; } else if (!strcmp(argv[i], "-m")) { if (i+1 >= argc) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } do_read_rootfs = 1; rootfs_fname = argv[i+1]; i++; } else if (!strcmp(argv[i], "-k")) { if (i+1 >= argc) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } do_read_kernel = 1; kernel_fname = argv[i+1]; i++; } else if (!strcmp(argv[i], "-w")) { if (i+1 >= argc) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } do_write = 1; new_img_fname = argv[i+1]; i++; } else if (img_fname != 0) { fprintf(stderr, "%s: too many arguments\n", app_name); return -1; } else { img_fname = argv[i]; } } if (img_fname == NULL) { fprintf(stderr, "%s: missing argument\n", app_name); return -1; } if ((do_read_rootfs && do_write_rootfs) || (do_read_kernel && do_write_kernel)) { fprintf(stderr, "%s: conflictuous options\n", app_name); return -1; } printf ("** Read firmware file\n"); img = read_img(img_fname); printf ("Firmware product: %s\n", img+0x3dffbd); printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]); if (do_write_rootfs) { printf ("** Write rootfs file\n"); write_rootfs(img, rootfs_fname); } if (do_write_kernel) { printf ("** Write kernel file\n"); write_kernel(img, kernel_fname); } if (do_read_rootfs) { printf ("** Read rootfs file\n"); read_rootfs(img, rootfs_fname); do_fix_checksum = 1; } if (do_read_kernel) { printf ("** Read kernel file\n"); read_kernel(img, kernel_fname); do_fix_checksum = 1; } img_checksum = get_checksum(img); real_checksum = compute_checksum(img); printf ("image checksum = %04x\n", img_checksum); printf ("real checksum = %04x\n", real_checksum); if (do_fix_checksum) { if (img_checksum != real_checksum) { printf ("** Bad Checksum, fix it\n"); set_checksum(img, real_checksum); } else { printf ("** Checksum is correct, good\n"); } } if (do_write) { printf ("** Write image file\n"); write_img(img, new_img_fname); } free(img); return 0; } ================================================ FILE: src/firmware-tools/encode_crc.c ================================================ /* ************************************************************************** This program creates a CRC checksum and encodes the file that is named in the command line. Compile with: gcc encode_crc.c -Wall -o encode_crc Author: Michael Margraf (michael.margraf@freecom.com) Copyright: Freecom Technology GmbH, Berlin, 2004 www.freecom.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ************************************************************************* */ #include #include #include #include // ******************************************************************* // CCITT polynom G(x)=x^16+x^12+x^5+1 #define POLYNOM 0x1021 // CRC algorithm with MSB first int make_crc16(int crc, char new) { int i; crc = crc ^ (((int)new) << 8); for(i=0; i<8; i++) { // work on 8 bits in "new" crc <<= 1; // MSBs first if(crc & 0x10000) crc ^= POLYNOM; } return crc & 0xFFFF; } // ******************************************************************* // Reads the file "filename" into memory and returns pointer to the buffer. static char *readfile(char *filename, int *size) { FILE *fp; char *buffer; struct stat info; if (stat(filename,&info)!=0) return NULL; if ((fp=fopen(filename,"r"))==NULL) return NULL; buffer=NULL; for (;;) { if ((buffer=(char *)malloc(info.st_size+1))==NULL) break; if (fread(buffer,1,info.st_size,fp)!=info.st_size) { free(buffer); buffer=NULL; break; } buffer[info.st_size]='\0'; if(size) *size = info.st_size; break; } (void)fclose(fp); return buffer; } // ******************************************************************* int main(int argc, char** argv) { if(argc < 3) { printf("ERROR: Argument missing!\n\n"); return 1; } int count; // size of file in bytes char *p, *master = readfile(argv[1], &count); if(!master) { printf("ERROR: File not found!\n"); return 1; } int crc = 0xFFFF, z; p = master; for(z=0; z 2) { // with flag for device recognition ? p = argv[2]; for(z=strlen(p); z>0; z--) { crc ^= (int)(*p); *(p++) = (char)crc; // encode device flag } } */ p = master; for(z=0; z 3) { // add flag for device recognition ? fwrite(argv[3], strlen(argv[3]), sizeof(char), fp); } else { // Device is an FSG, so byte swap (IXP4xx is big endian) crc16 = ((crc16 >> 8) & 0xFF) | ((crc16 << 8) & 0xFF00); } fwrite(&crc16, 1, sizeof(short), fp); // first write CRC fwrite(master, count, sizeof(char), fp); // write content fclose(fp); free(master); return 0; } ================================================ FILE: src/firmware-tools/fix-u-media-header.c ================================================ /* * Copyright (C) 2012 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include "cyg_crc.h" #include #include #define IH_MAGIC 0x27051956 /* Image Magic Number */ #define IH_NMLEN 32 /* Image Name Length */ #define UM_MAGIC 0x55525F46 #define UM_HEADER_LEN 12 /* * all data in network byte order (aka natural aka bigendian) */ struct u_media_header { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ uint32_t ih_time; /* Image Creation Timestamp */ uint32_t ih_size; /* Image Data Size */ uint32_t ih_load; /* Data Load Address */ uint32_t ih_ep; /* Entry Point Address */ uint32_t ih_dcrc; /* Image Data CRC Checksum */ uint8_t ih_os; /* Operating System */ uint8_t ih_arch; /* CPU architecture */ uint8_t ih_type; /* Image Type */ uint8_t ih_comp; /* Compression Type */ uint8_t ih_name[IH_NMLEN - UM_HEADER_LEN]; /* Image Name */ uint32_t ih_UMedia_magic; /* U-Media magic number */ uint32_t ih_UMedia_boardID; /* U-Media board ID */ uint8_t ih_UMedia_imageType; /* U-Media image type */ uint8_t ih_UMedia_LoadDefault; /* U-Media load to factory default setting */ uint8_t ih_UMedia_temp1; /* U-Media didn't use this tag */ uint8_t ih_UMedia_temp2; /* U-Media didn't use this tag */ } __attribute__ ((packed)); struct if_info { char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ }; static char *progname; static char *ofname; static struct if_info if_info; static int factory_defaults; static uint32_t board_id; static uint8_t image_type; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define DBG(fmt, ...) do { \ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) static void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B set board ID to \n" " -i read input from the file \n" " -F load factory defaults\n" " -o write output to the file \n" " -T set image type to \n" " -h show this screen\n" ); exit(status); } static int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } static int str2u8(char *arg, uint8_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } if (t > 255) return -1; *val = t; return 0; } static int get_file_stat(struct if_info *fdata) { struct stat st; int res; if (fdata->file_name == NULL) return 0; res = stat(fdata->file_name, &st); if (res){ ERRS("stat failed on %s", fdata->file_name); return res; } fdata->file_size = st.st_size; return 0; } static int read_to_buf(struct if_info *fdata, char *buf) { FILE *f; int ret = EXIT_FAILURE; f = fopen(fdata->file_name, "r"); if (f == NULL) { ERRS("could not open \"%s\" for reading", fdata->file_name); goto out; } errno = 0; fread(buf, fdata->file_size, 1, f); if (errno != 0) { ERRS("unable to read from file \"%s\"", fdata->file_name); goto out_close; } ret = EXIT_SUCCESS; out_close: fclose(f); out: return ret; } static int check_options(void) { int ret; if (ofname == NULL) { ERR("no %s specified", "output file"); return -1; } if (if_info.file_name == NULL) { ERR("no %s specified", "input file"); return -1; } ret = get_file_stat(&if_info); if (ret) return ret; return 0; } static int write_fw(char *data, int len) { FILE *f; int ret = EXIT_FAILURE; f = fopen(ofname, "w"); if (f == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } errno = 0; fwrite(data, len, 1, f); if (errno) { ERRS("unable to write output file"); goto out_flush; } ret = EXIT_SUCCESS; out_flush: fflush(f); fclose(f); if (ret != EXIT_SUCCESS) { unlink(ofname); } out: return ret; } static int fix_header(void) { int buflen; char *buf; uint32_t crc, crc_orig; struct u_media_header *hdr; int ret = EXIT_FAILURE; buflen = if_info.file_size; if (buflen < sizeof(*hdr)) { ERR("invalid input file\n"); return ret; } buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } ret = read_to_buf(&if_info, buf); if (ret) goto out_free_buf; hdr = (struct u_media_header *) buf; if (ntohl(hdr->ih_magic) != IH_MAGIC) { ERR("invalid input file, bad magic\n"); goto out_free_buf; } /* verify header CRC */ crc_orig = ntohl(hdr->ih_hcrc); hdr->ih_hcrc = 0; crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr)); if (crc != crc_orig) { ERR("invalid input file, bad header CRC\n"); goto out_free_buf; } hdr->ih_name[IH_NMLEN - UM_HEADER_LEN - 1] = '\0'; /* set U-Media specific fields */ hdr->ih_UMedia_magic = htonl(UM_MAGIC); hdr->ih_UMedia_boardID = htonl(board_id); hdr->ih_UMedia_imageType = image_type; hdr->ih_UMedia_LoadDefault = (factory_defaults) ? 1 : 0; /* update header CRC */ crc = cyg_ether_crc32((unsigned char *)hdr, sizeof(*hdr)); hdr->ih_hcrc = htonl(crc); ret = write_fw(buf, buflen); if (ret) goto out_free_buf; DBG("U-Media header fixed in \"%s\"", ofname); ret = EXIT_SUCCESS; out_free_buf: free(buf); out: return ret; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; progname = basename(argv[0]); while (1) { int c; c = getopt(argc, argv, "B:Fi:o:T:h"); if (c == -1) break; switch (c) { case 'B': if (str2u32(optarg, &board_id)) { ERR("%s is invalid '%s'", "board ID", optarg); goto out; } break; case 'T': if (str2u8(optarg, &image_type)) { ERR("%s is invalid '%s'", "image type", optarg); goto out; } break; case 'F': factory_defaults = 1; break; case 'i': if_info.file_name = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } ret = check_options(); if (ret) goto out; ret = fix_header(); out: return ret; } ================================================ FILE: src/firmware-tools/fw.h ================================================ /* * * Copyright (C) 2007 Ubiquiti Networks, Inc. * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifndef FW_INCLUDED #define FW_INCLUDED #include #define MAGIC_HEADER "OPEN" #define MAGIC_PART "PART" #define MAGIC_END "END." #define MAGIC_LENGTH 4 typedef struct header { char magic[MAGIC_LENGTH]; char version[256]; u_int32_t crc; u_int32_t pad; } __attribute__ ((packed)) header_t; typedef struct part { char magic[MAGIC_LENGTH]; char name[16]; char pad[12]; u_int32_t memaddr; u_int32_t index; u_int32_t baseaddr; u_int32_t entryaddr; u_int32_t data_size; u_int32_t part_size; } __attribute__ ((packed)) part_t; typedef struct part_crc { u_int32_t crc; u_int32_t pad; } __attribute__ ((packed)) part_crc_t; typedef struct signature { char magic[MAGIC_LENGTH]; u_int32_t crc; u_int32_t pad; } __attribute__ ((packed)) signature_t; #define VERSION "1.2" #define INFO(...) fprintf(stdout, __VA_ARGS__) #define ERROR(...) fprintf(stderr, "ERROR: "__VA_ARGS__) #define WARN(...) fprintf(stderr, "WARN: "__VA_ARGS__) #define DEBUG(...) do {\ if (debug) \ fprintf(stdout, "DEBUG: "__VA_ARGS__); \ } while (0); #endif ================================================ FILE: src/firmware-tools/imagetag.c ================================================ /* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2008 Axel Gembe * Copyright (C) 2009-2010 Daniel Dickinson */ #include #include #include #include #include #include #include #include #include "bcm_tag.h" #include "imagetag_cmdline.h" #define DEADCODE 0xDEADC0DE /* Kernel header */ struct kernelhdr { uint32_t loadaddr; /* Kernel load address */ uint32_t entry; /* Kernel entry point address */ uint32_t lzmalen; /* Compressed length of the LZMA data that follows */ }; static char pirellitab[NUM_PIRELLI][BOARDID_LEN] = PIRELLI_BOARDS; static uint32_t crc32tab[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; void int2tag(char *tag, uint32_t value) { uint32_t network = htonl(value); memcpy(tag, (char *)(&network), 4); } uint32_t crc32(uint32_t crc, uint8_t *data, size_t len) { while (len--) crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF]; return crc; } uint32_t compute_crc32(uint32_t crc, FILE *binfile, size_t compute_start, size_t compute_len) { uint8_t readbuf[1024]; size_t read; fseek(binfile, compute_start, SEEK_SET); /* read block of 1024 bytes */ while (binfile && !feof(binfile) && !ferror(binfile) && (compute_len >= sizeof(readbuf))) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), binfile); crc = crc32(crc, readbuf, read); compute_len = compute_len - read; } /* Less than 1024 bytes remains, read compute_len bytes */ if (binfile && !feof(binfile) && !ferror(binfile) && (compute_len > 0)) { read = fread(readbuf, sizeof(uint8_t), compute_len, binfile); crc = crc32(crc, readbuf, read); } return crc; } size_t getlen(FILE *fp) { size_t retval, curpos; if (!fp) return 0; curpos = ftell(fp); fseek(fp, 0, SEEK_END); retval = ftell(fp); fseek(fp, curpos, SEEK_SET); return retval; } int tagfile(const char *kernel, const char *rootfs, const char *bin, \ const struct gengetopt_args_info *args, \ uint32_t flash_start, uint32_t image_offset, \ uint32_t block_size, uint32_t load_address, uint32_t entry) { struct bcm_tag tag; struct kernelhdr khdr; FILE *kernelfile = NULL, *rootfsfile = NULL, *binfile = NULL, *cfefile = NULL; size_t cfeoff, cfelen, kerneloff, kernellen, rootfsoff, rootfslen, \ read, imagelen, rootfsoffpadlen = 0, kernelfslen, kerneloffpadlen = 0, oldrootfslen; uint8_t readbuf[1024]; uint32_t imagecrc = IMAGETAG_CRC_START; uint32_t kernelcrc = IMAGETAG_CRC_START; uint32_t rootfscrc = IMAGETAG_CRC_START; uint32_t kernelfscrc = IMAGETAG_CRC_START; uint32_t fwaddr = 0; uint8_t crc_val; const uint32_t deadcode = htonl(DEADCODE); int i; int is_pirelli = 0; memset(&tag, 0, sizeof(struct bcm_tag)); if (!kernel || !rootfs) { fprintf(stderr, "imagetag can't create an image without both kernel and rootfs\n"); } if (kernel && !(kernelfile = fopen(kernel, "rb"))) { fprintf(stderr, "Unable to open kernel \"%s\"\n", kernel); return 1; } if (rootfs && !(rootfsfile = fopen(rootfs, "rb"))) { fprintf(stderr, "Unable to open rootfs \"%s\"\n", rootfs); return 1; } if (!bin || !(binfile = fopen(bin, "wb+"))) { fprintf(stderr, "Unable to open output file \"%s\"\n", bin); return 1; } if ((args->cfe_given) && (args->cfe_arg)) { if (!(cfefile = fopen(args->cfe_arg, "rb"))) { fprintf(stderr, "Unable to open CFE file \"%s\"\n", args->cfe_arg); } } fwaddr = flash_start + image_offset; if (cfefile) { cfeoff = flash_start; cfelen = getlen(cfefile); /* Seek to the start of the file after tag */ fseek(binfile, sizeof(tag), SEEK_SET); /* Write the cfe */ while (cfefile && !feof(cfefile) && !ferror(cfefile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), cfefile); fwrite(readbuf, sizeof(uint8_t), read, binfile); } } else { cfeoff = 0; cfelen = 0; } if (!args->root_first_flag) { /* Build the kernel address and length (doesn't need to be aligned, read only) */ kerneloff = fwaddr + sizeof(tag); kernellen = getlen(kernelfile); if (!args->kernel_file_has_header_flag) { /* Build the kernel header */ khdr.loadaddr = htonl(load_address); khdr.entry = htonl(entry); khdr.lzmalen = htonl(kernellen); /* Increase the kernel size by the header size */ kernellen += sizeof(khdr); } /* Build the rootfs address and length (start and end do need to be aligned on flash erase block boundaries */ rootfsoff = kerneloff + kernellen; rootfsoff = (rootfsoff % block_size) > 0 ? (((rootfsoff / block_size) + 1) * block_size) : rootfsoff; rootfslen = getlen(rootfsfile); rootfslen = ( (rootfslen % block_size) > 0 ? (((rootfslen / block_size) + 1) * block_size) : rootfslen ); imagelen = rootfsoff + rootfslen - kerneloff + sizeof(deadcode); rootfsoffpadlen = rootfsoff - (kerneloff + kernellen); /* Seek to the start of the kernel */ fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET); /* Write the kernel header */ fwrite(&khdr, sizeof(khdr), 1, binfile); /* Write the kernel */ while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); } /* Write the RootFS */ fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET); while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); } /* Align image to specified erase block size and append deadc0de */ printf("Data alignment to %dk with 'deadc0de' appended\n", block_size/1024); fseek(binfile, rootfsoff + rootfslen - fwaddr + cfelen, SEEK_SET); fwrite(&deadcode, sizeof(uint32_t), 1, binfile); oldrootfslen = rootfslen; if (args->pad_given) { uint32_t allfs = 0xffffffff; uint32_t pad_size = args->pad_arg * 1024 * 1024; printf("Padding image to %d bytes ...\n", pad_size); while (imagelen < pad_size) { fwrite(&allfs, sizeof(uint32_t), 1, binfile); imagelen += 4; rootfslen += 4; } } /* Flush the binfile buffer so that when we read from file, it contains * everything in the buffer */ fflush(binfile); /* Compute the crc32 of the entire image (deadC0de included) */ imagecrc = compute_crc32(imagecrc, binfile, kerneloff - fwaddr + cfelen, imagelen); /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen); /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ kernelfscrc = compute_crc32(kernelfscrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen + rootfslen + sizeof(deadcode)); /* Compute the crc32 of the flashImageStart to rootLength. * The broadcom firmware assumes the rootfs starts the image, * therefore uses the rootfs start to determine where to flash * the image. Since we have the kernel first we have to give * it the kernel address, but the crc uses the length * associated with this address, which is added to the kernel * length to determine the length of image to flash and thus * needs to be rootfs + deadcode */ rootfscrc = compute_crc32(rootfscrc, binfile, kerneloff - fwaddr + cfelen, rootfslen + sizeof(deadcode)); } else { /* Build the kernel address and length (doesn't need to be aligned, read only) */ rootfsoff = fwaddr + sizeof(tag); oldrootfslen = getlen(rootfsfile); rootfslen = oldrootfslen; rootfslen = ( (rootfslen % block_size) > 0 ? (((rootfslen / block_size) + 1) * block_size) : rootfslen ); kerneloffpadlen = rootfslen - oldrootfslen; oldrootfslen = rootfslen; kerneloff = rootfsoff + rootfslen; kernellen = getlen(kernelfile); imagelen = cfelen + rootfslen + kernellen; /* Seek to the start of the kernel */ fseek(binfile, kerneloff - fwaddr + cfelen, SEEK_SET); if (!args->kernel_file_has_header_flag) { /* Build the kernel header */ khdr.loadaddr = htonl(load_address); khdr.entry = htonl(entry); khdr.lzmalen = htonl(kernellen); /* Write the kernel header */ fwrite(&khdr, sizeof(khdr), 1, binfile); /* Increase the kernel size by the header size */ kernellen += sizeof(khdr); } /* Write the kernel */ while (kernelfile && !feof(kernelfile) && !ferror(kernelfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), kernelfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); } /* Write the RootFS */ fseek(binfile, rootfsoff - fwaddr + cfelen, SEEK_SET); while (rootfsfile && !feof(rootfsfile) && !ferror(rootfsfile)) { read = fread(readbuf, sizeof(uint8_t), sizeof(readbuf), rootfsfile); fwrite(readbuf, sizeof(uint8_t), read, binfile); } /* Flush the binfile buffer so that when we read from file, it contains * everything in the buffer */ fflush(binfile); /* Compute the crc32 of the entire image (deadC0de included) */ imagecrc = compute_crc32(imagecrc, binfile, sizeof(tag), imagelen); /* Compute the crc32 of the kernel and padding between kernel and rootfs) */ kernelcrc = compute_crc32(kernelcrc, binfile, kerneloff - fwaddr + cfelen, kernellen + rootfsoffpadlen); kernelfscrc = compute_crc32(kernelfscrc, binfile, rootfsoff - fwaddr + cfelen, kernellen + rootfslen); rootfscrc = compute_crc32(rootfscrc, binfile, rootfsoff - fwaddr + cfelen, rootfslen); } /* Close the files */ if (cfefile) { fclose(cfefile); } fclose(kernelfile); fclose(rootfsfile); /* Build the tag */ strncpy(tag.tagVersion, args->tag_version_arg, sizeof(tag.tagVersion) - 1); strncpy(tag.sig_1, args->signature_arg, sizeof(tag.sig_1) - 1); strncpy(tag.sig_2, args->signature2_arg, sizeof(tag.sig_2) - 1); strncpy(tag.chipid, args->chipid_arg, sizeof(tag.chipid) - 1); strncpy(tag.boardid, args->boardid_arg, sizeof(tag.boardid) - 1); strcpy(tag.big_endian, "1"); sprintf(tag.totalLength, "%lu", imagelen); if (args->cfe_given) { sprintf(tag.cfeAddress, "%lu", flash_start); sprintf(tag.cfeLength, "%lu", cfelen); } else { /* We don't include CFE */ strcpy(tag.cfeAddress, "0"); strcpy(tag.cfeLength, "0"); } sprintf(tag.kernelAddress, "%lu", kerneloff); sprintf(tag.kernelLength, "%lu", kernellen + rootfsoffpadlen); if (args->root_first_flag) { sprintf(tag.flashImageStart, "%lu", rootfsoff); sprintf(tag.flashRootLength, "%lu", rootfslen); } else { sprintf(tag.flashImageStart, "%lu", kerneloff); sprintf(tag.flashRootLength, "%lu", rootfslen + sizeof(deadcode)); } int2tag(tag.rootLength, oldrootfslen + sizeof(deadcode)); if (args->rsa_signature_given) { strncpy(tag.rsa_signature, args->rsa_signature_arg, RSASIG_LEN); } if (args->layoutver_given) { strncpy(tag.flashLayoutVer, args->layoutver_arg, TAGLAYOUT_LEN); } if (args->info1_given) { strncpy(tag.information1, args->info1_arg, TAGINFO1_LEN); } if (args->info2_given) { strncpy(tag.information2, args->info2_arg, TAGINFO2_LEN); } if (args->reserved2_given) { strncpy(tag.reserved2, args->reserved2_arg, 16); } if (args->altinfo_given) { strncpy(&tag.information1[0], args->altinfo_arg, ALTTAGINFO_LEN); } if (args->second_image_flag_given) { if (strncmp(args->second_image_flag_arg, "2", DUALFLAG_LEN) != 0) { strncpy(tag.dualImage, args->second_image_flag_arg, DUALFLAG_LEN); } } if (args->inactive_given) { if (strncmp(args->inactive_arg, "2", INACTIVEFLAG_LEN) != 0) { strncpy(tag.inactiveFlag, args->second_image_flag_arg, INACTIVEFLAG_LEN); } } for (i = 0; i < NUM_PIRELLI; i++) { if (strncmp(args->boardid_arg, pirellitab[i], BOARDID_LEN) == 0) { is_pirelli = 1; break; } } if ( !is_pirelli ) { int2tag(tag.imageCRC, kernelfscrc); } else { int2tag(tag.imageCRC, kernelcrc); } int2tag(&(tag.rootfsCRC[0]), rootfscrc); int2tag(tag.kernelCRC, kernelcrc); int2tag(tag.fskernelCRC, kernelfscrc); int2tag(tag.headerCRC, crc32(IMAGETAG_CRC_START, (uint8_t*)&tag, sizeof(tag) - 20)); fseek(binfile, 0L, SEEK_SET); fwrite(&tag, sizeof(uint8_t), sizeof(tag), binfile); fflush(binfile); fclose(binfile); return 0; } int main(int argc, char **argv) { int c, i; char *kernel, *rootfs, *bin; uint32_t flash_start, image_offset, block_size, load_address, entry; flash_start = image_offset = block_size = load_address = entry = 0; struct gengetopt_args_info parsed_args; kernel = rootfs = bin = NULL; if (cmdline_parser(argc, argv, &parsed_args)) { exit(1); } printf("Broadcom 63xx image tagger - v2.0.0\n"); printf("Copyright (C) 2008 Axel Gembe\n"); printf("Copyright (C) 2009-2010 Daniel Dickinson\n"); printf("Licensed under the terms of the Gnu General Public License\n"); kernel = parsed_args.kernel_arg; rootfs = parsed_args.rootfs_arg; bin = parsed_args.output_arg; if (strlen(parsed_args.tag_version_arg) >= TAGVER_LEN) { fprintf(stderr, "Error: Tag Version (tag_version,v) too long.\n"); exit(1); } if (strlen(parsed_args.boardid_arg) >= BOARDID_LEN) { fprintf(stderr, "Error: Board ID (boardid,b) too long.\n"); exit(1); } if (strlen(parsed_args.chipid_arg) >= CHIPID_LEN) { fprintf(stderr, "Error: Chip ID (chipid,c) too long.\n"); exit(1); } if (strlen(parsed_args.signature_arg) >= SIG1_LEN) { fprintf(stderr, "Error: Magic string (signature,a) too long.\n"); exit(1); } if (strlen(parsed_args.signature2_arg) >= SIG2_LEN) { fprintf(stderr, "Error: Second magic string (signature2,m) too long.\n"); exit(1); } if (parsed_args.layoutver_given) { if (strlen(parsed_args.layoutver_arg) > FLASHLAYOUTVER_LEN) { fprintf(stderr, "Error: Flash layout version (layoutver,y) too long.\n"); exit(1); } } if (parsed_args.rsa_signature_given) { if (strlen(parsed_args.rsa_signature_arg) > RSASIG_LEN) { fprintf(stderr, "Error: RSA Signature (rsa_signature,r) too long.\n"); exit(1); } } if (parsed_args.info1_given) { if (strlen(parsed_args.info1_arg) >= TAGINFO1_LEN) { fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n"); exit(1); } } if (parsed_args.info2_given) { if (strlen(parsed_args.info2_arg) >= TAGINFO2_LEN) { fprintf(stderr, "Error: Vendor Information 2 (info2) too long.\n"); exit(1); } } if (parsed_args.altinfo_given) { if (strlen(parsed_args.altinfo_arg) >= ALTTAGINFO_LEN) { fprintf(stderr, "Error: Vendor Information 1 (info1) too long.\n"); exit(1); } } if (parsed_args.pad_given) { if (parsed_args.pad_arg < 0) { fprintf(stderr, "Error: pad size must be positive.\r"); exit(1); } } flash_start = strtoul(parsed_args.flash_start_arg, NULL, 16); image_offset = strtoul(parsed_args.image_offset_arg, NULL, 16); block_size = strtoul(parsed_args.block_size_arg, NULL, 16); if (!parsed_args.kernel_file_has_header_flag) { load_address = strtoul(parsed_args.load_addr_arg, NULL, 16); entry = strtoul(parsed_args.entry_arg, NULL, 16); if (load_address == 0) { fprintf(stderr, "Error: Invalid value for load address\n"); } if (entry == 0) { fprintf(stderr, "Error: Invalid value for entry\n"); } } return tagfile(kernel, rootfs, bin, &parsed_args, flash_start, image_offset, block_size, load_address, entry); } ================================================ FILE: src/firmware-tools/imagetag.ggo ================================================ # Command line option parsing generator file for imagetag # Supplied-To: gengetopt # # Copyright 2010 Daniel Dickinson # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. # package "imagetag" version "2.0.0" purpose "Generate image with CFE imagetag for Broadcom 63xx routers." description "Copyright (C) 2008 Axel Gembe Copyright (C) 2009-2010 Daniel Dickinson Licensed unter the terms of the Gnu General Public License. Given a root filesystem, a linux kernel, and an optional CFE, generates an image with an imagetag for a Broadcom 63xx-based router. Additional parameters to be specified depend on the specfic brand and model of router." args "--file-name=imagetag_cmdline" option "kernel" i "File with LZMA compressed kernel to include in the image." string typestr="filename" required option "rootfs" f "File with RootFS to include in the image." string typestr="filename" required option "output" o "Name of output file." string typestr="filename" required option "cfe" - "File with CFE to include in the image." string typestr="filename" optional option "boardid" b "Board ID to set in the image (must match what router expects, e.g. \"96345GW2\")." string required option "chipid" c "Chip ID to set in the image (must match the actual hardware, e.g. \"6345\")." string required option "flash-start" s "Flash start address." string typestr="address" optional default="0xBFC00000" option "image-offset" n "Offset from start address for the first byte after the CFE (in memory)." string typestr="offset" default="0x10000" optional option "tag-version" v "Version number for imagetag format." string default="6" optional option "signature" a "Magic string (signature), for boards that need it." string default="Broadcom Corporatio" optional option "signature2" m "Second magic string (signature2)." string default="ver. 2.0" optional option "block-size" k "Flash erase block size." string optional default="0x10000" option "load-addr" l "Kernel load address." string typestr="address" required option "entry" e "Address where the kernel entry point will be for booting." string typestr="address" required option "layoutver" y "Flash layout version (version 2.2x of the Broadcom code requires this)." string optional option "info1" 1 "String for first vendor information section." string optional option "altinfo" - "String for vendor information section (alternate/pirelli)." string optional option "info2" 2 "String for second vendor information section." string optional option "root-first" - "Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory)." flag off option "rsa-signature" r "String for RSA Signature section." string optional option "second-image-flag" - "Dual Image Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional option "inactive" - "Inactive Flag (2=not-specified)." values="0", "1", "2" default="2" typestr="flag-value" optional option "reserved2" - "String for second reserved section." string optional option "kernel-file-has-header" - "Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed" flag off option "pad" p "Pad the image to this size if smaller (in MiB)" int typestr="size (in MiB)" optional ================================================ FILE: src/firmware-tools/imagetag_cmdline.c ================================================ /* File autogenerated by gengetopt version 2.22.4 generated with the following command: gengetopt --file-name=imagetag_cmdline --file-name=imagetag_cmdline The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "imagetag_cmdline.h" const char *gengetopt_args_info_purpose = "Generate image with CFE imagetag for Broadcom 63xx routers."; const char *gengetopt_args_info_usage = "Usage: imagetag [OPTIONS]..."; const char *gengetopt_args_info_description = "Copyright (C) 2008 Axel Gembe\nCopyright (C) 2009-2010 Daniel Dickinson\nLicensed unter the terms of the Gnu General Public License.\n\nGiven a root filesystem, a linux kernel, and an optional CFE, generates an \nimage with an imagetag for a Broadcom 63xx-based router. Additional parameters \nto be specified depend on the specfic brand and model of router."; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -i, --kernel=filename File with LZMA compressed kernel to include in \n the image.", " -f, --rootfs=filename File with RootFS to include in the image.", " -o, --output=filename Name of output file.", " --cfe=filename File with CFE to include in the image.", " -b, --boardid=STRING Board ID to set in the image (must match what \n router expects, e.g. \"96345GW2\").", " -c, --chipid=STRING Chip ID to set in the image (must match the \n actual hardware, e.g. \"6345\").", " -s, --flash-start=address Flash start address. (default=`0xBFC00000')", " -n, --image-offset=offset Offset from start address for the first byte \n after the CFE (in memory). \n (default=`0x10000')", " -v, --tag-version=STRING Version number for imagetag format. \n (default=`6')", " -a, --signature=STRING Magic string (signature), for boards that need \n it. (default=`Broadcom Corporatio')", " -m, --signature2=STRING Second magic string (signature2). \n (default=`ver. 2.0')", " -k, --block-size=STRING Flash erase block size. (default=`0x10000')", " -l, --load-addr=address Kernel load address.", " -e, --entry=address Address where the kernel entry point will be \n for booting.", " -y, --layoutver=STRING Flash layout version (version 2.2x of the \n Broadcom code requires this).", " -1, --info1=STRING String for first vendor information section.", " --altinfo=STRING String for vendor information section \n (alternate/pirelli).", " -2, --info2=STRING String for second vendor information section.", " --root-first Put the rootfs before the kernel (only for \n stock images, e.g. captured from the router's \n flash memory). (default=off)", " -r, --rsa-signature=STRING String for RSA Signature section.", " --second-image-flag=flag-value\n Dual Image Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')", " --inactive=flag-value Inactive Flag (2=not-specified). (possible \n values=\"0\", \"1\", \"2\" default=`2')", " --reserved2=STRING String for second reserved section.", " --kernel-file-has-header Indicates that the kernel file includes the \n kernel header with correct load address and \n entry point, so no changes are needed \n (default=off)", " -p, --pad=size (in MiB) Pad the image to this size if smaller (in MiB)", 0 }; typedef enum {ARG_NO , ARG_FLAG , ARG_STRING , ARG_INT } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); static int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); const char *cmdline_parser_second_image_flag_values[] = {"0", "1", "2", 0}; /*< Possible values for second-image-flag. */ const char *cmdline_parser_inactive_values[] = {"0", "1", "2", 0}; /*< Possible values for inactive. */ static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->kernel_given = 0 ; args_info->rootfs_given = 0 ; args_info->output_given = 0 ; args_info->cfe_given = 0 ; args_info->boardid_given = 0 ; args_info->chipid_given = 0 ; args_info->flash_start_given = 0 ; args_info->image_offset_given = 0 ; args_info->tag_version_given = 0 ; args_info->signature_given = 0 ; args_info->signature2_given = 0 ; args_info->block_size_given = 0 ; args_info->load_addr_given = 0 ; args_info->entry_given = 0 ; args_info->layoutver_given = 0 ; args_info->info1_given = 0 ; args_info->altinfo_given = 0 ; args_info->info2_given = 0 ; args_info->root_first_given = 0 ; args_info->rsa_signature_given = 0 ; args_info->second_image_flag_given = 0 ; args_info->inactive_given = 0 ; args_info->reserved2_given = 0 ; args_info->kernel_file_has_header_given = 0 ; args_info->pad_given = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->kernel_arg = NULL; args_info->kernel_orig = NULL; args_info->rootfs_arg = NULL; args_info->rootfs_orig = NULL; args_info->output_arg = NULL; args_info->output_orig = NULL; args_info->cfe_arg = NULL; args_info->cfe_orig = NULL; args_info->boardid_arg = NULL; args_info->boardid_orig = NULL; args_info->chipid_arg = NULL; args_info->chipid_orig = NULL; args_info->flash_start_arg = gengetopt_strdup ("0xBFC00000"); args_info->flash_start_orig = NULL; args_info->image_offset_arg = gengetopt_strdup ("0x10000"); args_info->image_offset_orig = NULL; args_info->tag_version_arg = gengetopt_strdup ("6"); args_info->tag_version_orig = NULL; args_info->signature_arg = gengetopt_strdup ("Broadcom Corporatio"); args_info->signature_orig = NULL; args_info->signature2_arg = gengetopt_strdup ("ver. 2.0"); args_info->signature2_orig = NULL; args_info->block_size_arg = gengetopt_strdup ("0x10000"); args_info->block_size_orig = NULL; args_info->load_addr_arg = NULL; args_info->load_addr_orig = NULL; args_info->entry_arg = NULL; args_info->entry_orig = NULL; args_info->layoutver_arg = NULL; args_info->layoutver_orig = NULL; args_info->info1_arg = NULL; args_info->info1_orig = NULL; args_info->altinfo_arg = NULL; args_info->altinfo_orig = NULL; args_info->info2_arg = NULL; args_info->info2_orig = NULL; args_info->root_first_flag = 0; args_info->rsa_signature_arg = NULL; args_info->rsa_signature_orig = NULL; args_info->second_image_flag_arg = gengetopt_strdup ("2"); args_info->second_image_flag_orig = NULL; args_info->inactive_arg = gengetopt_strdup ("2"); args_info->inactive_orig = NULL; args_info->reserved2_arg = NULL; args_info->reserved2_orig = NULL; args_info->kernel_file_has_header_flag = 0; args_info->pad_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->kernel_help = gengetopt_args_info_help[2] ; args_info->rootfs_help = gengetopt_args_info_help[3] ; args_info->output_help = gengetopt_args_info_help[4] ; args_info->cfe_help = gengetopt_args_info_help[5] ; args_info->boardid_help = gengetopt_args_info_help[6] ; args_info->chipid_help = gengetopt_args_info_help[7] ; args_info->flash_start_help = gengetopt_args_info_help[8] ; args_info->image_offset_help = gengetopt_args_info_help[9] ; args_info->tag_version_help = gengetopt_args_info_help[10] ; args_info->signature_help = gengetopt_args_info_help[11] ; args_info->signature2_help = gengetopt_args_info_help[12] ; args_info->block_size_help = gengetopt_args_info_help[13] ; args_info->load_addr_help = gengetopt_args_info_help[14] ; args_info->entry_help = gengetopt_args_info_help[15] ; args_info->layoutver_help = gengetopt_args_info_help[16] ; args_info->info1_help = gengetopt_args_info_help[17] ; args_info->altinfo_help = gengetopt_args_info_help[18] ; args_info->info2_help = gengetopt_args_info_help[19] ; args_info->root_first_help = gengetopt_args_info_help[20] ; args_info->rsa_signature_help = gengetopt_args_info_help[21] ; args_info->second_image_flag_help = gengetopt_args_info_help[22] ; args_info->inactive_help = gengetopt_args_info_help[23] ; args_info->reserved2_help = gengetopt_args_info_help[24] ; args_info->kernel_file_has_header_help = gengetopt_args_info_help[25] ; args_info->pad_help = gengetopt_args_info_help[26] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); } static void print_help_common(void) { cmdline_parser_print_version (); if (strlen(gengetopt_args_info_purpose) > 0) printf("\n%s\n", gengetopt_args_info_purpose); if (strlen(gengetopt_args_info_usage) > 0) printf("\n%s\n", gengetopt_args_info_usage); printf("\n"); if (strlen(gengetopt_args_info_description) > 0) printf("%s\n\n", gengetopt_args_info_description); } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_string_field (&(args_info->kernel_arg)); free_string_field (&(args_info->kernel_orig)); free_string_field (&(args_info->rootfs_arg)); free_string_field (&(args_info->rootfs_orig)); free_string_field (&(args_info->output_arg)); free_string_field (&(args_info->output_orig)); free_string_field (&(args_info->cfe_arg)); free_string_field (&(args_info->cfe_orig)); free_string_field (&(args_info->boardid_arg)); free_string_field (&(args_info->boardid_orig)); free_string_field (&(args_info->chipid_arg)); free_string_field (&(args_info->chipid_orig)); free_string_field (&(args_info->flash_start_arg)); free_string_field (&(args_info->flash_start_orig)); free_string_field (&(args_info->image_offset_arg)); free_string_field (&(args_info->image_offset_orig)); free_string_field (&(args_info->tag_version_arg)); free_string_field (&(args_info->tag_version_orig)); free_string_field (&(args_info->signature_arg)); free_string_field (&(args_info->signature_orig)); free_string_field (&(args_info->signature2_arg)); free_string_field (&(args_info->signature2_orig)); free_string_field (&(args_info->block_size_arg)); free_string_field (&(args_info->block_size_orig)); free_string_field (&(args_info->load_addr_arg)); free_string_field (&(args_info->load_addr_orig)); free_string_field (&(args_info->entry_arg)); free_string_field (&(args_info->entry_orig)); free_string_field (&(args_info->layoutver_arg)); free_string_field (&(args_info->layoutver_orig)); free_string_field (&(args_info->info1_arg)); free_string_field (&(args_info->info1_orig)); free_string_field (&(args_info->altinfo_arg)); free_string_field (&(args_info->altinfo_orig)); free_string_field (&(args_info->info2_arg)); free_string_field (&(args_info->info2_orig)); free_string_field (&(args_info->rsa_signature_arg)); free_string_field (&(args_info->rsa_signature_orig)); free_string_field (&(args_info->second_image_flag_arg)); free_string_field (&(args_info->second_image_flag_orig)); free_string_field (&(args_info->inactive_arg)); free_string_field (&(args_info->inactive_orig)); free_string_field (&(args_info->reserved2_arg)); free_string_field (&(args_info->reserved2_orig)); free_string_field (&(args_info->pad_orig)); clear_given (args_info); } /** * @param val the value to check * @param values the possible values * @return the index of the matched value: * -1 if no value matched, * -2 if more than one value has matched */ static int check_possible_values(const char *val, const char *values[]) { int i, found, last; size_t len; if (!val) /* otherwise strlen() crashes below */ return -1; /* -1 means no argument for the option */ found = last = 0; for (i = 0, len = strlen(val); values[i]; ++i) { if (strncmp(val, values[i], len) == 0) { ++found; last = i; if (strlen(values[i]) == len) return i; /* exact macth no need to check more */ } } if (found == 1) /* one match: OK */ return last; return (found ? -2 : -1); /* return many values or none matched */ } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { int found = -1; if (arg) { if (values) { found = check_possible_values(arg, values); } if (found >= 0) fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]); else fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->kernel_given) write_into_file(outfile, "kernel", args_info->kernel_orig, 0); if (args_info->rootfs_given) write_into_file(outfile, "rootfs", args_info->rootfs_orig, 0); if (args_info->output_given) write_into_file(outfile, "output", args_info->output_orig, 0); if (args_info->cfe_given) write_into_file(outfile, "cfe", args_info->cfe_orig, 0); if (args_info->boardid_given) write_into_file(outfile, "boardid", args_info->boardid_orig, 0); if (args_info->chipid_given) write_into_file(outfile, "chipid", args_info->chipid_orig, 0); if (args_info->flash_start_given) write_into_file(outfile, "flash-start", args_info->flash_start_orig, 0); if (args_info->image_offset_given) write_into_file(outfile, "image-offset", args_info->image_offset_orig, 0); if (args_info->tag_version_given) write_into_file(outfile, "tag-version", args_info->tag_version_orig, 0); if (args_info->signature_given) write_into_file(outfile, "signature", args_info->signature_orig, 0); if (args_info->signature2_given) write_into_file(outfile, "signature2", args_info->signature2_orig, 0); if (args_info->block_size_given) write_into_file(outfile, "block-size", args_info->block_size_orig, 0); if (args_info->load_addr_given) write_into_file(outfile, "load-addr", args_info->load_addr_orig, 0); if (args_info->entry_given) write_into_file(outfile, "entry", args_info->entry_orig, 0); if (args_info->layoutver_given) write_into_file(outfile, "layoutver", args_info->layoutver_orig, 0); if (args_info->info1_given) write_into_file(outfile, "info1", args_info->info1_orig, 0); if (args_info->altinfo_given) write_into_file(outfile, "altinfo", args_info->altinfo_orig, 0); if (args_info->info2_given) write_into_file(outfile, "info2", args_info->info2_orig, 0); if (args_info->root_first_given) write_into_file(outfile, "root-first", 0, 0 ); if (args_info->rsa_signature_given) write_into_file(outfile, "rsa-signature", args_info->rsa_signature_orig, 0); if (args_info->second_image_flag_given) write_into_file(outfile, "second-image-flag", args_info->second_image_flag_orig, cmdline_parser_second_image_flag_values); if (args_info->inactive_given) write_into_file(outfile, "inactive", args_info->inactive_orig, cmdline_parser_inactive_values); if (args_info->reserved2_given) write_into_file(outfile, "reserved2", args_info->reserved2_orig, 0); if (args_info->kernel_file_has_header_given) write_into_file(outfile, "kernel-file-has-header", 0, 0 ); if (args_info->pad_given) write_into_file(outfile, "pad", args_info->pad_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { int result = EXIT_SUCCESS; if (cmdline_parser_required2(args_info, prog_name, 0) > 0) result = EXIT_FAILURE; if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) { int error = 0; FIX_UNUSED (additional_error); /* checks for required options */ if (! args_info->kernel_given) { fprintf (stderr, "%s: '--kernel' ('-i') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->rootfs_given) { fprintf (stderr, "%s: '--rootfs' ('-f') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->output_given) { fprintf (stderr, "%s: '--output' ('-o') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->boardid_given) { fprintf (stderr, "%s: '--boardid' ('-b') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->chipid_given) { fprintf (stderr, "%s: '--chipid' ('-c') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->load_addr_given) { fprintf (stderr, "%s: '--load-addr' ('-l') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } if (! args_info->entry_given) { fprintf (stderr, "%s: '--entry' ('-e') option required%s\n", prog_name, (additional_error ? additional_error : "")); error = 1; } /* checks for dependences among options */ return error; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0) { if (short_opt != '-') fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_FLAG: *((int *)field) = !*((int *)field); break; case ARG_INT: if (val) *((int *)field) = strtol (val, &stop_char, 0); break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* check numeric conversion */ switch(arg_type) { case ARG_INT: if (val && !(stop_char && *stop_char == '\0')) { fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); return 1; /* failure */ } break; default: ; }; /* store the original value */ switch(arg_type) { case ARG_NO: case ARG_FLAG: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; override = params->override; initialize = params->initialize; check_required = params->check_required; check_ambiguity = params->check_ambiguity; if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "kernel", 1, NULL, 'i' }, { "rootfs", 1, NULL, 'f' }, { "output", 1, NULL, 'o' }, { "cfe", 1, NULL, 0 }, { "boardid", 1, NULL, 'b' }, { "chipid", 1, NULL, 'c' }, { "flash-start", 1, NULL, 's' }, { "image-offset", 1, NULL, 'n' }, { "tag-version", 1, NULL, 'v' }, { "signature", 1, NULL, 'a' }, { "signature2", 1, NULL, 'm' }, { "block-size", 1, NULL, 'k' }, { "load-addr", 1, NULL, 'l' }, { "entry", 1, NULL, 'e' }, { "layoutver", 1, NULL, 'y' }, { "info1", 1, NULL, '1' }, { "altinfo", 1, NULL, 0 }, { "info2", 1, NULL, '2' }, { "root-first", 0, NULL, 0 }, { "rsa-signature", 1, NULL, 'r' }, { "second-image-flag", 1, NULL, 0 }, { "inactive", 1, NULL, 0 }, { "reserved2", 1, NULL, 0 }, { "kernel-file-has-header", 0, NULL, 0 }, { "pad", 1, NULL, 'p' }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVi:f:o:b:c:s:n:v:a:m:k:l:e:y:1:2:r:p:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'i': /* File with LZMA compressed kernel to include in the image.. */ if (update_arg( (void *)&(args_info->kernel_arg), &(args_info->kernel_orig), &(args_info->kernel_given), &(local_args_info.kernel_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "kernel", 'i', additional_error)) goto failure; break; case 'f': /* File with RootFS to include in the image.. */ if (update_arg( (void *)&(args_info->rootfs_arg), &(args_info->rootfs_orig), &(args_info->rootfs_given), &(local_args_info.rootfs_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "rootfs", 'f', additional_error)) goto failure; break; case 'o': /* Name of output file.. */ if (update_arg( (void *)&(args_info->output_arg), &(args_info->output_orig), &(args_info->output_given), &(local_args_info.output_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "output", 'o', additional_error)) goto failure; break; case 'b': /* Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */ if (update_arg( (void *)&(args_info->boardid_arg), &(args_info->boardid_orig), &(args_info->boardid_given), &(local_args_info.boardid_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "boardid", 'b', additional_error)) goto failure; break; case 'c': /* Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */ if (update_arg( (void *)&(args_info->chipid_arg), &(args_info->chipid_orig), &(args_info->chipid_given), &(local_args_info.chipid_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "chipid", 'c', additional_error)) goto failure; break; case 's': /* Flash start address.. */ if (update_arg( (void *)&(args_info->flash_start_arg), &(args_info->flash_start_orig), &(args_info->flash_start_given), &(local_args_info.flash_start_given), optarg, 0, "0xBFC00000", ARG_STRING, check_ambiguity, override, 0, 0, "flash-start", 's', additional_error)) goto failure; break; case 'n': /* Offset from start address for the first byte after the CFE (in memory).. */ if (update_arg( (void *)&(args_info->image_offset_arg), &(args_info->image_offset_orig), &(args_info->image_offset_given), &(local_args_info.image_offset_given), optarg, 0, "0x10000", ARG_STRING, check_ambiguity, override, 0, 0, "image-offset", 'n', additional_error)) goto failure; break; case 'v': /* Version number for imagetag format.. */ if (update_arg( (void *)&(args_info->tag_version_arg), &(args_info->tag_version_orig), &(args_info->tag_version_given), &(local_args_info.tag_version_given), optarg, 0, "6", ARG_STRING, check_ambiguity, override, 0, 0, "tag-version", 'v', additional_error)) goto failure; break; case 'a': /* Magic string (signature), for boards that need it.. */ if (update_arg( (void *)&(args_info->signature_arg), &(args_info->signature_orig), &(args_info->signature_given), &(local_args_info.signature_given), optarg, 0, "Broadcom Corporatio", ARG_STRING, check_ambiguity, override, 0, 0, "signature", 'a', additional_error)) goto failure; break; case 'm': /* Second magic string (signature2).. */ if (update_arg( (void *)&(args_info->signature2_arg), &(args_info->signature2_orig), &(args_info->signature2_given), &(local_args_info.signature2_given), optarg, 0, "ver. 2.0", ARG_STRING, check_ambiguity, override, 0, 0, "signature2", 'm', additional_error)) goto failure; break; case 'k': /* Flash erase block size.. */ if (update_arg( (void *)&(args_info->block_size_arg), &(args_info->block_size_orig), &(args_info->block_size_given), &(local_args_info.block_size_given), optarg, 0, "0x10000", ARG_STRING, check_ambiguity, override, 0, 0, "block-size", 'k', additional_error)) goto failure; break; case 'l': /* Kernel load address.. */ if (update_arg( (void *)&(args_info->load_addr_arg), &(args_info->load_addr_orig), &(args_info->load_addr_given), &(local_args_info.load_addr_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "load-addr", 'l', additional_error)) goto failure; break; case 'e': /* Address where the kernel entry point will be for booting.. */ if (update_arg( (void *)&(args_info->entry_arg), &(args_info->entry_orig), &(args_info->entry_given), &(local_args_info.entry_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "entry", 'e', additional_error)) goto failure; break; case 'y': /* Flash layout version (version 2.2x of the Broadcom code requires this).. */ if (update_arg( (void *)&(args_info->layoutver_arg), &(args_info->layoutver_orig), &(args_info->layoutver_given), &(local_args_info.layoutver_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "layoutver", 'y', additional_error)) goto failure; break; case '1': /* String for first vendor information section.. */ if (update_arg( (void *)&(args_info->info1_arg), &(args_info->info1_orig), &(args_info->info1_given), &(local_args_info.info1_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "info1", '1', additional_error)) goto failure; break; case '2': /* String for second vendor information section.. */ if (update_arg( (void *)&(args_info->info2_arg), &(args_info->info2_orig), &(args_info->info2_given), &(local_args_info.info2_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "info2", '2', additional_error)) goto failure; break; case 'r': /* String for RSA Signature section.. */ if (update_arg( (void *)&(args_info->rsa_signature_arg), &(args_info->rsa_signature_orig), &(args_info->rsa_signature_given), &(local_args_info.rsa_signature_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "rsa-signature", 'r', additional_error)) goto failure; break; case 'p': /* Pad the image to this size if smaller (in MiB). */ if (update_arg( (void *)&(args_info->pad_arg), &(args_info->pad_orig), &(args_info->pad_given), &(local_args_info.pad_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "pad", 'p', additional_error)) goto failure; break; case 0: /* Long option with no short option */ /* File with CFE to include in the image.. */ if (strcmp (long_options[option_index].name, "cfe") == 0) { if (update_arg( (void *)&(args_info->cfe_arg), &(args_info->cfe_orig), &(args_info->cfe_given), &(local_args_info.cfe_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "cfe", '-', additional_error)) goto failure; } /* String for vendor information section (alternate/pirelli).. */ else if (strcmp (long_options[option_index].name, "altinfo") == 0) { if (update_arg( (void *)&(args_info->altinfo_arg), &(args_info->altinfo_orig), &(args_info->altinfo_given), &(local_args_info.altinfo_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "altinfo", '-', additional_error)) goto failure; } /* Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory).. */ else if (strcmp (long_options[option_index].name, "root-first") == 0) { if (update_arg((void *)&(args_info->root_first_flag), 0, &(args_info->root_first_given), &(local_args_info.root_first_given), optarg, 0, 0, ARG_FLAG, check_ambiguity, override, 1, 0, "root-first", '-', additional_error)) goto failure; } /* Dual Image Flag (2=not-specified).. */ else if (strcmp (long_options[option_index].name, "second-image-flag") == 0) { if (update_arg( (void *)&(args_info->second_image_flag_arg), &(args_info->second_image_flag_orig), &(args_info->second_image_flag_given), &(local_args_info.second_image_flag_given), optarg, cmdline_parser_second_image_flag_values, "2", ARG_STRING, check_ambiguity, override, 0, 0, "second-image-flag", '-', additional_error)) goto failure; } /* Inactive Flag (2=not-specified).. */ else if (strcmp (long_options[option_index].name, "inactive") == 0) { if (update_arg( (void *)&(args_info->inactive_arg), &(args_info->inactive_orig), &(args_info->inactive_given), &(local_args_info.inactive_given), optarg, cmdline_parser_inactive_values, "2", ARG_STRING, check_ambiguity, override, 0, 0, "inactive", '-', additional_error)) goto failure; } /* String for second reserved section.. */ else if (strcmp (long_options[option_index].name, "reserved2") == 0) { if (update_arg( (void *)&(args_info->reserved2_arg), &(args_info->reserved2_orig), &(args_info->reserved2_given), &(local_args_info.reserved2_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "reserved2", '-', additional_error)) goto failure; } /* Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed. */ else if (strcmp (long_options[option_index].name, "kernel-file-has-header") == 0) { if (update_arg((void *)&(args_info->kernel_file_has_header_flag), 0, &(args_info->kernel_file_has_header_given), &(local_args_info.kernel_file_has_header_given), optarg, 0, 0, ARG_FLAG, check_ambiguity, override, 1, 0, "kernel-file-has-header", '-', additional_error)) goto failure; } break; case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ if (check_required) { error += cmdline_parser_required2 (args_info, argv[0], additional_error); } cmdline_parser_release (&local_args_info); if ( error ) return (EXIT_FAILURE); return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } ================================================ FILE: src/firmware-tools/imagetag_cmdline.h ================================================ /** @file imagetag_cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.22.4 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt by Lorenzo Bettini */ #ifndef IMAGETAG_CMDLINE_H #define IMAGETAG_CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE "imagetag" #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #define CMDLINE_PARSER_PACKAGE_NAME "imagetag" #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION "2.0.0" #endif /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ char * kernel_arg; /**< @brief File with LZMA compressed kernel to include in the image.. */ char * kernel_orig; /**< @brief File with LZMA compressed kernel to include in the image. original value given at command line. */ const char *kernel_help; /**< @brief File with LZMA compressed kernel to include in the image. help description. */ char * rootfs_arg; /**< @brief File with RootFS to include in the image.. */ char * rootfs_orig; /**< @brief File with RootFS to include in the image. original value given at command line. */ const char *rootfs_help; /**< @brief File with RootFS to include in the image. help description. */ char * output_arg; /**< @brief Name of output file.. */ char * output_orig; /**< @brief Name of output file. original value given at command line. */ const char *output_help; /**< @brief Name of output file. help description. */ char * cfe_arg; /**< @brief File with CFE to include in the image.. */ char * cfe_orig; /**< @brief File with CFE to include in the image. original value given at command line. */ const char *cfe_help; /**< @brief File with CFE to include in the image. help description. */ char * boardid_arg; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\").. */ char * boardid_orig; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). original value given at command line. */ const char *boardid_help; /**< @brief Board ID to set in the image (must match what router expects, e.g. \"96345GW2\"). help description. */ char * chipid_arg; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\").. */ char * chipid_orig; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). original value given at command line. */ const char *chipid_help; /**< @brief Chip ID to set in the image (must match the actual hardware, e.g. \"6345\"). help description. */ char * flash_start_arg; /**< @brief Flash start address. (default='0xBFC00000'). */ char * flash_start_orig; /**< @brief Flash start address. original value given at command line. */ const char *flash_start_help; /**< @brief Flash start address. help description. */ char * image_offset_arg; /**< @brief Offset from start address for the first byte after the CFE (in memory). (default='0x10000'). */ char * image_offset_orig; /**< @brief Offset from start address for the first byte after the CFE (in memory). original value given at command line. */ const char *image_offset_help; /**< @brief Offset from start address for the first byte after the CFE (in memory). help description. */ char * tag_version_arg; /**< @brief Version number for imagetag format. (default='6'). */ char * tag_version_orig; /**< @brief Version number for imagetag format. original value given at command line. */ const char *tag_version_help; /**< @brief Version number for imagetag format. help description. */ char * signature_arg; /**< @brief Magic string (signature), for boards that need it. (default='Broadcom Corporatio'). */ char * signature_orig; /**< @brief Magic string (signature), for boards that need it. original value given at command line. */ const char *signature_help; /**< @brief Magic string (signature), for boards that need it. help description. */ char * signature2_arg; /**< @brief Second magic string (signature2). (default='ver. 2.0'). */ char * signature2_orig; /**< @brief Second magic string (signature2). original value given at command line. */ const char *signature2_help; /**< @brief Second magic string (signature2). help description. */ char * block_size_arg; /**< @brief Flash erase block size. (default='0x10000'). */ char * block_size_orig; /**< @brief Flash erase block size. original value given at command line. */ const char *block_size_help; /**< @brief Flash erase block size. help description. */ char * load_addr_arg; /**< @brief Kernel load address.. */ char * load_addr_orig; /**< @brief Kernel load address. original value given at command line. */ const char *load_addr_help; /**< @brief Kernel load address. help description. */ char * entry_arg; /**< @brief Address where the kernel entry point will be for booting.. */ char * entry_orig; /**< @brief Address where the kernel entry point will be for booting. original value given at command line. */ const char *entry_help; /**< @brief Address where the kernel entry point will be for booting. help description. */ char * layoutver_arg; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this).. */ char * layoutver_orig; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). original value given at command line. */ const char *layoutver_help; /**< @brief Flash layout version (version 2.2x of the Broadcom code requires this). help description. */ char * info1_arg; /**< @brief String for first vendor information section.. */ char * info1_orig; /**< @brief String for first vendor information section. original value given at command line. */ const char *info1_help; /**< @brief String for first vendor information section. help description. */ char * altinfo_arg; /**< @brief String for vendor information section (alternate/pirelli).. */ char * altinfo_orig; /**< @brief String for vendor information section (alternate/pirelli). original value given at command line. */ const char *altinfo_help; /**< @brief String for vendor information section (alternate/pirelli). help description. */ char * info2_arg; /**< @brief String for second vendor information section.. */ char * info2_orig; /**< @brief String for second vendor information section. original value given at command line. */ const char *info2_help; /**< @brief String for second vendor information section. help description. */ int root_first_flag; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). (default=off). */ const char *root_first_help; /**< @brief Put the rootfs before the kernel (only for stock images, e.g. captured from the router's flash memory). help description. */ char * rsa_signature_arg; /**< @brief String for RSA Signature section.. */ char * rsa_signature_orig; /**< @brief String for RSA Signature section. original value given at command line. */ const char *rsa_signature_help; /**< @brief String for RSA Signature section. help description. */ char * second_image_flag_arg; /**< @brief Dual Image Flag (2=not-specified). (default='2'). */ char * second_image_flag_orig; /**< @brief Dual Image Flag (2=not-specified). original value given at command line. */ const char *second_image_flag_help; /**< @brief Dual Image Flag (2=not-specified). help description. */ char * inactive_arg; /**< @brief Inactive Flag (2=not-specified). (default='2'). */ char * inactive_orig; /**< @brief Inactive Flag (2=not-specified). original value given at command line. */ const char *inactive_help; /**< @brief Inactive Flag (2=not-specified). help description. */ char * reserved2_arg; /**< @brief String for second reserved section.. */ char * reserved2_orig; /**< @brief String for second reserved section. original value given at command line. */ const char *reserved2_help; /**< @brief String for second reserved section. help description. */ int kernel_file_has_header_flag; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed (default=off). */ const char *kernel_file_has_header_help; /**< @brief Indicates that the kernel file includes the kernel header with correct load address and entry point, so no changes are needed help description. */ int pad_arg; /**< @brief Pad the image to this size if smaller (in MiB). */ char * pad_orig; /**< @brief Pad the image to this size if smaller (in MiB) original value given at command line. */ const char *pad_help; /**< @brief Pad the image to this size if smaller (in MiB) help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int kernel_given ; /**< @brief Whether kernel was given. */ unsigned int rootfs_given ; /**< @brief Whether rootfs was given. */ unsigned int output_given ; /**< @brief Whether output was given. */ unsigned int cfe_given ; /**< @brief Whether cfe was given. */ unsigned int boardid_given ; /**< @brief Whether boardid was given. */ unsigned int chipid_given ; /**< @brief Whether chipid was given. */ unsigned int flash_start_given ; /**< @brief Whether flash-start was given. */ unsigned int image_offset_given ; /**< @brief Whether image-offset was given. */ unsigned int tag_version_given ; /**< @brief Whether tag-version was given. */ unsigned int signature_given ; /**< @brief Whether signature was given. */ unsigned int signature2_given ; /**< @brief Whether signature2 was given. */ unsigned int block_size_given ; /**< @brief Whether block-size was given. */ unsigned int load_addr_given ; /**< @brief Whether load-addr was given. */ unsigned int entry_given ; /**< @brief Whether entry was given. */ unsigned int layoutver_given ; /**< @brief Whether layoutver was given. */ unsigned int info1_given ; /**< @brief Whether info1 was given. */ unsigned int altinfo_given ; /**< @brief Whether altinfo was given. */ unsigned int info2_given ; /**< @brief Whether info2 was given. */ unsigned int root_first_given ; /**< @brief Whether root-first was given. */ unsigned int rsa_signature_given ; /**< @brief Whether rsa-signature was given. */ unsigned int second_image_flag_given ; /**< @brief Whether second-image-flag was given. */ unsigned int inactive_given ; /**< @brief Whether inactive was given. */ unsigned int reserved2_given ; /**< @brief Whether reserved2 was given. */ unsigned int kernel_file_has_header_given ; /**< @brief Whether kernel-file-has-header was given. */ unsigned int pad_given ; /**< @brief Whether pad was given. */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); extern const char *cmdline_parser_second_image_flag_values[]; /**< @brief Possible values for second-image-flag. */ extern const char *cmdline_parser_inactive_values[]; /**< @brief Possible values for inactive. */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* IMAGETAG_CMDLINE_H */ ================================================ FILE: src/firmware-tools/lzma2eva.c ================================================ /* lzma2eva - convert lzma-compressed file to AVM EVA bootloader format Copyright (C) 2007 Enrik Berkhan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include /* crc32 */ #define checksum_add32(csum, data) \ csum += ((uint8_t *)&data)[0]; \ csum += ((uint8_t *)&data)[1]; \ csum += ((uint8_t *)&data)[2]; \ csum += ((uint8_t *)&data)[3]; void usage(void) { fprintf(stderr, "usage: lzma2eva \n"); exit(1); } void pexit(const char *msg) { perror(msg); exit(1); } int main(int argc, char *argv[]) { const char *infile, *outfile; FILE *in, *out; static const uint8_t buf[4096]; size_t elems; uint8_t properties; uint32_t dictsize; uint64_t datasize; uint32_t magic = 0xfeed1281L; uint32_t reclength = 0; fpos_t reclengthpos; uint32_t loadaddress = 0; uint32_t type = 0x075a0201L; /* might be 7Z 2.1? */ uint32_t checksum = 0; uint32_t compsize = 0; fpos_t compsizepos; uint32_t datasize32 = 0; uint32_t datacrc32 = crc32(0, 0, 0); uint32_t zero = 0; uint32_t entry = 0; if (argc != 5) usage(); /* "parse" command line */ loadaddress = strtoul(argv[1], 0, 0); entry = strtoul(argv[2], 0, 0); infile = argv[3]; outfile = argv[4]; in = fopen(infile, "rb"); if (!in) pexit("fopen"); out = fopen(outfile, "w+b"); if (!out) pexit("fopen"); /* read LZMA header */ if (1 != fread(&properties, sizeof properties, 1, in)) pexit("fread"); if (1 != fread(&dictsize, sizeof dictsize, 1, in)) pexit("fread"); if (1 != fread(&datasize, sizeof datasize, 1, in)) pexit("fread"); /* write EVA header */ if (1 != fwrite(&magic, sizeof magic, 1, out)) pexit("fwrite"); if (fgetpos(out, &reclengthpos)) pexit("fgetpos"); if (1 != fwrite(&reclength, sizeof reclength, 1, out)) pexit("fwrite"); if (1 != fwrite(&loadaddress, sizeof loadaddress, 1, out)) pexit("fwrite"); if (1 != fwrite(&type, sizeof type, 1, out)) pexit("fwrite"); /* write EVA LZMA header */ if (fgetpos(out, &compsizepos)) pexit("fgetpos"); if (1 != fwrite(&compsize, sizeof compsize, 1, out)) pexit("fwrite"); /* XXX check length */ datasize32 = (uint32_t)datasize; if (1 != fwrite(&datasize32, sizeof datasize32, 1, out)) pexit("fwrite"); if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out)) pexit("fwrite"); /* write modified LZMA header */ if (1 != fwrite(&properties, sizeof properties, 1, out)) pexit("fwrite"); if (1 != fwrite(&dictsize, sizeof dictsize, 1, out)) pexit("fwrite"); if (1 != fwrite(&zero, 3, 1, out)) pexit("fwrite"); /* copy compressed data, calculate crc32 */ while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, in))) { compsize += elems; if (elems != fwrite(&buf, sizeof buf[0], elems, out)) pexit("fwrite"); datacrc32 = crc32(datacrc32, buf, elems); } if (ferror(in)) pexit("fread"); fclose(in); /* re-write record length */ reclength = compsize + 24; if (fsetpos(out, &reclengthpos)) pexit("fsetpos"); if (1 != fwrite(&reclength, sizeof reclength, 1, out)) pexit("fwrite"); /* re-write EVA LZMA header including size and data crc */ if (fsetpos(out, &compsizepos)) pexit("fsetpos"); if (1 != fwrite(&compsize, sizeof compsize, 1, out)) pexit("fwrite"); if (1 != fwrite(&datasize32, sizeof datasize32, 1, out)) pexit("fwrite"); if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out)) pexit("fwrite"); /* calculate record checksum */ checksum += reclength; checksum += loadaddress; checksum_add32(checksum, type); checksum_add32(checksum, compsize); checksum_add32(checksum, datasize32); checksum_add32(checksum, datacrc32); if (fseek(out, 0, SEEK_CUR)) pexit("fseek"); while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, out))) { size_t i; for (i = 0; i < elems; ++i) checksum += buf[i]; } if (ferror(out)) pexit("fread"); if (fseek(out, 0, SEEK_CUR)) pexit("fseek"); checksum = ~checksum + 1; if (1 != fwrite(&checksum, sizeof checksum, 1, out)) pexit("fwrite"); /* write entry record */ if (1 != fwrite(&zero, sizeof zero, 1, out)) pexit("fwrite"); if (1 != fwrite(&entry, sizeof entry, 1, out)) pexit("fwrite"); if (fclose(out)) pexit("fclose"); return 0; } ================================================ FILE: src/firmware-tools/makeamitbin.c ================================================ /* * makeamitbin - create firmware binaries for MGB100 * * Copyright (C) 2007 Volker Weiss * Christian Welzel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include /* defaults: Level One WAP-0007 */ static char *ascii1 = "DDC_RUS001"; static char *ascii2 = "Queen"; static struct hdrinfo { char *name; unsigned long unknown; /* can probably be any number, maybe version number */ int topalign; unsigned int addr; unsigned int size; } hdrinfo[] = { { "bios", 0xc76be111, 1, 0x3fa000, 0x006000 }, /* BIOS */ { "recovery", 0xc76be222, 0, 0x3f0000, 0x004000 }, /* Recovery Loader */ { "linux", 0xc76bee9d, 0, 0x000000, 0x100000 }, /* Linux */ { "ramdisk", 0xc76bee9d, 0, 0x100000, 0x280000 }, /* ramdisk */ { "amitconfig", 0xc76bee8b, 0, 0x380000, 0x060000 }, /* AMIT config */ { "redboot", 0x00000000, 1, 0x3d0000, 0x030000 }, /* Redboot 128kB image */ { "redbootlow", 0, 0, 0x3e0000, 0x18000 }, /* Redboot 1. part */ { "redboothigh", 0, 0, 0x3fa000, 0x6000 }, /* Redboot 2. part */ { "linux3g", 0xcb5f06b5, 0, 0x000000, 0x100000 }, /* Linux */ { "ramdisk3g", 0xcb5f06b5, 0, 0x100000, 0x280000 }, /* ramdisk */ { NULL } }; /* CHD2WLANU_R400b7 11e1 6bc7 22e2 6bc7 5dc3 47c8 5cc3 47c8 21c3 47c8 */ /* 20060106_DDC_WAP-0007_R400b4 11e1 6bc7 22e2 6bc7 9dee 6bc7 9dee 6bc7 8bee 6bc7 */ /* WMU-6000FS_R400b6 11e1 6bc7 22e2 6bc7 6d2d 0fc8 6c2d 0fc8 542d 0fc8 */ /* WAP-0007(R4.00b8)_2006-10-02 9979 5fc8 22e2 6bc7 c46e cec8 c36e cec8 a76e cec8 */ #define HDRSIZE 80 #define COPY_SHORT(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \ d[o+1] = (unsigned char)(((v) >> 8) & 0xff) #define COPY_LONG(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \ d[o+1] = (unsigned char)(((v) >> 8) & 0xff); \ d[o+2] = (unsigned char)(((v) >> 16) & 0xff); \ d[o+3] = (unsigned char)(((v) >> 24) & 0xff) #define READ_SHORT(d, o) ((unsigned short)(d[o+0]) + \ (((unsigned short)(d[o+1])) << 8)) /* 00..0d ASCII product ID 0e..0f checksum of payload 10..1b ASCII Queen 1c..1f AMIT BIOS: 11e1 6bc7, Recovery Tool: 22e2 6bc7 Linux: 5dc3 47c8, ramdisk: 5cc3 47c8 AMIT FS: 21c3 47c8 VERSION NUMBER?????? 20..23 offset in flash aligned to segment boundary 24..27 length in flash aligned to segment boundary 28..2b offset in flash (payload) 2c..2f length (payload) 30..3f always 0 40..47 always 4248 0101 5000 0001 (last maybe .....0501) 48..4b same as 20..23 4c..4d always 0b00 4e..4f inverted checksum of header */ unsigned short checksum(unsigned char *data, long size) { long n; unsigned short d, cs = 0; for (n = 0; n < size; n += 2) { d = READ_SHORT(data, n); cs += d; if (cs < d) cs++; } if (size & 1) { d = data[n]; cs += d; if (cs < d) cs++; } return cs; } void showhdr(unsigned char *hdr) { int i, j; for (j = 0; j < 5; j++) { for (i = 0; i < 16; i++) { printf("%02x ", (unsigned int)(hdr[j * 16 + i])); } printf(" "); for (i = 0; i < 16; i++) { unsigned char d = hdr[j * 16 + i]; printf("%c", (d >= ' ' && d < 127) ? d : '.'); } printf("\n"); } } void makehdr(unsigned char *hdr, struct hdrinfo *info, unsigned char *data, long size, int last) { unsigned int offset = info->addr + 0x10; memset(hdr, 0, HDRSIZE); if (info->topalign) offset = info->addr + info->size - size; /* top align */ strncpy((char *)hdr + 0x00, ascii1, 14); strncpy((char *)hdr + 0x10, ascii2, 12); COPY_LONG(hdr, 0x1c, info->unknown); COPY_LONG(hdr, 0x20, info->addr); COPY_LONG(hdr, 0x24, info->size); COPY_LONG(hdr, 0x28, offset); COPY_LONG(hdr, 0x2c, size); COPY_LONG(hdr, 0x40, 0x01014842); COPY_LONG(hdr, 0x44, last ? 0x01050050 : 0x01000050); COPY_LONG(hdr, 0x48, info->addr); COPY_SHORT(hdr, 0x4c, info->unknown == 0xcb5f06b5 ? 0x0016 : 0x000b); COPY_SHORT(hdr, 0x0e, checksum(data, size)); COPY_SHORT(hdr, 0x4e, ~checksum(hdr, HDRSIZE)); } unsigned char *read_file(const char *name, long *size) { FILE *f; unsigned char *data = NULL; *size = 0; f = fopen(name, "r"); if (f != NULL) { if (fseek(f, 0, SEEK_END) == 0) { *size = ftell(f); if (*size != -1) { if (fseek(f, 0, SEEK_SET) == 0) { data = (unsigned char *)malloc(*size); if (data != NULL) { if (fread(data, sizeof(char), *size, f) != *size) { free(data); data = NULL; } } } } } fclose(f); } return data; } struct hdrinfo *find_hdrinfo(const char *name) { int n; for (n = 0; hdrinfo[n].name != NULL; n++) { if (strcmp(name, hdrinfo[n].name) == 0) return &hdrinfo[n]; } return NULL; } void oferror(FILE *f) { printf("file error\n"); exit(2); } void showhelp(void) { printf("Syntax: makeamitbin [options]\n"); printf("Options:\n"); printf(" -1 ID1\tFirmware identifier 1, e.g. 'DDC_RUS001' for manufacturer LevelOne\n"); printf(" -2 ID2\tFirmware identifier 2, 'Queen' in all known cases\n"); printf(" -o FILE\tOutput file\n"); printf(" -ids\t\tShow a list of known firmware identifiers.\n"); exit(1); } void show_fwids(void) { printf("List of known firmware identifiers:\n"); printf("Manufacturer\t\tProduct\t\tIdentifier\n"); printf("=====================================================\n"); printf("Conceptronic\t\tCHD2WLANU\tLLM_RUS001\n"); printf("Pearl\t\t\tPE6643\t\tQueen\n"); printf("Micronica\t\tMGB100\t\tQueen\n"); printf("LevelOne\t\tWAP-0007\tDDC_RUS001\n"); printf("SMC\t\t\tWAPS-G\t\tSMC_RUS001\n"); printf("OvisLink (AirLive)\tWMU-6\t\tOVS_RUS001\n"); printf("SafeCom SWSAPUR-5\tFMW\t\tSafeco_RPS001\n"); exit(1); } int main(int argc, char *argv[]) { unsigned char hdr[HDRSIZE]; unsigned char *data; FILE *of; char *outfile = NULL; char *type; struct hdrinfo *info; long size; int last = 0; int n; for (n = 1; n < argc; n++) { if (strcmp(argv[n], "-1") == 0) ascii1 = argv[n+1]; if (strcmp(argv[n], "-2") == 0) ascii2 = argv[n+1]; if (strcmp(argv[n], "-o") == 0) outfile = argv[n+1]; if (strcmp(argv[n], "-ids") == 0) show_fwids(); } if (ascii1 == NULL || ascii2 == NULL || outfile == NULL) showhelp(); of = fopen(outfile, "w"); if (of == NULL) oferror(of); for (n = 1; n < argc; n++) { if (strncmp(argv[n], "-", 1) != 0) { type = argv[n++]; if (n >= argc) showhelp(); last = ((n + 1) >= argc); /* dirty, options first! */ info = find_hdrinfo(type); if (info == NULL) showhelp(); data = read_file(argv[n], &size); if (data == NULL) showhelp(); makehdr(hdr, info, data, size, last); /* showhdr(hdr); */ if (fwrite(hdr, HDRSIZE, 1, of) != 1) oferror(of); if (fwrite(data, size, 1, of) != 1) oferror(of); free(data); } else n++; } if (fclose(of) != 0) oferror(NULL); return 0; } ================================================ FILE: src/firmware-tools/md5.c ================================================ /* *********************************************************************** ** md5.c -- the source code for MD5 routines ** ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** *********************************************************************** */ /* *********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** *********************************************************************** */ #include #include "md5.h" /* *********************************************************************** ** Message-digest routines: ** ** To form the message digest for a message M ** ** (1) Initialize a context buffer mdContext using MD5_Init ** ** (2) Call MD5_Update on mdContext and M ** ** (3) Call MD5_Final on mdContext ** ** The message digest is now in mdContext->digest[0...15] ** *********************************************************************** */ /* forward declaration */ static void Transform (); static unsigned char PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* F, G, H and I are basic MD5 functions */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ /* Rotation is separate from addition to prevent recomputation */ #define FF(a, b, c, d, x, s, ac) \ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) \ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) \ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) \ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #ifdef __STDC__ #define UL(x) x##U #else #define UL(x) x #endif /* The routine MD5_Init initializes the message-digest context mdContext. All fields are set to zero. */ void MD5_Init (mdContext) MD5_CTX *mdContext; { mdContext->i[0] = mdContext->i[1] = (UINT4)0; /* Load magic initialization constants. */ mdContext->buf[0] = (UINT4)0x67452301; mdContext->buf[1] = (UINT4)0xefcdab89; mdContext->buf[2] = (UINT4)0x98badcfe; mdContext->buf[3] = (UINT4)0x10325476; } /* The routine MD5Update updates the message-digest context to account for the presence of each of the characters inBuf[0..inLen-1] in the message whose digest is being computed. */ void MD5_Update (mdContext, inBuf, inLen) MD5_CTX *mdContext; unsigned char *inBuf; unsigned int inLen; { UINT4 in[16]; int mdi; unsigned int i, ii; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* update number of bits */ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++; mdContext->i[0] += ((UINT4)inLen << 3); mdContext->i[1] += ((UINT4)inLen >> 29); while (inLen--) { /* add new character to buffer, increment mdi */ mdContext->in[mdi++] = *inBuf++; /* transform if necessary */ if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); mdi = 0; } } } /* The routine MD5Final terminates the message-digest computation and ends with the desired message digest in mdContext->digest[0...15]. */ void MD5_Final (hash, mdContext) unsigned char hash[]; MD5_CTX *mdContext; { UINT4 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; /* save number of bits */ in[14] = mdContext->i[0]; in[15] = mdContext->i[1]; /* compute number of bytes mod 64 */ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); /* pad out to 56 mod 64 */ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); MD5_Update (mdContext, PADDING, padLen); /* append length in bits and transform */ for (i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | (((UINT4)mdContext->in[ii+2]) << 16) | (((UINT4)mdContext->in[ii+1]) << 8) | ((UINT4)mdContext->in[ii]); Transform (mdContext->buf, in); /* store buffer in digest */ for (i = 0, ii = 0; i < 4; i++, ii += 4) { mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); } memcpy(hash, mdContext->digest, 16); } /* Basic MD5 step. Transforms buf based on in. */ static void Transform (buf, in) UINT4 *buf; UINT4 *in; { UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ /* Round 2 */ #define S21 5 #define S22 9 #define S23 14 #define S24 20 GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ /* Round 3 */ #define S31 4 #define S32 11 #define S33 16 #define S34 23 HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ /* Round 4 */ #define S41 6 #define S42 10 #define S43 15 #define S44 21 II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* *********************************************************************** ** End of md5.c ** ******************************** (cut) ******************************** */ ================================================ FILE: src/firmware-tools/md5.h ================================================ /* *********************************************************************** ** md5.h -- header file for implementation of MD5 ** ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** ** Revised (for MD5): RLR 4/27/91 ** ** -- G modified to have y&~z instead of y&z ** ** -- FF, GG, HH modified to add in last register done ** ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** ** -- distinct additive constant for each step ** ** -- round 4 added, working mod 7 ** *********************************************************************** */ /* *********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** *********************************************************************** */ #ifndef __MD5_INCLUDE__ /* typedef a 32-bit type */ #ifdef _LP64 typedef unsigned int UINT4; typedef int INT4; #else typedef unsigned long UINT4; typedef long INT4; #endif #define _UINT4_T /* Data structure for MD5 (Message-Digest) computation */ typedef struct { UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ UINT4 buf[4]; /* scratch buffer */ unsigned char in[64]; /* input buffer */ unsigned char digest[16]; /* actual digest after MD5Final call */ } MD5_CTX; void MD5_Init (); void MD5_Update (); void MD5_Final (); #define __MD5_INCLUDE__ #endif /* __MD5_INCLUDE__ */ ================================================ FILE: src/firmware-tools/mkbrncmdline.c ================================================ /* * mkbrncmdline.c - partially based on OpenWrt's wndr3700.c * * Copyright (C) 2011 Tobias Diedrich * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include static void usage(const char *) __attribute__ (( __noreturn__ )); static void usage(const char *mess) { fprintf(stderr, "Error: %s\n", mess); fprintf(stderr, "Usage: mkbrncmdline -i input_file -o output_file [-a loadaddress] arg1 [argx ...]\n"); fprintf(stderr, "\n"); exit(1); } static char *input_file = NULL; static char *output_file = NULL; static unsigned loadaddr = 0x80002000; static void parseopts(int *argc, char ***argv) { char *endptr; int res; while ((res = getopt(*argc, *argv, "a:i:o:")) != -1) { switch (res) { default: usage("Unknown option"); break; case 'a': loadaddr = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != 0) usage("loadaddress must be a decimal or hexadecimal 32-bit value"); break; case 'i': input_file = optarg; break; case 'o': output_file = optarg; break; } } *argc -= optind; *argv += optind; } static void emitload(int outfd, int reg, unsigned value) { char buf[8] = { 0x3c, 0x04 + reg, value >> 24, value >> 16, 0x34, 0x84 + reg + (reg << 5), value >> 8, value, }; if (write(outfd, buf, sizeof(buf)) != sizeof(buf)) { fprintf(stderr, "write: %s\n", strerror(errno)); exit(1); } } int main(int argc, char **argv) { int outfd; int i; int fd; size_t len, skip, buf_len; unsigned cmdline_addr; unsigned s_ofs; char *buf; parseopts(&argc, &argv); if (argc < 1) usage("must specify at least one kernel cmdline argument"); if (input_file == NULL || output_file == NULL) usage("must specify input and output file"); if ((outfd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { fprintf(stderr, "Error opening '%s' for writing: %s\n", output_file, strerror(errno)); exit(1); } // mmap input_file if ((fd = open(input_file, O_RDONLY)) < 0 || (len = lseek(fd, 0, SEEK_END)) < 0 || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) || close(fd) < 0) { fprintf(stderr, "Error mapping file '%s': %s\n", input_file, strerror(errno)); exit(1); } cmdline_addr = loadaddr + len; // Kernel args are passed in registers a0,a1,a2 and a3 emitload(outfd, 0, 0); /* a0 = 0 */ emitload(outfd, 1, 0); /* a1 = 0 */ emitload(outfd, 2, cmdline_addr); /* a2 = &cmdline */ emitload(outfd, 3, 0); /* a3 = 0 */ skip = lseek(outfd, 0, SEEK_END); // write the kernel if (write(outfd, input_file + skip, len - skip) != len -skip) { fprintf(stderr, "write: %s\n", strerror(errno)); exit(1); } // write cmdline structure buf_len = (argc + 1) * 4; for (i=0; i> 24; buf[i * 4 + 1] = s_ptr >> 16; buf[i * 4 + 2] = s_ptr >> 8; buf[i * 4 + 3] = s_ptr >> 0; memcpy(&buf[s_ofs], argv[i], strlen(argv[i])); s_ofs += strlen(argv[i]) + 1; } if (write(outfd, buf, buf_len) != buf_len) { fprintf(stderr, "write: %s\n", strerror(errno)); exit(1); } munmap(input_file, len); close(outfd); free(buf); return 0; } ================================================ FILE: src/firmware-tools/mkbrnimg.c ================================================ /* * mkbrnimg.c - partially based on OpenWrt's wndr3700.c * * Copyright (C) 2011 Tobias Diedrich * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #define BPB 8 /* bits/byte */ static uint32_t crc32[1<> 1)) : (crc >> 1); crc32[n] = crc; } } static uint32_t crc32buf(unsigned char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for (; len; len--, buf++) crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB); return ~crc; } static void usage(const char *) __attribute__ (( __noreturn__ )); static void usage(const char *mess) { fprintf(stderr, "Error: %s\n", mess); fprintf(stderr, "Usage: mkbrnimg [-o output_file] [-m magic] [-s signature] kernel_file [additional files]\n"); fprintf(stderr, "\n"); exit(1); } static char *output_file = "default-brnImage"; static uint32_t magic = 0x12345678; static char *signature = "BRNDTW502"; static void parseopts(int *argc, char ***argv) { char *endptr; int res; while ((res = getopt(*argc, *argv, "o:m:s:")) != -1) { switch (res) { default: usage("Unknown option"); break; case 'o': output_file = optarg; break; case 'm': magic = strtoul(optarg, &endptr, 0); if (endptr == optarg || *endptr != 0) usage("magic must be a decimal or hexadecimal 32-bit value"); break; case 's': signature = optarg; break; } } *argc -= optind; *argv += optind; } static void appendfile(int outfd, char *path, int kernel) { int fd; size_t len, padded_len; char *input_file; uint32_t crc; char padding[0x400]; char footer[12]; memset(padding, 0xff, sizeof(padding)); // mmap input_file if ((fd = open(path, O_RDONLY)) < 0 || (len = lseek(fd, 0, SEEK_END)) < 0 || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) || close(fd) < 0) { fprintf(stderr, "Error mapping file '%s': %s\n", path, strerror(errno)); exit(1); } // kernel should be lzma compressed image, not uImage if (kernel && (input_file[0] != (char)0x5d || input_file[1] != (char)0x00 || input_file[2] != (char)0x00 || input_file[3] != (char)0x80)) { fprintf(stderr, "lzma signature not found on kernel image.\n"); exit(1); } init_crc32(); crc = crc32buf(input_file, len); fprintf(stderr, "crc32 for '%s' is %08x.\n", path, crc); // write the file write(outfd, input_file, len); // write padding padded_len = ((len + sizeof(footer) + sizeof(padding) - 1) & ~(sizeof(padding) - 1)) - sizeof(footer); fprintf(stderr, "len=%08x padded_len=%08x\n", len, padded_len); write(outfd, padding, padded_len - len); // write footer footer[0] = (len >> 0) & 0xff; footer[1] = (len >> 8) & 0xff; footer[2] = (len >> 16) & 0xff; footer[3] = (len >> 24) & 0xff; footer[4] = (magic >> 0) & 0xff; footer[5] = (magic >> 8) & 0xff; footer[6] = (magic >> 16) & 0xff; footer[7] = (magic >> 24) & 0xff; footer[8] = (crc >> 0) & 0xff; footer[9] = (crc >> 8) & 0xff; footer[10] = (crc >> 16) & 0xff; footer[11] = (crc >> 24) & 0xff; write(outfd, footer, sizeof(footer)); munmap(input_file, len); } int main(int argc, char **argv) { int outfd; int i; parseopts(&argc, &argv); if (argc < 1) usage("wrong number of arguments"); if ((outfd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { fprintf(stderr, "Error opening '%s' for writing: %s\n", output_file, strerror(errno)); exit(1); } for (i=0; i * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include #include #define MAX_MODEL_LEN 20 #define MAX_SIGNATURE_LEN 30 #define MAX_REGION_LEN 4 #define MAX_VERSION_LEN 12 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) struct file_info { char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ uint32_t write_size; }; struct img_header { uint32_t checksum; uint32_t image_size; uint32_t kernel_size; char model[MAX_MODEL_LEN]; char signature[MAX_SIGNATURE_LEN]; char region[MAX_REGION_LEN]; char version[MAX_VERSION_LEN]; unsigned char header_len; unsigned char is_tgz; unsigned char pad[4]; } __attribute__ ((packed)); /* * Globals */ static char *ofname; static char *progname; static char *model; static char *signature; static char *region = "DEF"; static char *version; static struct file_info kernel_info; static struct file_info rootfs_info; static uint32_t kernel_size; static uint32_t image_size; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define DBG(fmt, ...) do { \ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) static void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -k read kernel image from the file \n" " -M set model to \n" " -o write output to the file \n" " -r read rootfs image from the file \n" " -S set image signature to \n" " -R set image region to \n" " -V set image version to \n" " -I set image size to \n" " -K set kernel size to \n" " -h show this screen\n" ); exit(status); } int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } static int get_file_stat(struct file_info *fdata) { struct stat st; int res; if (fdata->file_name == NULL) return 0; res = stat(fdata->file_name, &st); if (res){ ERRS("stat failed on %s", fdata->file_name); return res; } fdata->file_size = st.st_size; fdata->write_size = fdata->file_size; return 0; } static int read_to_buf(struct file_info *fdata, char *buf) { FILE *f; int ret = EXIT_FAILURE; f = fopen(fdata->file_name, "r"); if (f == NULL) { ERRS("could not open \"%s\" for reading", fdata->file_name); goto out; } errno = 0; fread(buf, fdata->file_size, 1, f); if (errno != 0) { ERRS("unable to read from file \"%s\"", fdata->file_name); goto out_close; } ret = EXIT_SUCCESS; out_close: fclose(f); out: return ret; } static int check_options(void) { int ret; #define CHKSTR(_name, _msg) \ do { \ if (_name == NULL) { \ ERR("no %s specified", _msg); \ return -1; \ } \ } while (0) #define CHKSTRLEN(_name, _msg) \ do { \ int field_len; \ CHKSTR(_name, _msg); \ field_len = FIELD_SIZEOF(struct img_header, _name) - 1; \ if (strlen(_name) > field_len) { \ ERR("%s is too long, max length is %d", \ _msg, field_len); \ return -1; \ } \ } while (0) CHKSTRLEN(model, "model"); CHKSTRLEN(signature, "signature"); CHKSTRLEN(region, "region"); CHKSTRLEN(version, "version"); CHKSTR(ofname, "output file"); CHKSTR(kernel_info.file_name, "kernel image"); CHKSTR(rootfs_info.file_name, "rootfs image"); ret = get_file_stat(&kernel_info); if (ret) return ret; ret = get_file_stat(&rootfs_info); if (ret) return ret; if (kernel_size) { /* override kernel size */ kernel_info.write_size = kernel_size; } if (image_size) { if (image_size < kernel_info.write_size) kernel_info.write_size = image_size; /* override rootfs size */ rootfs_info.write_size = image_size - kernel_info.write_size; } if (kernel_info.file_size > kernel_info.write_size) { ERR("kernel image is too big"); return -1; } if (rootfs_info.file_size > rootfs_info.write_size) { ERR("rootfs image is too big"); return -1; } return 0; } static int write_fw(char *data, int len) { FILE *f; int ret = EXIT_FAILURE; f = fopen(ofname, "w"); if (f == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } errno = 0; fwrite(data, len, 1, f); if (errno) { ERRS("unable to write output file"); goto out_flush; } DBG("firmware file \"%s\" completed", ofname); ret = EXIT_SUCCESS; out_flush: fflush(f); fclose(f); if (ret != EXIT_SUCCESS) { unlink(ofname); } out: return ret; } static uint32_t get_csum(unsigned char *p, uint32_t len) { uint32_t csum = 0; while (len--) csum += *p++; return csum; } static int build_fw(void) { int buflen; char *buf; char *p; uint32_t csum; struct img_header *hdr; int ret = EXIT_FAILURE; buflen = sizeof(struct img_header) + kernel_info.write_size + rootfs_info.write_size; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } memset(buf, 0, buflen); p = buf + sizeof(struct img_header); /* read kernel data */ ret = read_to_buf(&kernel_info, p); if (ret) goto out_free_buf; p += kernel_info.write_size; /* read rootfs data */ ret = read_to_buf(&rootfs_info, p); if (ret) goto out_free_buf; csum = get_csum((unsigned char *)(buf + sizeof(struct img_header)), buflen - sizeof(struct img_header)); /* fill firmware header */ hdr = (struct img_header *) buf; hdr->checksum = htonl(csum); hdr->image_size = htonl(buflen - sizeof(struct img_header)); hdr->kernel_size = htonl(kernel_info.write_size); hdr->header_len = sizeof(struct img_header); strncpy(hdr->model, model, sizeof(hdr->model)); strncpy(hdr->signature, signature, sizeof(hdr->signature)); strncpy(hdr->version, version, sizeof(hdr->version)); strncpy(hdr->region, region, sizeof(hdr->region)); ret = write_fw(buf, buflen); if (ret) goto out_free_buf; ret = EXIT_SUCCESS; out_free_buf: free(buf); out: return ret; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; progname = basename(argv[0]); while (1) { int c; c = getopt(argc, argv, "M:S:V:R:k:K:I:r:o:h"); if (c == -1) break; switch (c) { case 'M': model = optarg; break; case 'S': signature = optarg; break; case 'V': version = optarg; break; case 'R': region = optarg; break; case 'k': kernel_info.file_name = optarg; break; case 'K': if (str2u32(optarg, &kernel_size)) { ERR("%s is invalid '%s'", "kernel size", optarg); goto out; } break; case 'I': if (str2u32(optarg, &image_size)) { ERR("%s is invalid '%s'", "image size", optarg); goto out; } break; case 'r': rootfs_info.file_name = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } ret = check_options(); if (ret) goto out; ret = build_fw(); out: return ret; } ================================================ FILE: src/firmware-tools/mkcasfw.c ================================================ /* * * Copyright (C) 2007 OpenWrt.org * Copyright (C) 2007 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include /* for __BYTE_ORDER */ #if defined(__CYGWIN__) # include #endif #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) # define LE16_TO_HOST(x) (x) # define LE32_TO_HOST(x) (x) #else # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) # define LE16_TO_HOST(x) bswap_16(x) # define LE32_TO_HOST(x) bswap_32(x) #endif #define MAX_NUM_BLOCKS 2 #define MAX_ARG_COUNT 32 #define MAX_ARG_LEN 1024 #define FILE_BUF_LEN (16*1024) #define DEFAULT_PADC 0xFF #define DEFAULT_BLOCK_ALIGN 0x10000U #define CSUM_TYPE_NONE 0 #define CSUM_TYPE_8 1 #define CSUM_TYPE_16 2 #define CSUM_TYPE_32 3 struct csum_state{ int size; uint32_t val; uint32_t tmp; int odd; }; struct image_desc { int need_file; char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ uint32_t csum; uint32_t out_size; uint8_t padc; }; struct fwhdr_nfs { uint32_t type; uint32_t kernel_offs; uint32_t kernel_size; uint32_t fs_offs; uint32_t fs_size; uint32_t kernel_csum; uint32_t fs_csum; uint32_t id; } __attribute__ ((packed)); struct fwhdr_cas { uint32_t type; uint32_t kernel_offs; uint32_t kernel_size; uint32_t id; uint32_t kernel_csum; uint32_t magic1; uint32_t magic2; uint32_t magic3; } __attribute__ ((packed)); union file_hdr { struct fwhdr_cas cas; struct fwhdr_nfs nfs; }; struct board_info { char *model; char *name; int header_type; uint32_t id; uint32_t max_kernel_size; uint32_t max_fs_size; }; #define HEADER_TYPE_NFS 0 #define HEADER_TYPE_CAS 1 #define KERNEL_SIZE_CAS (61*64*1024) #define KERNEL_SIZE_NFS (52*64*1024) #define FS_SIZE_NFS (9*64*1024) #define CAS_MAGIC1 0x5241AA55 #define CAS_MAGIC2 0x524F4741 #define CAS_MAGIC3 0xD3F22D4E /* Cellvision/SparkLAN products */ #define MODEL_CAS_630 0x01000000 #define MODEL_CAS_630W 0x01000000 #define MODEL_CAS_670 0x01000000 #define MODEL_CAS_670W 0x01000000 #define MODEL_NFS_101U 0x01000000 #define MODEL_NFS_101WU 0x01000003 #define MODEL_NFS_202U 0x01000001 #define MODEL_NFS_202WU 0x01000002 /* Corega products */ #define MODEL_CG_NSADP 0x01000020 /* NFS-101U */ #define MODEL_CG_NSADPCR 0x01000021 /* NFS-202U */ /* D-Link products */ #define MODEL_DCS_950 0x01010102 /* CAS-630 */ #define MODEL_DCS_950G 0x01020102 /* CAS-630W */ #define MODEL_DNS_120 0x01000030 /* NFS-101U */ #define MODEL_DNS_G120 0x01000032 /* NFS-101WU */ /* Digitus products */ #define MODEL_DN_16021 MODEL_CAS_630 #define MODEL_DN_16022 MODEL_CAS_630W #define MODEL_DN_16030 MODEL_CAS_670 #define MODEL_DN_16031 MODEL_CAS_670W #define MODEL_DN_7013 MODEL_NFS_101U /* Lobos products */ #define MODEL_LB_SS01TXU 0x00000000 /* Neu-Fusion products */ /* Ovislink products */ #define MODEL_MU_5000FS 0x01000040 /* NFS-101U */ #define MODEL_WL_5420CAM 0x020B0101 /* CAS-630W? */ #define MODEL_WL_5460CAM 0x020B0001 /* CAS-670W */ /* Repotec products */ /* Sitecom products */ #define MODEL_LN_350 /* unknown */ #define MODEL_LN_403 0x01020402 #define MODEL_WL_401 0x01010402 /* Surecom products */ #define MODEL_EP_4001_MM 0x01030A02 /* CAS-630 */ #define MODEL_EP_4002_MM 0x01020A02 /* CAS-630W */ #define MODEL_EP_4011_MM 0x01010A02 /* CAS-670 */ #define MODEL_EP_4012_MM 0x01000A02 /* CAS-670W */ #define MODEL_EP_9812_U /* unknown */ /* Trendnet products */ #define MODEL_TN_U100 0x01000081 /* NFS-101U */ #define MODEL_TN_U200 0x01000082 /* NFS-202U */ /* * Globals */ char *progname; char *ofname; int verblevel; int keep_invalid_images; int invalid_causes_error = 1; union file_hdr header; struct image_desc kernel_image; struct image_desc fs_image; struct board_info *board = NULL; #define BOARD(m, n, i, ks, fs, h) { \ .model = (m), \ .name = (n), \ .id = (i), \ .max_kernel_size = (ks), \ .max_fs_size = (fs), \ .header_type = (h) \ } #define BOARD_CAS(m,n,i) \ BOARD(m, n, i, KERNEL_SIZE_CAS, 0, HEADER_TYPE_CAS) #define BOARD_NFS(m,n,i) \ BOARD(m, n, i, KERNEL_SIZE_NFS, FS_SIZE_NFS, HEADER_TYPE_NFS) static struct board_info boards[] = { /* Cellvision/Sparklan products */ BOARD_CAS("CAS-630", "Cellvision CAS-630", MODEL_CAS_630), BOARD_CAS("CAS-630W", "Cellvision CAS-630W", MODEL_CAS_630W), BOARD_CAS("CAS-670", "Cellvision CAS-670", MODEL_CAS_670), BOARD_CAS("CAS-670W", "Cellvision CAS-670W", MODEL_CAS_670W), BOARD_NFS("NFS-101U", "Cellvision NFS-101U", MODEL_NFS_101U), BOARD_NFS("NFS-101WU", "Cellvision NFS-101WU", MODEL_NFS_101WU), BOARD_NFS("NFS-202U", "Cellvision NFS-202U", MODEL_NFS_202U), BOARD_NFS("NFS-202WU", "Cellvision NFS-202WU", MODEL_NFS_202WU), /* Corega products */ BOARD_NFS("CG-NSADP", "Corega CG-NSADP", MODEL_CG_NSADP), BOARD_NFS("CG-NSADPCR", "Corega CG-NSADPCR", MODEL_CG_NSADPCR), /* D-Link products */ BOARD_CAS("DCS-950", "D-Link DCS-950", MODEL_DCS_950), BOARD_CAS("DCS-950G", "D-Link DCS-950G", MODEL_DCS_950G), BOARD_NFS("DNS-120", "D-Link DNS-120", MODEL_DNS_120), BOARD_NFS("DNS-G120", "D-Link DNS-G120", MODEL_DNS_G120), /* Digitus products */ BOARD_NFS("DN-7013", "Digitus DN-7013", MODEL_DN_7013), /* Lobos products */ BOARD_NFS("LB-SS01TXU", "Lobos LB-SS01TXU", MODEL_LB_SS01TXU), /* Ovislink products */ BOARD_NFS("MU-5000FS", "Ovislink MU-5000FS", MODEL_MU_5000FS), BOARD_CAS("WL-5420CAM", "Ovislink WL-5420 CAM", MODEL_WL_5420CAM), BOARD_CAS("WL-5460CAM", "Ovislink WL-5460 CAM", MODEL_WL_5460CAM), /* Sitecom products */ BOARD_CAS("LN-403", "Sitecom LN-403", MODEL_LN_403), BOARD_CAS("WL-401", "Sitecom WL-401", MODEL_WL_401), /* Surecom products */ BOARD_CAS("EP-4001-MM", "Surecom EP-4001-MM", MODEL_EP_4001_MM), BOARD_CAS("EP-4002-MM", "Surecom EP-4002-MM", MODEL_EP_4002_MM), BOARD_CAS("EP-4011-MM", "Surecom EP-4011-MM", MODEL_EP_4011_MM), BOARD_CAS("EP-4012-MM", "Surecom EP-4012-MM", MODEL_EP_4012_MM), /* TrendNET products */ BOARD_NFS("TN-U100", "TrendNET TN-U100", MODEL_TN_U100), BOARD_NFS("TN-U200", "TrendNET TN-U200", MODEL_TN_U200), {.model = NULL} }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define WARN(fmt, ...) do { \ fprintf(stderr, "[%s] *** warning: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define DBG(lev, fmt, ...) do { \ if (verblevel < lev) \ break;\ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) #define ERR_FATAL -1 #define ERR_INVALID_IMAGE -2 void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...] \n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with .\n" " valid values:\n" ); for (board = boards; board->model != NULL; board++){ fprintf(stream, " %-12s: %s\n", board->model, board->name); }; fprintf(stream, " -d don't throw error on invalid images\n" " -k keep invalid images\n" " -K add kernel to the image\n" " -C add custom filesystem to the image\n" " -h show this screen\n" "Parameters:\n" " write output to the file \n" ); exit(status); } static inline uint32_t align(uint32_t base, uint32_t alignment) { uint32_t ret; if (alignment) { ret = (base + alignment - 1); ret &= ~(alignment-1); } else { ret = base; } return ret; } /* * argument parsing */ int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } int str2u16(char *arg, uint16_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) { return -1; } *val = t & 0xFFFF; return 0; } int str2u8(char *arg, uint8_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) { return -1; } *val = t & 0xFF; return 0; } int parse_arg(char *arg, char *buf, char *argv[]) { int res = 0; size_t argl; char *tok; char **ap = &buf; int i; memset(argv, 0, MAX_ARG_COUNT * sizeof(void *)); if ((arg == NULL)) { /* no arguments */ return 0; } argl = strlen(arg); if (argl == 0) { /* no arguments */ return 0; } if (argl >= MAX_ARG_LEN) { /* argument is too long */ argl = MAX_ARG_LEN-1; } memcpy(buf, arg, argl); buf[argl] = '\0'; for (i = 0; i < MAX_ARG_COUNT; i++) { tok = strsep(ap, ":"); if (tok == NULL) { break; } #if 0 else if (tok[0] == '\0') { break; } #endif argv[i] = tok; res++; } return res; } int required_arg(char c, char *arg) { if (arg == NULL || *arg != '-') return 0; ERR("option -%c requires an argument\n", c); return ERR_FATAL; } int is_empty_arg(char *arg) { int ret = 1; if (arg != NULL) { if (*arg) ret = 0; }; return ret; } void csum8_update(uint8_t *p, uint32_t len, struct csum_state *css) { for ( ; len > 0; len --) { css->val += *p++; } } uint16_t csum8_get(struct csum_state *css) { uint8_t t; t = css->val; return ~t + 1; } void csum16_update(uint8_t *p, uint32_t len, struct csum_state *css) { uint16_t t; if (css->odd) { t = css->tmp + (p[0]<<8); css->val += LE16_TO_HOST(t); css->odd = 0; len--; p++; } for ( ; len > 1; len -= 2, p +=2 ) { t = p[0] + (p[1] << 8); css->val += LE16_TO_HOST(t); } if (len == 1) { css->tmp = p[0]; css->odd = 1; } } uint16_t csum16_get(struct csum_state *css) { char pad = 0; csum16_update(&pad, 1, css); return ~css->val + 1; } void csum32_update(uint8_t *p, uint32_t len, struct csum_state *css) { uint32_t t; for ( ; len > 3; len -= 4, p += 4 ) { t = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); css->val ^= t; } } uint32_t csum32_get(struct csum_state *css) { return css->val; } void csum_init(struct csum_state *css, int size) { css->val = 0; css->tmp = 0; css->odd = 0; css->size = size; } void csum_update(uint8_t *p, uint32_t len, struct csum_state *css) { switch (css->size) { case CSUM_TYPE_8: csum8_update(p,len,css); break; case CSUM_TYPE_16: csum16_update(p,len,css); break; case CSUM_TYPE_32: csum32_update(p,len,css); break; } } uint32_t csum_get(struct csum_state *css) { uint32_t ret; switch (css->size) { case CSUM_TYPE_8: ret = csum8_get(css); break; case CSUM_TYPE_16: ret = csum16_get(css); break; case CSUM_TYPE_32: ret = csum32_get(css); } return ret; } /* * routines to write data to the output file */ int write_out_data(FILE *outfile, uint8_t *data, size_t len, struct csum_state *css) { errno = 0; fwrite(data, len, 1, outfile); if (errno) { ERRS("unable to write output file"); return ERR_FATAL; } if (css) { csum_update(data, len, css); } return 0; } int write_out_padding(FILE *outfile, size_t len, uint8_t padc, struct csum_state *css) { uint8_t buf[512]; size_t buflen = sizeof(buf); int err; memset(buf, padc, buflen); while (len > 0) { if (len < buflen) buflen = len; err = write_out_data(outfile, buf, buflen, css); if (err) return err; len -= buflen; } return 0; } int image_stat_file(struct image_desc *desc) { struct stat st; int err; if (desc->file_name == NULL) return 0; err = stat(desc->file_name, &st); if (err){ ERRS("stat failed on %s", desc->file_name); return ERR_FATAL; } if (st.st_size > desc->out_size) { WARN("file %s is too big, will be truncated to %d bytes\n", desc->file_name, desc->out_size); desc->file_size = desc->out_size; return ERR_INVALID_IMAGE; } desc->file_size = st.st_size; desc->out_size = align(desc->file_size,1); return 0; } int image_writeout_file(FILE *outfile, struct image_desc *desc, struct csum_state *css) { char buf[FILE_BUF_LEN]; size_t buflen = sizeof(buf); FILE *f; size_t len; int res; if (desc->file_name == NULL) return 0; if (desc->file_size == 0) return 0; errno = 0; f = fopen(desc->file_name,"r"); if (errno) { ERRS("unable to open file: %s", desc->file_name); return ERR_FATAL; } len = desc->file_size; while (len > 0) { if (len < buflen) buflen = len; /* read data from source file */ errno = 0; fread(buf, buflen, 1, f); if (errno != 0) { ERRS("unable to read from file: %s", desc->file_name); res = ERR_FATAL; break; } res = write_out_data(outfile, buf, buflen, css); if (res) break; len -= buflen; } fclose(f); return res; } int image_writeout(FILE *outfile, struct image_desc *desc) { int res; struct csum_state css; size_t padlen; res = 0; if (!desc->file_size) return 0; DBG(2, "writing image, file=%s, file_size=%d\n", desc->file_name, desc->file_size); csum_init(&css, CSUM_TYPE_32); res = image_writeout_file(outfile, desc, &css); if (res) return res; /* write padding data if neccesary */ padlen = desc->out_size - desc->file_size; DBG(1,"padding desc, length=%d", padlen); res = write_out_padding(outfile, padlen, desc->padc, &css); desc->csum = csum_get(&css); return res; } int write_out_header(FILE *outfile) { union file_hdr tmp; int res; errno = 0; if (fseek(outfile, 0, SEEK_SET) != 0) { ERRS("fseek failed on output file"); return ERR_FATAL; } switch (board->header_type) { case HEADER_TYPE_CAS: tmp.cas.type = HOST_TO_LE32(header.cas.type); tmp.cas.id = HOST_TO_LE32(header.cas.id); tmp.cas.kernel_offs = HOST_TO_LE32(sizeof(tmp.cas)); tmp.cas.kernel_size = HOST_TO_LE32(kernel_image.out_size); tmp.cas.kernel_csum = HOST_TO_LE32(kernel_image.csum); tmp.cas.magic1 = HOST_TO_LE32(CAS_MAGIC1); tmp.cas.magic2 = HOST_TO_LE32(CAS_MAGIC2); tmp.cas.magic3 = HOST_TO_LE32(CAS_MAGIC3); res = write_out_data(outfile, (uint8_t *)&tmp.cas, sizeof(tmp.cas), NULL); break; case HEADER_TYPE_NFS: tmp.nfs.type = HOST_TO_LE32(header.nfs.type); tmp.nfs.id = HOST_TO_LE32(header.nfs.id); tmp.nfs.kernel_offs = HOST_TO_LE32(sizeof(tmp.nfs)); tmp.nfs.kernel_size = HOST_TO_LE32(kernel_image.out_size); tmp.nfs.kernel_csum = HOST_TO_LE32(kernel_image.csum); tmp.nfs.fs_offs = HOST_TO_LE32(sizeof(tmp.nfs) + kernel_image.out_size); tmp.nfs.fs_size = HOST_TO_LE32(fs_image.out_size); tmp.nfs.fs_csum = HOST_TO_LE32(fs_image.csum); res = write_out_data(outfile, (uint8_t *)&tmp.nfs, sizeof(tmp.nfs), NULL); break; } return res; } int write_out_images(FILE *outfile) { struct image_desc *desc; int i, res; res = image_writeout(outfile, &kernel_image); if (res) return res; res = image_writeout(outfile, &fs_image); if (res) return res; return 0; } struct board_info * find_board(char *model) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->model != NULL; board++){ if (strcasecmp(model, board->model) == 0) { ret = board; break; } }; return ret; } int parse_opt_board(char ch, char *arg) { DBG(1,"parsing board option: -%c %s", ch, arg); if (board != NULL) { ERR("only one board option allowed"); return ERR_FATAL; } if (required_arg(ch, arg)) return ERR_FATAL; board = find_board(arg); if (board == NULL){ ERR("invalid/unknown board specified: %s", arg); return ERR_FATAL; } switch (board->header_type) { case HEADER_TYPE_CAS: header.cas.type = HEADER_TYPE_CAS; header.cas.id = board->id; break; case HEADER_TYPE_NFS: header.nfs.type = HEADER_TYPE_NFS; header.nfs.id = board->id; break; default: ERR("internal error, unknown header type\n"); return ERR_FATAL; } return 0; } int parse_opt_image(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; struct image_desc *desc = NULL; int i; switch (ch) { case 'K': if (kernel_image.file_name) { WARN("only one kernel option allowed"); break; } desc = &kernel_image; break; case 'F': if (fs_image.file_name) { WARN("only one fs option allowed"); break; } desc = &fs_image; break; } if (!desc) return ERR_FATAL; argc = parse_arg(arg, buf, argv); i = 0; p = argv[i++]; if (!is_empty_arg(p)) { desc->file_name = strdup(p); if (desc->file_name == NULL) { ERR("not enough memory"); return ERR_FATAL; } } else { ERR("no file specified for option %c", ch); return ERR_FATAL; } return 0; } int process_images(void) { struct image_desc *desc; uint32_t offs = 0; int i; int res; kernel_image.out_size = board->max_kernel_size; kernel_image.padc = DEFAULT_PADC; res = image_stat_file(&kernel_image); if (res) return res; if (!fs_image.file_name) return 0; fs_image.out_size = board->max_fs_size; fs_image.padc = DEFAULT_PADC; res = image_stat_file(&fs_image); if (res) return res; return 0; } int main(int argc, char *argv[]) { int optinvalid = 0; /* flag for invalid option */ int c; int res = ERR_FATAL; FILE *outfile; progname=basename(argv[0]); opterr = 0; /* could not print standard getopt error messages */ while ( 1 ) { optinvalid = 0; c = getopt(argc, argv, "B:C:dhK:r:vw:x:"); if (c == -1) break; switch (c) { case 'B': optinvalid = parse_opt_board(c,optarg); break; case 'd': invalid_causes_error = 0; break; case 'C': case 'K': optinvalid = parse_opt_image(c,optarg); break; case 'k': keep_invalid_images = 1; break; case 'v': verblevel++; break; case 'h': usage(EXIT_SUCCESS); break; default: optinvalid = 1; break; } if (optinvalid != 0 ){ ERR("invalid option: -%c", optopt); goto out; } } if (board == NULL) { ERR("no board specified"); goto out; } if (optind == argc) { ERR("no output file specified"); goto out; } ofname = argv[optind++]; if (optind < argc) { ERR("invalid option: %s", argv[optind]); goto out; } res = process_images(); if (res == ERR_FATAL) goto out; if (res == ERR_INVALID_IMAGE) { if (invalid_causes_error) res = ERR_FATAL; if (keep_invalid_images == 0) { WARN("generation of invalid images disabled", ofname); goto out; } WARN("generating invalid image", ofname); } outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); res = ERR_FATAL; goto out; } if (write_out_header(outfile) != 0) { res = ERR_FATAL; goto out_flush; } if (write_out_images(outfile) != 0) { res = ERR_FATAL; goto out_flush; } if (write_out_header(outfile) != 0) { res = ERR_FATAL; goto out_flush; } DBG(1,"Image file %s completed.", ofname); out_flush: fflush(outfile); fclose(outfile); if (res == ERR_FATAL) { unlink(ofname); } out: if (res == ERR_FATAL) return EXIT_FAILURE; return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/mkchkimg.c ================================================ /* * Make CHK Image * * This utility creates Netgear .chk files. * * Copyright (C) 2008 Dave C. Reeve * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #define BUF_LEN (2048) #define MAX_BOARD_ID_LEN (64) struct chk_header { uint32_t magic; uint32_t header_len; uint8_t reserved[8]; uint32_t kernel_chksum; uint32_t rootfs_chksum; uint32_t kernel_len; uint32_t rootfs_len; uint32_t image_chksum; uint32_t header_chksum; /* char board_id[] - upto MAX_BOARD_ID_LEN */ }; static void __attribute__ ((format (printf, 2, 3))) fatal_error (int maybe_errno, const char * format, ...) { va_list ap; fprintf (stderr, "mkchkimg: "); va_start (ap, format); vfprintf (stderr, format, ap); va_end (ap); if (maybe_errno) { fprintf (stderr, ": %s\n", strerror (maybe_errno)); } else { fprintf (stderr, "\n"); } exit (EXIT_FAILURE); } static void __attribute__ ((format (printf, 1, 2))) message (const char * format, ...) { va_list ap; fprintf (stderr, "mkchkimg: "); va_start (ap, format); vfprintf (stderr, format, ap); va_end (ap); fprintf (stderr, "\n"); } struct ngr_checksum { uint32_t c0; uint32_t c1; }; static inline void netgear_checksum_init (struct ngr_checksum * c) { c->c0 = c->c1 = 0; } static inline void netgear_checksum_add (struct ngr_checksum * c, unsigned char * buf, size_t len) { size_t i; for (i=0; ic0 += buf[i] & 0xff; c->c1 += c->c0; } } static inline unsigned long netgear_checksum_fini (struct ngr_checksum * c) { uint32_t b, checksum; b = (c->c0 & 65535) + ((c->c0 >> 16) & 65535); c->c0 = ((b >> 16) + b) & 65535; b = (c->c1 & 65535) + ((c->c1 >> 16) & 65535); c->c1 = ((b >> 16) + b) & 65535; checksum = ((c->c1 << 16) | c->c0); return checksum; } static void print_help (void) { fprintf (stderr, "Usage: mkchkimg -o output -k kernel [-f filesys] [-b board_id] [-r region]\n"); } int main (int argc, char * argv[]) { int opt; char * ptr; size_t len; size_t header_len; struct chk_header * hdr; struct ngr_checksum chk_part, chk_whole; char buf[BUF_LEN]; char * output_file, * kern_file, * fs_file; FILE * out_fp, * kern_fp, * fs_fp; char * board_id; unsigned long region; /* Default values */ board_id = "U12H072T00_NETGEAR"; region = 1; /* 1=WW, 2=NA */ output_file = NULL; kern_file = NULL; fs_file = NULL; fs_fp = NULL; while ((opt = getopt (argc, argv, ":b:r:k:f:o:h")) != -1) { switch (opt) { case 'b': /* Board Identity */ if (strlen (optarg) > MAX_BOARD_ID_LEN) { fatal_error (0, "Board lenght exceeds %d", MAX_BOARD_ID_LEN); } board_id = optarg; break; case 'r': /* Region */ errno = 0; region = strtoul (optarg, &ptr, 0); if (errno || ptr==optarg || *ptr!='\0') { fatal_error (0, "Cannot parse region %s", optarg); } if (region > 0xff) { fatal_error (0, "Region cannot exceed 0xff"); } break; case 'k': /* Kernel */ kern_file = optarg; break; case 'f': /* Filing System */ fs_file = optarg; break; case 'o': /* Output file */ output_file = optarg; break; case 'h': print_help (); return EXIT_SUCCESS; case ':': print_help (); fatal_error (0, "Option -%c missing argument", optopt); break; case '?': print_help (); fatal_error (0, "Unknown argument -%c", optopt); break; default: break; } } /* Check we have all the options expected */ if (!kern_file) { print_help (); fatal_error (0, "Kernel file expected"); } if (!output_file) { print_help (); fatal_error (0, "Output file required"); } message ("Netgear CHK writer - v0.1"); /* Open the input file */ kern_fp = fopen (kern_file, "r"); if (!kern_fp) { fatal_error (errno, "Cannot open %s", kern_file); } /* Open the fs file, if specified */ if (fs_file) { fs_fp = fopen (fs_file, "r"); if (!fs_fp) { fatal_error (errno, "Cannot open %s", fs_file); } } /* Open the output file */ out_fp = fopen (output_file, "w+"); if (!out_fp) { fatal_error (errno, "Cannot open %s", output_file); } /* Write zeros when the chk header will be */ buf[0] = '\0'; header_len = sizeof (struct chk_header) + strlen (board_id); if (fwrite (buf, 1, header_len, out_fp) != header_len) { fatal_error (errno, "Cannot write header"); } /* Allocate storage for header, we fill in as we go */ hdr = malloc (sizeof (struct chk_header)); if (!hdr) { fatal_error (0, "malloc failed"); } bzero (hdr, sizeof (struct chk_header)); /* Fill in known values */ hdr->magic = htonl (0x2a23245e); hdr->header_len = htonl(header_len); hdr->reserved[0] = (unsigned char)(region & 0xff); hdr->reserved[1] = 1; /* Major */ hdr->reserved[2] = 1; /* Minor */ hdr->reserved[3] = 99; /* Build */ hdr->reserved[4] = 0; /* Unknown t1 ? was 1 */ hdr->reserved[5] = 0; /* Unknonw t2 ? was 0 */ hdr->reserved[6] = 0; /* Unknonw t3 ? was 1 */ hdr->reserved[7] = 0; /* Unused ? */ message (" Board Id: %s", board_id); message (" Region: %s", region == 1 ? "World Wide (WW)" : (region == 2 ? "North America (NA)" : "Unknown")); /* Copy the trx file, calculating the checksum as we go */ netgear_checksum_init (&chk_part); netgear_checksum_init (&chk_whole); while (!feof (kern_fp)) { len = fread (buf, 1, BUF_LEN, kern_fp); if (len < 1) { break; } if (fwrite (buf, len, 1, out_fp) != 1) { fatal_error (errno, "Write error"); } hdr->kernel_len += len; netgear_checksum_add (&chk_part, (unsigned char *)buf, len); netgear_checksum_add (&chk_whole, (unsigned char *)buf, len); } hdr->kernel_chksum = netgear_checksum_fini (&chk_part); message (" Kernel Len: %u", hdr->kernel_len); message ("Kernel Checksum: 0x%08x", hdr->kernel_chksum); hdr->kernel_len = htonl (hdr->kernel_len); hdr->kernel_chksum = htonl (hdr->kernel_chksum); /* Now copy the root fs, calculating the checksum as we go */ if (fs_fp) { netgear_checksum_init (&chk_part); while (!feof (fs_fp)) { len = fread (buf, 1, BUF_LEN, fs_fp); if (len < 1) { break; } if (fwrite (buf, len, 1, out_fp) != 1) { fatal_error (errno, "Write error"); } hdr->rootfs_len += len; netgear_checksum_add (&chk_part, (unsigned char *)buf, len); netgear_checksum_add (&chk_whole, (unsigned char *)buf, len); } hdr->rootfs_chksum = (netgear_checksum_fini (&chk_part)); message (" Rootfs Len: %u", hdr->rootfs_len); message ("Rootfs Checksum: 0x%08x", hdr->rootfs_chksum); hdr->rootfs_len = htonl (hdr->rootfs_len); hdr->rootfs_chksum = htonl (hdr->rootfs_chksum); } /* Calcautate the image checksum */ hdr->image_chksum = netgear_checksum_fini (&chk_whole); message (" Image Checksum: 0x%08x", hdr->image_chksum); hdr->image_chksum = htonl (hdr->image_chksum); /* Calculate the header checksum */ netgear_checksum_init (&chk_part); netgear_checksum_add (&chk_part, (unsigned char *)hdr, sizeof (struct chk_header)); netgear_checksum_add (&chk_part, (unsigned char *)board_id, strlen (board_id)); hdr->header_chksum = htonl (netgear_checksum_fini (&chk_part)); /* Finally rewind the output and write headers */ rewind (out_fp); if (fwrite (hdr, sizeof (struct chk_header), 1, out_fp) != 1) { fatal_error (errno, "Cannot write header"); } if (fwrite (board_id, strlen (board_id), 1, out_fp) != 1) { fatal_error (errno, "Cannot write board id"); } /* Success */ return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/mkcsysimg.c ================================================ /* * * Copyright (C) 2007-2009 Gabor Juhos * * This program was based on the code found in various Linux * source tarballs released by Edimax for it's devices. * Original author: David Hsu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include /* for __BYTE_ORDER */ #if defined(__CYGWIN__) # include #endif #include "csysimg.h" #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) # define LE16_TO_HOST(x) (x) # define LE32_TO_HOST(x) (x) #else # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) # define LE16_TO_HOST(x) bswap_16(x) # define LE32_TO_HOST(x) bswap_32(x) #endif #define MAX_NUM_BLOCKS 8 #define MAX_ARG_COUNT 32 #define MAX_ARG_LEN 1024 #define FILE_BUF_LEN (16*1024) #define CSYS_PADC 0xFF #define BLOCK_TYPE_BOOT 0 #define BLOCK_TYPE_CONF 1 #define BLOCK_TYPE_WEBP 2 #define BLOCK_TYPE_CODE 3 #define BLOCK_TYPE_XTRA 4 #define DEFAULT_BLOCK_ALIGN 0x10000U #define CSUM_SIZE_NONE 0 #define CSUM_SIZE_8 1 #define CSUM_SIZE_16 2 struct csum_state{ int size; uint16_t val; uint16_t tmp; int odd; }; struct csys_block { int type; /* type of the block */ int need_file; char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ unsigned char sig[SIG_LEN]; uint32_t addr; int addr_set; uint32_t align; int align_set; uint8_t padc; uint32_t size; uint32_t size_hdr; uint32_t size_csum; uint32_t size_avail; struct csum_state *css; }; struct board_info { char *model; char *name; uint32_t flash_size; char sig_boot[SIG_LEN]; char sig_conf[SIG_LEN]; char sig_webp[SIG_LEN]; uint32_t boot_size; uint32_t conf_size; uint32_t webp_size; uint32_t webp_size_max; uint32_t code_size; uint32_t addr_code; uint32_t addr_webp; }; #define BOARD(m, n, f, sigb, sigw, bs, cs, ws, ac, aw) {\ .model = m, .name = n, .flash_size = f<<20, \ .sig_boot = sigb, .sig_conf = SIG_CONF, .sig_webp = sigw, \ .boot_size = bs, .conf_size = cs, \ .webp_size = ws, .webp_size_max = 3*0x10000, \ .addr_code = ac, .addr_webp = aw \ } #define BOARD_ADM(m,n,f, sigw) BOARD(m,n,f, ADM_BOOT_SIG, sigw, \ ADM_BOOT_SIZE, ADM_CONF_SIZE, ADM_WEBP_SIZE, \ ADM_CODE_ADDR, ADM_WEBP_ADDR) /* * Globals */ char *progname; char *ofname = NULL; int verblevel = 0; int invalid_causes_error = 1; int keep_invalid_images = 0; struct board_info *board = NULL; struct csys_block *boot_block = NULL; struct csys_block *conf_block = NULL; struct csys_block *webp_block = NULL; struct csys_block *code_block = NULL; struct csys_block blocks[MAX_NUM_BLOCKS]; int num_blocks = 0; static struct board_info boards[] = { /* The original Edimax products */ BOARD_ADM("BR-6104K", "Edimax BR-6104K", 2, SIG_BR6104K), BOARD_ADM("BR-6104KP", "Edimax BR-6104KP", 2, SIG_BR6104KP), BOARD_ADM("BR-6104Wg", "Edimax BR-6104Wg", 2, SIG_BR6104Wg), BOARD_ADM("BR-6114WG", "Edimax BR-6114WG", 2, SIG_BR6114WG), BOARD_ADM("BR-6524K", "Edimax BR-6524K", 2, SIG_BR6524K), BOARD_ADM("BR-6524KP", "Edimax BR-6524KP", 2, SIG_BR6524KP), BOARD_ADM("BR-6524WG", "Edimax BR-6524WG", 4, SIG_BR6524WG), BOARD_ADM("BR-6524WP", "Edimax BR-6524WP", 4, SIG_BR6524WP), BOARD_ADM("BR-6541K", "Edimax BR-6541K", 2, SIG_BR6541K), BOARD_ADM("BR-6541KP", "Edimax BR-6541K", 2, SIG_BR6541KP), BOARD_ADM("BR-6541WP", "Edimax BR-6541WP", 4, SIG_BR6541WP), BOARD_ADM("EW-7207APg", "Edimax EW-7207APg", 2, SIG_EW7207APg), BOARD_ADM("PS-1205UWg", "Edimax PS-1205UWg", 2, SIG_PS1205UWg), BOARD_ADM("PS-3205U", "Edimax PS-3205U", 2, SIG_PS3205U), BOARD_ADM("PS-3205UWg", "Edimax PS-3205UWg", 2, SIG_PS3205UWg), /* Hawking products */ BOARD_ADM("H2BR4", "Hawking H2BR4", 2, SIG_H2BR4), BOARD_ADM("H2WR54G", "Hawking H2WR54G", 4, SIG_H2WR54G), /* Planet products */ BOARD_ADM("XRT-401D", "Planet XRT-401D", 2, SIG_XRT401D), BOARD_ADM("XRT-402D", "Planet XRT-402D", 2, SIG_XRT402D), /* Conceptronic products */ BOARD_ADM("C54BSR4", "Conceptronic C54BSR4", 2, SIG_C54BSR4), /* OSBRiDGE products */ BOARD_ADM("5GXi", "OSBDRiDGE 5GXi", 2, SIG_5GXI), {.model = NULL} }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", progname, ## __VA_ARGS__ \ , strerror(save)); \ } while (0) #define WARN(fmt, ...) do { \ fprintf(stderr, "[%s] *** warning: " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) #define DBG(lev, fmt, ...) do { \ if (verblevel < lev) \ break;\ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) #define ERR_FATAL -1 #define ERR_INVALID_IMAGE -2 void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...] \n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with .\n" " valid values:\n" ); for (board = boards; board->model != NULL; board++){ fprintf(stream, " %-12s: %s\n", board->model, board->name); }; fprintf(stream, " -d don't throw error on invalid images\n" " -k keep invalid images\n" " -b [:[:]]\n" " add boot code to the image\n" " -c [:[:]]\n" " add configuration settings to the image\n" " -r :[][:[:]]\n" " add runtime code to the image\n" " -w [:[][:[:]]]\n" " add webpages to the image\n" " -x [:[:]]\n" " add extra data at the end of the image\n" " -h show this screen\n" "Parameters:\n" " write output to the file \n" ); exit(status); } static inline uint32_t align(uint32_t base, uint32_t alignment) { uint32_t ret; if (alignment) { ret = (base + alignment - 1); ret &= ~(alignment-1); } else { ret = base; } return ret; } /* * argument parsing */ int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } int str2u16(char *arg, uint16_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) { return -1; } *val = t & 0xFFFF; return 0; } int str2u8(char *arg, uint8_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) { return -1; } *val = t & 0xFF; return 0; } int str2sig(char *arg, uint32_t *sig) { if (strlen(arg) != 4) return -1; *sig = arg[0] | (arg[1] << 8) | (arg[2] << 16) | (arg[3] << 24); return 0; } int parse_arg(char *arg, char *buf, char *argv[]) { int res = 0; size_t argl; char *tok; char **ap = &buf; int i; memset(argv, 0, MAX_ARG_COUNT * sizeof(void *)); if ((arg == NULL)) { /* no arguments */ return 0; } argl = strlen(arg); if (argl == 0) { /* no arguments */ return 0; } if (argl >= MAX_ARG_LEN) { /* argument is too long */ argl = MAX_ARG_LEN-1; } memcpy(buf, arg, argl); buf[argl] = '\0'; for (i = 0; i < MAX_ARG_COUNT; i++) { tok = strsep(ap, ":"); if (tok == NULL) { break; } #if 0 else if (tok[0] == '\0') { break; } #endif argv[i] = tok; res++; } return res; } int required_arg(char c, char *arg) { if (arg == NULL || *arg != '-') return 0; ERR("option -%c requires an argument\n", c); return ERR_FATAL; } int is_empty_arg(char *arg) { int ret = 1; if (arg != NULL) { if (*arg) ret = 0; }; return ret; } void csum8_update(uint8_t *p, uint32_t len, struct csum_state *css) { for ( ; len > 0; len --) { css->val += *p++; } } uint16_t csum8_get(struct csum_state *css) { uint8_t t; t = css->val; return ~t + 1; } void csum16_update(uint8_t *p, uint32_t len, struct csum_state *css) { uint16_t t; if (css->odd) { t = css->tmp + (p[0]<<8); css->val += LE16_TO_HOST(t); css->odd = 0; len--; p++; } for ( ; len > 1; len -= 2, p +=2 ) { t = p[0] + (p[1] << 8); css->val += LE16_TO_HOST(t); } if (len == 1) { css->tmp = p[0]; css->odd = 1; } } uint16_t csum16_get(struct csum_state *css) { char pad = 0; csum16_update(&pad, 1, css); return ~css->val + 1; } void csum_init(struct csum_state *css, int size) { css->val = 0; css->tmp = 0; css->odd = 0; css->size = size; } void csum_update(uint8_t *p, uint32_t len, struct csum_state *css) { switch (css->size) { case CSUM_SIZE_8: csum8_update(p,len,css); break; case CSUM_SIZE_16: csum16_update(p,len,css); break; } } uint16_t csum_get(struct csum_state *css) { uint16_t ret; switch (css->size) { case CSUM_SIZE_8: ret = csum8_get(css); break; case CSUM_SIZE_16: ret = csum16_get(css); break; } return ret; } /* * routines to write data to the output file */ int write_out_data(FILE *outfile, uint8_t *data, size_t len, struct csum_state *css) { errno = 0; fwrite(data, len, 1, outfile); if (errno) { ERRS("unable to write output file"); return ERR_FATAL; } if (css) { csum_update(data, len, css); } return 0; } int write_out_padding(FILE *outfile, size_t len, uint8_t padc, struct csum_state *css) { uint8_t buf[512]; size_t buflen = sizeof(buf); int err; memset(buf, padc, buflen); while (len > 0) { if (len < buflen) buflen = len; err = write_out_data(outfile, buf, buflen, css); if (err) return err; len -= buflen; } return 0; } int block_stat_file(struct csys_block *block) { struct stat st; int err; if (block->file_name == NULL) return 0; err = stat(block->file_name, &st); if (err){ ERRS("stat failed on %s", block->file_name); return ERR_FATAL; } block->file_size = st.st_size; return 0; } int block_writeout_hdr(FILE *outfile, struct csys_block *block) { struct csys_header hdr; int res; if (block->size_hdr == 0) return 0; /* setup header fields */ memcpy(hdr.sig, block->sig, 4); hdr.addr = HOST_TO_LE32(block->addr); hdr.size = HOST_TO_LE32(block->size - block->size_hdr - block->size_csum); DBG(1,"writing header for block"); res = write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr),NULL); return res; } int block_writeout_file(FILE *outfile, struct csys_block *block) { char buf[FILE_BUF_LEN]; size_t buflen = sizeof(buf); FILE *f; size_t len; int res; if (block->file_name == NULL) return 0; if (block->file_size == 0) return 0; errno = 0; f = fopen(block->file_name,"r"); if (errno) { ERRS("unable to open file: %s", block->file_name); return ERR_FATAL; } len = block->file_size; while (len > 0) { if (len < buflen) buflen = len; /* read data from source file */ errno = 0; fread(buf, buflen, 1, f); if (errno != 0) { ERRS("unable to read from file: %s", block->file_name); res = ERR_FATAL; break; } res = write_out_data(outfile, buf, buflen, block->css); if (res) break; len -= buflen; } fclose(f); return res; } int block_writeout_data(FILE *outfile, struct csys_block *block) { int res; size_t padlen; res = block_writeout_file(outfile, block); if (res) return res; /* write padding data if neccesary */ padlen = block->size_avail - block->file_size; DBG(1,"padding block, length=%d", padlen); res = write_out_padding(outfile, padlen, block->padc, block->css); return res; } int block_writeout_csum(FILE *outfile, struct csys_block *block) { uint16_t csum; int res; if (block->size_csum == 0) return 0; DBG(1,"writing checksum for block"); csum = HOST_TO_LE16(csum_get(block->css)); res = write_out_data(outfile, (uint8_t *)&csum, block->size_csum, NULL); return res; } int block_writeout(FILE *outfile, struct csys_block *block) { int res; struct csum_state css; res = 0; if (block == NULL) return res; block->css = NULL; DBG(2, "writing block, file=%s, file_size=%d, space=%d", block->file_name, block->file_size, block->size_avail); res = block_writeout_hdr(outfile, block); if (res) return res; if (block->size_csum != 0) { block->css = &css; csum_init(&css, block->size_csum); } res = block_writeout_data(outfile, block); if (res) return res; res = block_writeout_csum(outfile, block); if (res) return res; return res; } int write_out_blocks(FILE *outfile) { struct csys_block *block; int i, res; res = block_writeout(outfile, boot_block); if (res) return res; res = block_writeout(outfile, conf_block); if (res) return res; res = block_writeout(outfile, webp_block); if (res) return res; res = block_writeout(outfile, code_block); if (res) return res; res = 0; for (i=0; i < num_blocks; i++) { block = &blocks[i]; if (block->type != BLOCK_TYPE_XTRA) continue; res = block_writeout(outfile, block); if (res) break; } return res; } struct board_info * find_board(char *model) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->model != NULL; board++){ if (strcasecmp(model, board->model) == 0) { ret = board; break; } }; return ret; } int parse_opt_board(char ch, char *arg) { DBG(1,"parsing board option: -%c %s", ch, arg); if (board != NULL) { ERR("only one board option allowed"); return ERR_FATAL; } if (required_arg(ch, arg)) return ERR_FATAL; board = find_board(arg); if (board == NULL){ ERR("invalid/unknown board specified: %s", arg); return ERR_FATAL; } return 0; } int parse_opt_block(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; struct csys_block *block; int i; if ( num_blocks > MAX_NUM_BLOCKS ) { ERR("too many blocks specified"); return ERR_FATAL; } block = &blocks[num_blocks]; /* setup default field values */ block->need_file = 1; block->padc = 0xFF; switch (ch) { case 'b': if (boot_block) { WARN("only one boot block allowed"); break; } block->type = BLOCK_TYPE_BOOT; boot_block = block; break; case 'c': if (conf_block) { WARN("only one config block allowed"); break; } block->type = BLOCK_TYPE_CONF; conf_block = block; break; case 'w': if (webp_block) { WARN("only one web block allowed"); break; } block->type = BLOCK_TYPE_WEBP; block->size_hdr = sizeof(struct csys_header); block->size_csum = CSUM_SIZE_8; block->need_file = 0; webp_block = block; break; case 'r': if (code_block) { WARN("only one runtime block allowed"); break; } block->type = BLOCK_TYPE_CODE; block->size_hdr = sizeof(struct csys_header); block->size_csum = CSUM_SIZE_16; code_block = block; break; case 'x': block->type = BLOCK_TYPE_XTRA; break; default: ERR("unknown block type \"%c\"", ch); return ERR_FATAL; } argc = parse_arg(arg, buf, argv); i = 0; p = argv[i++]; if (!is_empty_arg(p)) { block->file_name = strdup(p); if (block->file_name == NULL) { ERR("not enough memory"); return ERR_FATAL; } } else if (block->need_file){ ERR("no file specified in %s", arg); return ERR_FATAL; } if (block->size_hdr) { p = argv[i++]; if (!is_empty_arg(p)) { if (str2u32(p, &block->addr) != 0) { ERR("invalid start address in %s", arg); return ERR_FATAL; } block->addr_set = 1; } } p = argv[i++]; if (!is_empty_arg(p)) { if (str2u32(p, &block->align) != 0) { ERR("invalid alignment value in %s", arg); return ERR_FATAL; } block->align_set = 1; } p = argv[i++]; if (!is_empty_arg(p) && (str2u8(p, &block->padc) != 0)) { ERR("invalid paddig character in %s", arg); return ERR_FATAL; } num_blocks++; return 0; } int process_blocks(void) { struct csys_block *block; uint32_t offs = 0; int i; int res; res = 0; /* collecting stats */ for (i = 0; i < num_blocks; i++) { block = &blocks[i]; res = block_stat_file(block); if (res) return res; } /* bootloader */ block = boot_block; if (block) { block->size = board->boot_size; if (block->file_size > board->boot_size) { WARN("boot block is too big"); res = ERR_INVALID_IMAGE; } } offs += board->boot_size; /* configuration data */ block = conf_block; if (block) { block->size = board->conf_size; if (block->file_size > board->conf_size) { WARN("config block is too big"); res = ERR_INVALID_IMAGE; } } offs += board->conf_size; /* webpages */ block = webp_block; if (block) { memcpy(block->sig, board->sig_webp, 4); if (block->addr_set == 0) block->addr = board->addr_webp; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size + block->size_hdr + block->size_csum, block->align) - offs; if (block->size > board->webp_size_max) { WARN("webpages block is too big"); res = ERR_INVALID_IMAGE; } DBG(2,"webpages start at %08x, size=%08x", offs, block->size); offs += block->size; if (offs > board->flash_size) { WARN("webp block is too big"); res = ERR_INVALID_IMAGE; } } /* runtime code */ block = code_block; if (block) { memcpy(code_block->sig, SIG_CSYS, 4); if (block->addr_set == 0) block->addr = board->addr_code; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size + block->size_hdr + block->size_csum, block->align) - offs; DBG(2,"code block start at %08x, size=%08x", offs, block->size); offs += block->size; if (offs > board->flash_size) { WARN("code block is too big"); res = ERR_INVALID_IMAGE; } } for (i = 0; i < num_blocks; i++) { block = &blocks[i]; if (block->type != BLOCK_TYPE_XTRA) continue; if (block->align_set == 0) block->align = DEFAULT_BLOCK_ALIGN; block->size = align(offs + block->file_size, block->align) - offs; DBG(2,"file %s start at %08x, size=%08x, align=%08x", block->file_name, offs, block->size, block->align); offs += block->size; if (offs > board->flash_size) { WARN("file %s is too big, size=%d, avail=%d", block->file_name, block->file_size, board->flash_size - offs); res = ERR_INVALID_IMAGE; } } for (i = 0; i < num_blocks; i++) { block = &blocks[i]; block->size_avail = block->size - block->size_hdr - block->size_csum; if (block->size_avail < block->file_size) { WARN("file %s is too big, size=%d, avail=%d", block->file_name, block->file_size, block->size_avail); res = ERR_INVALID_IMAGE; } } return res; } int main(int argc, char *argv[]) { int optinvalid = 0; /* flag for invalid option */ int c; int res = ERR_FATAL; FILE *outfile; progname=basename(argv[0]); opterr = 0; /* could not print standard getopt error messages */ while ( 1 ) { optinvalid = 0; c = getopt(argc, argv, "b:B:c:dhkr:vw:x:"); if (c == -1) break; switch (c) { case 'b': case 'c': case 'r': case 'x': optinvalid = parse_opt_block(c,optarg); break; case 'w': if (optarg != NULL && *optarg == '-') { /* rollback */ optind--; optarg = NULL; } optinvalid = parse_opt_block(c,optarg); break; case 'd': invalid_causes_error = 0; break; case 'k': keep_invalid_images = 1; break; case 'B': optinvalid = parse_opt_board(c,optarg); break; case 'v': verblevel++; break; case 'h': usage(EXIT_SUCCESS); break; default: optinvalid = 1; break; } if (optinvalid != 0 ){ ERR("invalid option: -%c", optopt); goto out; } } if (board == NULL) { ERR("no board specified"); goto out; } if (optind == argc) { ERR("no output file specified"); goto out; } ofname = argv[optind++]; if (optind < argc) { ERR("invalid option: %s", argv[optind]); goto out; } res = process_blocks(); if (res == ERR_FATAL) goto out; if (res == ERR_INVALID_IMAGE) { if (invalid_causes_error) res = ERR_FATAL; if (keep_invalid_images == 0) { WARN("generation of invalid images disabled", ofname); goto out; } WARN("generating invalid image", ofname); } outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); res = ERR_FATAL; goto out; } if (write_out_blocks(outfile) != 0) { res = ERR_FATAL; goto out_flush; } DBG(1,"Image file %s completed.", ofname); out_flush: fflush(outfile); fclose(outfile); if (res == ERR_FATAL) { unlink(ofname); } out: if (res == ERR_FATAL) return EXIT_FAILURE; return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/mkdapimg.c ================================================ #include #include #include #include #include #include #include #include #include #include // htonl // Usage: mkdapimg [-p] [-m ] -s -i -o // // e.g.: mkdapimg -s RT3052-AP-DAP1350-3 -i sysupgarde.bin -o factory.bin // // If the model string is not given, we will assume that // the leading characters upto the first "-" is the model. // // The "-p" (patch) option is used to patch the exisiting image with the // specified model and signature. // The "-x" (fix) option will recalculate the payload size and checksum // during the patch mode operation. // The img_hdr_struct was taken from the D-Link SDK: // DAP-1350_A1_FW1.11NA_GPL/GPL_Source_Code/Uboot/DAP-1350/httpd/header.h #define MAX_MODEL_NAME_LEN 20 #define MAX_SIG_LEN 30 struct img_hdr_struct { uint32_t checksum; char model[MAX_MODEL_NAME_LEN]; char sig[MAX_SIG_LEN]; uint8_t partition; uint8_t hdr_len; uint8_t rsv1; uint8_t rsv2; uint32_t flash_byte_cnt; } imghdr ; char *progname; void perrexit(int code, char *msg) { fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); exit(code); } void usage() { fprintf(stderr, "usage: %s [-p] [-m model] -s signature -i input -o output\n", progname); exit(1); } int main(int ac, char *av[]) { char model[MAX_MODEL_NAME_LEN+1]; char signature[MAX_SIG_LEN+1]; int patchmode = 0; int fixmode = 0; FILE *ifile, *ofile; int c; uint32_t cksum; uint32_t bcnt; progname = basename(av[0]); memset(model, 0, sizeof(model)); memset(signature, 0, sizeof(signature)); while ( 1 ) { int c; c = getopt(ac, av, "pxm:s:i:o:"); if (c == -1) break; switch (c) { case 'p': patchmode = 1; break; case 'x': fixmode = 1; break; case 'm': if (strlen(optarg) > MAX_MODEL_NAME_LEN) { fprintf(stderr, "%s: model name exceeds %d chars\n", progname, MAX_MODEL_NAME_LEN); exit(1); } strcpy(model, optarg); break; case 's': if (strlen(optarg) > MAX_SIG_LEN) { fprintf(stderr, "%s: signature exceeds %d chars\n", progname, MAX_SIG_LEN); exit(1); } strcpy(signature, optarg); break; case 'i': if ((ifile = fopen(optarg, "r")) == NULL) perrexit(1, optarg); break; case 'o': if ((ofile = fopen(optarg, "w")) == NULL) perrexit(1, optarg); break; default: usage(); } } if (signature[0] == 0 || ifile == NULL || ofile == NULL) { usage(); } if (model[0] == 0) { char *p = strchr(signature, '-'); if (p == NULL) { fprintf(stderr, "%s: model name unknown\n", progname); exit(1); } if (p - signature > MAX_MODEL_NAME_LEN) { *p = 0; fprintf(stderr, "%s: auto model name failed, string %s too long\n", progname, signature); exit(1); } strncpy(model, signature, p - signature); } if (patchmode) { if (fread(&imghdr, sizeof(imghdr), 1, ifile) < 0) perrexit(2, "fread on input"); } for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++) cksum += c & 0xff; if (fseek(ifile, patchmode ? sizeof(imghdr) : 0, SEEK_SET) < 0) perrexit(2, "fseek on input"); if (patchmode == 0) { // Fill in the header memset(&imghdr, 0, sizeof(imghdr)); imghdr.checksum = htonl(cksum); imghdr.partition = 0 ; // don't care? imghdr.hdr_len = sizeof(imghdr); imghdr.flash_byte_cnt = htonl(bcnt); } else { if (ntohl(imghdr.checksum) != cksum) { fprintf(stderr, "%s: patch mode, checksum mismatch\n", progname); if (fixmode) { fprintf(stderr, "%s: fixing\n", progname); imghdr.checksum = htonl(cksum); } else exit(3); } else if (ntohl(imghdr.flash_byte_cnt) != bcnt) { fprintf(stderr, "%s: patch mode, size mismatch\n", progname); if (fixmode) { fprintf(stderr, "%s: fixing\n", progname); imghdr.flash_byte_cnt = htonl(bcnt); } else exit(3); } } strncpy(imghdr.model, model, MAX_MODEL_NAME_LEN); strncpy(imghdr.sig, signature, MAX_SIG_LEN); if (fwrite(&imghdr, sizeof(imghdr), 1, ofile) < 0) perrexit(2, "fwrite header on output"); while ((c = fgetc(ifile)) != EOF) { if (fputc(c, ofile) == EOF) perrexit(2, "fputc on output"); } if (ferror(ifile)) perrexit(2, "fgetc on input"); fclose(ofile); fclose(ifile); } ================================================ FILE: src/firmware-tools/mkdir615h1.c ================================================ /* * * Copyright (C) 2012 OpenWrt.org * Copyright (C) 2012 Mikko Hissa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include #include #include #include "md5.h" #define HDR_LEN 0x60 #define BUF_SIZE 0x200 #define VERSION_SIZE 0x10 #define MD5_SIZE 0x10 #define PAD_SIZE 0x20 #define DEFAULT_MAGIC 305419896 #define DEFAULT_VERSION "123" #define DEFAULT_VENDOR_ID 536 #define DEFAULT_HEAD_VALUE 0x0 #define DEFAULT_BLOCK_SIZE 65535 #define DEFAULT_PRODUCT_ID 48 #define DEFAULT_FIRMWARE_TYPE 0x03 typedef struct { uint32_t head; uint32_t vendor_id; uint32_t product_id; uint8_t version[VERSION_SIZE]; uint32_t firmware_type; uint32_t filesize; uint32_t zero; uint8_t md5sum[MD5_SIZE]; uint8_t pad[PAD_SIZE]; uint32_t chksum; uint32_t magic; } img_header; typedef struct { uint8_t id; char * name; } firmware_type; typedef enum { NONE, ENCODE, DECODE } op_mode; static firmware_type FIRMWARE_TYPES[] = { { 0x01, "bootloader" }, { 0x02, "kernel" }, { 0x03, "kernelapp" }, { 0x04, "apps" }, { 0x05, "littleapps" }, { 0x06, "sounds" }, { 0x07, "userconfig" }, { 0x0a, "factoryapps" }, { 0x0b, "odmapps" }, { 0x0c, "langpack" } }; static long get_file_size(const char *filename) { FILE *fp_file; long result; fp_file = fopen(filename, "r"); if (!fp_file) return -1; fseek(fp_file, 0, SEEK_END); result = ftell(fp_file); fclose(fp_file); return result; } static int header_checksum(void *data, int len) { int i; int sum; sum = 0; if (data != NULL && len >= 0) { for (i = 0; i < len; ++i) sum += *(unsigned char *) (data + i); return sum; } return -1; } static int md5_file(const char *filename, uint8_t *dst) { FILE *fp_src; MD5_CTX ctx; char buf[BUF_SIZE]; size_t bytes_read; MD5_Init(&ctx); fp_src = fopen(filename, "r+b"); if (!fp_src) { return -1; } while (!feof(fp_src)) { bytes_read = fread(&buf, 1, BUF_SIZE, fp_src); MD5_Update(&ctx, &buf, bytes_read); } fclose(fp_src); MD5_Final(dst, &ctx); return 0; } static int encode_image(const char *input_file_name, const char *output_file_name, img_header *header, int block_size) { char buf[BUF_SIZE]; size_t bytes_read; size_t pad_len = 0; size_t bytes_avail; FILE *fp_input; FILE *fp_output; int i; long magic; fp_input = fopen(input_file_name, "r+b"); if (!fp_input) { fprintf(stderr, "Cannot open %s !!\n", input_file_name); return -1; } fp_output = fopen(output_file_name, "w+b"); if (!fp_output) { fprintf(stderr, "Cannot open %s !!\n", output_file_name); fclose(fp_input); return -1; } header->filesize = get_file_size(input_file_name); if (!header->filesize) { fprintf(stderr, "File %s open/size error!\n", input_file_name); fclose(fp_input); fclose(fp_output); return -1; } /* * Zero padding */ if (block_size > 0) { pad_len = block_size - (header->filesize % block_size); } if (md5_file(input_file_name, (uint8_t *) &header->md5sum) < 0) { fprintf(stderr, "Md5 failed on file %s\n", input_file_name); fclose(fp_input); fclose(fp_output); return -1; } header->zero = 0; header->chksum = header_checksum(header, HDR_LEN); header->head = htonl(header->head); header->vendor_id = htonl(header->vendor_id); header->product_id = htonl(header->product_id); header->firmware_type = htonl(header->firmware_type); header->filesize = htonl(header->filesize); header->chksum = htonl(header->chksum); magic = header->magic; header->magic = htonl(header->magic); fwrite(header, HDR_LEN, 1, fp_output); while (!feof(fp_input) || pad_len > 0) { if (!feof(fp_input)) bytes_read = fread(&buf, 1, BUF_SIZE, fp_input); else bytes_read = 0; /* * No more bytes read, start padding */ if (bytes_read < BUF_SIZE && pad_len > 0) { bytes_avail = BUF_SIZE - bytes_read; memset( &buf[bytes_read], 0, bytes_avail); bytes_read += bytes_avail < pad_len ? bytes_avail : pad_len; pad_len -= bytes_avail < pad_len ? bytes_avail : pad_len; } for (i = 0; i < bytes_read; i++) buf[i] ^= magic >> ((((i >> 60) + i) & 7) - (i >> 60)); fwrite(&buf, bytes_read, 1, fp_output); } fclose(fp_input); fclose(fp_output); return 1; } int decode_image(const char *input_file_name, const char *output_file_name) { img_header header; char buf[512]; FILE *fp_input; FILE *fp_output; unsigned int i; size_t bytes_read; size_t bytes_written; fp_input = fopen(input_file_name, "r+b"); if (!fp_input) { fprintf(stderr, "Cannot open %s !!\n", input_file_name); fclose(fp_input); return -1; } fp_output = fopen(output_file_name, "w+b"); if (!fp_output) { fprintf(stderr, "Cannot open %s !!\n", output_file_name); fclose(fp_output); return -1; } if (fread(&header, 1, HDR_LEN, fp_input) != HDR_LEN) { fprintf(stderr, "Incorrect header size!!"); fclose(fp_input); fclose(fp_output); return -1; } header.head = ntohl(header.head); header.vendor_id = ntohl(header.vendor_id); header.product_id = ntohl(header.product_id); header.firmware_type = ntohl(header.firmware_type); header.filesize = ntohl(header.filesize); header.chksum = ntohl(header.chksum); header.magic = ntohl(header.magic); bytes_written = 0; while (!feof(fp_input)) { bytes_read = fread(&buf, 1, BUF_SIZE, fp_input); for (i = 0; i < bytes_read; i++) buf[i] ^= header.magic >> ((((i >> 60) + i) & 7) - (i >> 60)); /* * Handle padded source file */ if (bytes_written + bytes_read > header.filesize) { bytes_read = header.filesize - bytes_written; if (bytes_read > 0) fwrite(&buf, bytes_read, 1, fp_output); break; } fwrite(&buf, bytes_read, 1, fp_output); bytes_written += bytes_read; } fclose(fp_input); fclose(fp_output); return 1; } static void usage(const char *progname, int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; int i; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -e encode image file \n" " -d decode image file \n" " -o write output to the file \n" " -t set image type to , defaults to 3\n" " valid image values:\n"); for (i = 0; i < sizeof(FIRMWARE_TYPES) / sizeof(firmware_type); i++) { fprintf(stream, " %-5i= %s\n", FIRMWARE_TYPES[i].id, FIRMWARE_TYPES[i].name); } fprintf(stream, " -v set image version to \n" " -r set image vendor id to \n" " -p set image product id to \n" " -m set encoding magic \n" " -z enable image padding to \n" " -b set image , defaults to 65535\n" " -h show this screen\n"); exit(status); } int main(int argc, char *argv[]) { int opt; char *input_file, *output_file, *progname = NULL; op_mode mode = NONE; int tmp, i, pad = 0; int block_size; img_header header; block_size = DEFAULT_BLOCK_SIZE; progname = basename(argv[0]); memset(&header, 0, sizeof( img_header )); header.magic = DEFAULT_MAGIC; header.head = DEFAULT_HEAD_VALUE; header.vendor_id = DEFAULT_VENDOR_ID; header.product_id = DEFAULT_PRODUCT_ID; header.firmware_type = DEFAULT_FIRMWARE_TYPE; strncpy( (char*)&header.version, DEFAULT_VERSION, VERSION_SIZE - 1); while ((opt = getopt(argc, argv, ":o:e:d:t:v:r:p:m:b:h?z")) != -1) { switch (opt) { case 'e': input_file = optarg; mode = ENCODE; break; case 'd': input_file = optarg; mode = DECODE; break; case 'o': output_file = optarg; break; case 't': tmp = strtol(optarg, 0, 10); for (i = 0; i < sizeof(FIRMWARE_TYPES) / sizeof(firmware_type); i++) { if (FIRMWARE_TYPES[i].id == tmp) { header.firmware_type = FIRMWARE_TYPES[i].id; break; } } if (header.firmware_type == 0) { fprintf(stderr, "Invalid firmware !\n"); usage(progname, EXIT_FAILURE); } break; case 'v': strncpy( (char*)&header.version, optarg, VERSION_SIZE - 1); break; case 'r': header.vendor_id = strtol(optarg, 0, 10); break; case 'p': header.product_id = strtol(optarg, 0, 10); break; case 'm': header.magic = strtoul(optarg, 0, 16); break; case 'z': pad = 1; break; case 'b': block_size = strtol(optarg, 0, 10); break; case 'h': usage(progname, EXIT_SUCCESS); break; case ':': fprintf(stderr, "Option -%c requires an operand\n", optopt); usage(progname, EXIT_FAILURE); break; case '?': fprintf(stderr, "Unrecognized option: -%c\n", optopt); usage(progname, EXIT_FAILURE); break; default: usage(progname, EXIT_FAILURE); break; } } if (input_file == NULL || output_file == NULL ) { fprintf(stderr, "Input and output files must be defined\n"); usage(progname, EXIT_FAILURE); } switch (mode) { case NONE: usage(progname, EXIT_FAILURE); break; case ENCODE: if (encode_image(input_file, output_file, &header, pad ? block_size : 0) < 0) return EXIT_FAILURE; break; case DECODE: if (decode_image(input_file, output_file) < 0) return EXIT_FAILURE; break; } return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/mkdniimg.c ================================================ /* * Copyright (C) 2009 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #define DNI_HDR_LEN 128 /* * Globals */ static char *ifname; static char *progname; static char *ofname; static char *version = "1.00.00"; static char *region = ""; static char *hd_id; static char *board_id; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with \n" " -i read input from the file \n" " -o write output to the file \n" " -v set image version to \n" " -r set image region to \n" " -H set image hardware id to \n" " -h show this screen\n" ); exit(status); } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int buflen; int err; struct stat st; char *buf; int pos, rem, i; uint8_t csum; FILE *outfile, *infile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "B:i:o:v:r:H:h"); if (c == -1) break; switch (c) { case 'B': board_id = optarg; break; case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 'v': version = optarg; break; case 'r': region = optarg; break; case 'H': hd_id = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } if (board_id == NULL) { ERR("no board specified"); goto err; } if (ifname == NULL) { ERR("no input file specified"); goto err; } if (ofname == NULL) { ERR("no output file specified"); goto err; } err = stat(ifname, &st); if (err){ ERRS("stat failed on %s", ifname); goto err; } buflen = st.st_size + DNI_HDR_LEN + 1; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto err; } memset(buf, 0, DNI_HDR_LEN); pos = snprintf(buf, DNI_HDR_LEN, "device:%s\nversion:V%s\nregion:%s\n", board_id, version, region); rem = DNI_HDR_LEN - pos; if (pos >= 0 && rem > 1 && hd_id) { snprintf(buf + pos, rem, "hd_id:%s\n", hd_id); } infile = fopen(ifname, "r"); if (infile == NULL) { ERRS("could not open \"%s\" for reading", ifname); goto err_free; } errno = 0; fread(buf + DNI_HDR_LEN, st.st_size, 1, infile); if (errno != 0) { ERRS("unable to read from file %s", ifname); goto err_close_in; } csum = 0; for (i = 0; i < (st.st_size + DNI_HDR_LEN); i++) csum += buf[i]; csum = 0xff - csum; buf[st.st_size + DNI_HDR_LEN] = csum; outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto err_close_in; } errno = 0; fwrite(buf, buflen, 1, outfile); if (errno) { ERRS("unable to write to file %s", ofname); goto err_close_out; } res = EXIT_SUCCESS; out_flush: fflush(outfile); err_close_out: fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } err_close_in: fclose(infile); err_free: free(buf); err: return res; } ================================================ FILE: src/firmware-tools/mkedimaximg.c ================================================ /* * Copyright (C) 2011 Vasilis Tsiligiannis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * */ #include #include #include #include #include #include #include #include /* for __BYTE_ORDER */ #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) #else # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) #endif struct header { unsigned char sign[4]; unsigned int start; unsigned int flash; unsigned char model[4]; unsigned int size; } __attribute__ ((packed)); struct finfo { char *name; off_t size; }; struct buf { char *start; size_t size; }; static char *progname; static void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -s set image signature to \n" " -m set model to \n" " -i read input from file \n" " -o write output to file \n" " -f set flash address to \n" " -S set start address to \n"); exit(status); } static int strtou32(char *arg, unsigned int *val) { char *endptr = NULL; errno = 0; *val = strtoul(arg, &endptr, 0); if (errno || (endptr == arg) || (*endptr && (endptr != NULL))) { return EXIT_SUCCESS; } return EXIT_FAILURE; } static unsigned short fwcsum (struct buf *buf) { int i; unsigned short ret = 0; for (i = 0; i < buf->size / 2; i++) ret -= ((unsigned short *) buf->start)[i]; return ret; } static int fwread(struct finfo *finfo, struct buf *buf) { FILE *f; f = fopen(finfo->name, "r"); if (!f) { fprintf(stderr, "could not open \"%s\" for reading\n", finfo->name); usage(EXIT_FAILURE); } buf->size = fread(buf->start, 1, finfo->size, f); if (buf->size != finfo->size) { fprintf(stderr, "unable to read from file \"%s\"\n", finfo->name); usage(EXIT_FAILURE); } fclose(f); return EXIT_SUCCESS; } static int fwwrite(struct finfo *finfo, struct buf *buf) { FILE *f; f = fopen(finfo->name, "w"); if (!f) { fprintf(stderr, "could not open \"%s\" for writing\n", finfo->name); usage(EXIT_FAILURE); } buf->size = fwrite(buf->start, 1, finfo->size, f); if (buf->size != finfo->size) { fprintf(stderr, "unable to write to file \"%s\"\n", finfo->name); usage(EXIT_FAILURE); } fclose(f); return EXIT_SUCCESS; } int main(int argc, char **argv) { struct stat st; struct header header; struct buf ibuf, obuf; struct finfo ifinfo, ofinfo; unsigned short csum; int c; ifinfo.name = ofinfo.name = NULL; header.flash = header.size = header.start = 0; progname = basename(argv[0]); while((c = getopt(argc, argv, "i:o:m:s:f:S:h")) != -1) { switch (c) { case 'i': ifinfo.name = optarg; break; case 'o': ofinfo.name = optarg; break; case 'm': if (strlen(optarg) != 4) { fprintf(stderr, "model must be 4 characters long\n"); usage(EXIT_FAILURE); } memcpy(header.model, optarg, 4); break; case 's': if (strlen(optarg) != 4) { fprintf(stderr, "signature must be 4 characters long\n"); usage(EXIT_FAILURE); } memcpy(header.sign, optarg, 4); break; case 'h': usage(EXIT_SUCCESS); break; case 'f': if (!strtou32(optarg, &header.flash)) { fprintf(stderr, "invalid flash address specified\n"); usage(EXIT_FAILURE); } break; case 'S': if (!strtou32(optarg, &header.start)) { fprintf(stderr, "invalid start address specified\n"); usage(EXIT_FAILURE); } break; default: usage(EXIT_FAILURE); break; } } if (ifinfo.name == NULL) { fprintf(stderr, "no input file specified\n"); usage(EXIT_FAILURE); } if (ofinfo.name == NULL) { fprintf(stderr, "no output file specified\n"); usage(EXIT_FAILURE); } if (stat(ifinfo.name, &st)) { fprintf(stderr, "stat failed on %s\n", ifinfo.name); usage(EXIT_FAILURE); } if (header.sign == NULL) { fprintf(stderr, "no signature specified\n"); usage(EXIT_FAILURE); } if (header.model == NULL) { fprintf(stderr, "no model specified\n"); usage(EXIT_FAILURE); } if (!header.flash) { fprintf(stderr, "no flash address specified\n"); usage(EXIT_FAILURE); } if (!header.start) { fprintf(stderr, "no start address specified\n"); usage(EXIT_FAILURE); } ifinfo.size = st.st_size; obuf.size = ifinfo.size + sizeof(struct header) + sizeof(unsigned short); if (obuf.size % sizeof(unsigned short)) obuf.size++; obuf.start = malloc(obuf.size); if (!obuf.start) { fprintf(stderr, "no memory for buffer\n"); usage(EXIT_FAILURE); } memset(obuf.start, 0, obuf.size); ibuf.size = ifinfo.size; ibuf.start = obuf.start + sizeof(struct header); if (fwread(&ifinfo, &ibuf)) usage(EXIT_FAILURE); header.flash = HOST_TO_LE32(header.flash); header.size = HOST_TO_LE32(obuf.size - sizeof(struct header)); header.start = HOST_TO_LE32(header.start); memcpy (obuf.start, &header, sizeof(struct header)); csum = HOST_TO_LE16(fwcsum(&ibuf)); memcpy(obuf.start + obuf.size - sizeof(unsigned short), &csum, sizeof(unsigned short)); ofinfo.size = obuf.size; if (fwwrite(&ofinfo, &obuf)) usage(EXIT_FAILURE); return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/mkfwimage.c ================================================ /* * Copyright (C) 2007 Ubiquiti Networks, Inc. * Copyright (C) 2008 Lukas Kuna * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "fw.h" typedef struct fw_layout_data { char name[PATH_MAX]; u_int32_t kern_start; u_int32_t kern_entry; u_int32_t firmware_max_length; } fw_layout_t; fw_layout_t fw_layout_data[] = { { .name = "XS2", .kern_start = 0xbfc30000, .kern_entry = 0x80041000, .firmware_max_length= 0x00390000, }, { .name = "XS5", .kern_start = 0xbe030000, .kern_entry = 0x80041000, .firmware_max_length= 0x00390000, }, { .name = "RS", .kern_start = 0xbf030000, .kern_entry = 0x80060000, .firmware_max_length= 0x00B00000, }, { .name = "RSPRO", .kern_start = 0xbf030000, .kern_entry = 0x80060000, .firmware_max_length= 0x00B00000, }, { .name = "LS-SR71", .kern_start = 0xbf030000, .kern_entry = 0x80060000, .firmware_max_length= 0x00640000, }, { .name = "XS2-8", .kern_start = 0xa8030000, .kern_entry = 0x80041000, .firmware_max_length= 0x006C0000, }, { .name = "XM", .kern_start = 0x9f050000, .kern_entry = 0x80002000, .firmware_max_length= 0x006A0000, }, { .name = "", }, }; typedef struct part_data { char partition_name[64]; int partition_index; u_int32_t partition_baseaddr; u_int32_t partition_startaddr; u_int32_t partition_memaddr; u_int32_t partition_entryaddr; u_int32_t partition_length; char filename[PATH_MAX]; struct stat stats; } part_data_t; #define MAX_SECTIONS 8 #define DEFAULT_OUTPUT_FILE "firmware-image.bin" #define DEFAULT_VERSION "UNKNOWN" #define OPTIONS "B:hv:m:o:r:k:" static int debug = 0; typedef struct image_info { char magic[16]; char version[256]; char outputfile[PATH_MAX]; u_int32_t part_count; part_data_t parts[MAX_SECTIONS]; } image_info_t; static void write_header(void* mem, const char *magic, const char* version) { header_t* header = mem; memset(header, 0, sizeof(header_t)); memcpy(header->magic, magic, MAGIC_LENGTH); strncpy(header->version, version, sizeof(header->version)); header->crc = htonl(crc32(0L, (unsigned char *)header, sizeof(header_t) - 2 * sizeof(u_int32_t))); header->pad = 0L; } static void write_signature(void* mem, u_int32_t sig_offset) { /* write signature */ signature_t* sign = (signature_t*)(mem + sig_offset); memset(sign, 0, sizeof(signature_t)); memcpy(sign->magic, MAGIC_END, MAGIC_LENGTH); sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset)); sign->pad = 0L; } static int write_part(void* mem, part_data_t* d) { char* addr; int fd; part_t* p = mem; part_crc_t* crc = mem + sizeof(part_t) + d->stats.st_size; fd = open(d->filename, O_RDONLY); if (fd < 0) { ERROR("Failed opening file '%s'\n", d->filename); return -1; } if ((addr=(char*)mmap(0, d->stats.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { ERROR("Failed mmaping memory for file '%s'\n", d->filename); close(fd); return -2; } memcpy(mem + sizeof(part_t), addr, d->stats.st_size); munmap(addr, d->stats.st_size); memset(p->name, 0, sizeof(p->name)); strncpy(p->magic, MAGIC_PART, MAGIC_LENGTH); strncpy(p->name, d->partition_name, sizeof(p->name)); p->index = htonl(d->partition_index); p->data_size = htonl(d->stats.st_size); p->part_size = htonl(d->partition_length); p->baseaddr = htonl(d->partition_baseaddr); p->memaddr = htonl(d->partition_memaddr); p->entryaddr = htonl(d->partition_entryaddr); crc->crc = htonl(crc32(0L, mem, d->stats.st_size + sizeof(part_t))); crc->pad = 0L; return 0; } static void usage(const char* progname) { INFO("Version %s\n" "Usage: %s [options]\n" "\t-v \t - firmware version information, default: %s\n" "\t-o \t - firmware output file, default: %s\n" "\t-m \t - firmware magic, default: %s\n" "\t-k \t\t - kernel file\n" "\t-r \t\t - rootfs file\n" "\t-B \t\t - choose firmware layout for specified board (XS2, XS5, RS, XM)\n" "\t-h\t\t\t - this help\n", VERSION, progname, DEFAULT_VERSION, DEFAULT_OUTPUT_FILE, MAGIC_HEADER); } static void print_image_info(const image_info_t* im) { int i = 0; INFO("Firmware version: '%s'\n" "Output file: '%s'\n" "Part count: %u\n", im->version, im->outputfile, im->part_count); for (i = 0; i < im->part_count; ++i) { const part_data_t* d = &im->parts[i]; INFO(" %10s: %8ld bytes (free: %8ld)\n", d->partition_name, d->stats.st_size, d->partition_length - d->stats.st_size); } } static u_int32_t filelength(const char* file) { FILE *p; int ret = -1; if ( (p = fopen(file, "rb") ) == NULL) return (-1); fseek(p, 0, SEEK_END); ret = ftell(p); fclose (p); return (ret); } static int create_image_layout(const char* kernelfile, const char* rootfsfile, char* board_name, image_info_t* im) { part_data_t* kernel = &im->parts[0]; part_data_t* rootfs = &im->parts[1]; fw_layout_t* p; p = &fw_layout_data[0]; while ((strlen(p->name) != 0) && (strncmp(p->name, board_name, sizeof(board_name)) != 0)) p++; if (p->name == NULL) { printf("BUG! Unable to find default fw layout!\n"); exit(-1); } printf("board = %s\n", p->name); strcpy(kernel->partition_name, "kernel"); kernel->partition_index = 1; kernel->partition_baseaddr = p->kern_start; if ( (kernel->partition_length = filelength(kernelfile)) < 0) return (-1); kernel->partition_memaddr = p->kern_entry; kernel->partition_entryaddr = p->kern_entry; strncpy(kernel->filename, kernelfile, sizeof(kernel->filename)); if (filelength(rootfsfile) + kernel->partition_length > p->firmware_max_length) return (-2); strcpy(rootfs->partition_name, "rootfs"); rootfs->partition_index = 2; rootfs->partition_baseaddr = kernel->partition_baseaddr + kernel->partition_length; rootfs->partition_length = p->firmware_max_length - kernel->partition_length; rootfs->partition_memaddr = 0x00000000; rootfs->partition_entryaddr = 0x00000000; strncpy(rootfs->filename, rootfsfile, sizeof(rootfs->filename)); printf("kernel: %d 0x%08x\n", kernel->partition_length, kernel->partition_baseaddr); printf("root: %d 0x%08x\n", rootfs->partition_length, rootfs->partition_baseaddr); im->part_count = 2; return 0; } /** * Checks the availability and validity of all image components. * Fills in stats member of the part_data structure. */ static int validate_image_layout(image_info_t* im) { int i; if (im->part_count == 0 || im->part_count > MAX_SECTIONS) { ERROR("Invalid part count '%d'\n", im->part_count); return -1; } for (i = 0; i < im->part_count; ++i) { part_data_t* d = &im->parts[i]; int len = strlen(d->partition_name); if (len == 0 || len > 16) { ERROR("Invalid partition name '%s' of the part %d\n", d->partition_name, i); return -1; } if (stat(d->filename, &d->stats) < 0) { ERROR("Couldn't stat file '%s' from part '%s'\n", d->filename, d->partition_name); return -2; } if (d->stats.st_size == 0) { ERROR("File '%s' from part '%s' is empty!\n", d->filename, d->partition_name); return -3; } if (d->stats.st_size > d->partition_length) { ERROR("File '%s' too big (%d) - max size: 0x%08X (exceeds %lu bytes)\n", d->filename, i, d->partition_length, d->stats.st_size - d->partition_length); return -4; } } return 0; } static int build_image(image_info_t* im) { char* mem; char* ptr; u_int32_t mem_size; FILE* f; int i; // build in-memory buffer mem_size = sizeof(header_t) + sizeof(signature_t); for (i = 0; i < im->part_count; ++i) { part_data_t* d = &im->parts[i]; mem_size += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t); } mem = (char*)calloc(mem_size, 1); if (mem == NULL) { ERROR("Cannot allocate memory chunk of size '%u'\n", mem_size); return -1; } // write header write_header(mem, im->magic, im->version); ptr = mem + sizeof(header_t); // write all parts for (i = 0; i < im->part_count; ++i) { part_data_t* d = &im->parts[i]; int rc; if ((rc = write_part(ptr, d)) != 0) { ERROR("ERROR: failed writing part %u '%s'\n", i, d->partition_name); } ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t); } // write signature write_signature(mem, mem_size - sizeof(signature_t)); // write in-memory buffer into file if ((f = fopen(im->outputfile, "w")) == NULL) { ERROR("Can not create output file: '%s'\n", im->outputfile); return -10; } if (fwrite(mem, mem_size, 1, f) != 1) { ERROR("Could not write %d bytes into file: '%s'\n", mem_size, im->outputfile); return -11; } free(mem); fclose(f); return 0; } int main(int argc, char* argv[]) { char kernelfile[PATH_MAX]; char rootfsfile[PATH_MAX]; char board_name[PATH_MAX]; int o, rc; image_info_t im; memset(&im, 0, sizeof(im)); memset(kernelfile, 0, sizeof(kernelfile)); memset(rootfsfile, 0, sizeof(rootfsfile)); memset(board_name, 0, sizeof(board_name)); strcpy(im.outputfile, DEFAULT_OUTPUT_FILE); strcpy(im.version, DEFAULT_VERSION); strncpy(im.magic, MAGIC_HEADER, sizeof(im.magic)); while ((o = getopt(argc, argv, OPTIONS)) != -1) { switch (o) { case 'v': if (optarg) strncpy(im.version, optarg, sizeof(im.version)); break; case 'o': if (optarg) strncpy(im.outputfile, optarg, sizeof(im.outputfile)); break; case 'm': if (optarg) strncpy(im.magic, optarg, sizeof(im.magic)); break; case 'h': usage(argv[0]); return -1; case 'k': if (optarg) strncpy(kernelfile, optarg, sizeof(kernelfile)); break; case 'r': if (optarg) strncpy(rootfsfile, optarg, sizeof(rootfsfile)); break; case 'B': if (optarg) strncpy(board_name, optarg, sizeof(board_name)); break; } } if (strlen(board_name) == 0) strcpy(board_name, "XS2"); /* default to XS2 */ if (strlen(kernelfile) == 0) { ERROR("Kernel file is not specified, cannot continue\n"); usage(argv[0]); return -2; } if (strlen(rootfsfile) == 0) { ERROR("Root FS file is not specified, cannot continue\n"); usage(argv[0]); return -2; } if ((rc = create_image_layout(kernelfile, rootfsfile, board_name, &im)) != 0) { ERROR("Failed creating firmware layout description - error code: %d\n", rc); return -3; } if ((rc = validate_image_layout(&im)) != 0) { ERROR("Failed validating firmware layout - error code: %d\n", rc); return -4; } print_image_info(&im); if ((rc = build_image(&im)) != 0) { ERROR("Failed building image file '%s' - error code: %d\n", im.outputfile, rc); return -5; } return 0; } ================================================ FILE: src/firmware-tools/mkfwimage2.c ================================================ /* * Copyright (C) 2007 Ubiquiti Networks, Inc. * Copyright (C) 2008 Lukas Kuna * Copyright (C) 2008 Gabor Juhos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "fw.h" #undef VERSION #define VERSION "1.2-OpenWrt.1" #define MAX_SECTIONS 8 #define DEFAULT_OUTPUT_FILE "firmware-image.bin" #define DEFAULT_VERSION "UNKNOWN" #define DEFAULT_FLASH_BASE (0xbfc00000) #define FIRMWARE_MAX_LENGTH (0x390000) typedef struct part_data { char partition_name[64]; int partition_index; u_int32_t partition_baseaddr; u_int32_t partition_offset; u_int32_t partition_memaddr; u_int32_t partition_entryaddr; u_int32_t partition_length; char filename[PATH_MAX]; struct stat stats; } part_data_t; typedef struct image_info { char version[256]; char outputfile[PATH_MAX]; char magic[MAGIC_LENGTH]; u_int32_t flash_baseaddr; u_int32_t part_count; part_data_t parts[MAX_SECTIONS]; } image_info_t; static image_info_t im; static int debug = 0; static int zero_part_baseaddr = 0; static void write_header(void* mem, const char* version) { header_t* header = mem; memset(header, 0, sizeof(header_t)); memcpy(header->magic, im.magic, MAGIC_LENGTH); strncpy(header->version, version, sizeof(header->version)); header->crc = htonl(crc32(0L, (unsigned char *)header, sizeof(header_t) - 2 * sizeof(u_int32_t))); header->pad = 0L; } static void write_signature(void* mem, u_int32_t sig_offset) { /* write signature */ signature_t* sign = (signature_t*)(mem + sig_offset); memset(sign, 0, sizeof(signature_t)); memcpy(sign->magic, MAGIC_END, MAGIC_LENGTH); sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset)); sign->pad = 0L; } static int write_part(void* mem, part_data_t* d) { char* addr; int fd; part_t* p = mem; part_crc_t* crc = mem + sizeof(part_t) + d->stats.st_size; fd = open(d->filename, O_RDONLY); if (fd < 0) { ERROR("Failed opening file '%s'\n", d->filename); return -1; } if ((addr=(char*)mmap(0, d->stats.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { ERROR("Failed mmaping memory for file '%s'\n", d->filename); close(fd); return -2; } memcpy(mem + sizeof(part_t), addr, d->stats.st_size); munmap(addr, d->stats.st_size); memset(p->name, 0, sizeof(p->name)); strncpy(p->magic, MAGIC_PART, MAGIC_LENGTH); strncpy(p->name, d->partition_name, sizeof(p->name)); p->index = htonl(d->partition_index); p->data_size = htonl(d->stats.st_size); p->part_size = htonl(d->partition_length); p->baseaddr = htonl(d->partition_baseaddr); p->memaddr = htonl(d->partition_memaddr); p->entryaddr = htonl(d->partition_entryaddr); crc->crc = htonl(crc32(0L, mem, d->stats.st_size + sizeof(part_t))); crc->pad = 0L; return 0; } static void usage(const char* progname) { INFO("Version %s\n" "Usage: %s [options]\n" "\t-v \t - firmware version information, default: %s\n" "\t-m \t\t - firmware magic, default: %s\n" "\t-f \t\t - flash base address, default: 0x%08x\n" "\t-o \t - firmware output file, default: %s\n" "\t-p :::::\n " "\t\t\t\t - create a partition from \n" "\t-z\t\t\t - set partition offsets to zero\n" "\t-h\t\t\t - this help\n", VERSION, progname, DEFAULT_VERSION, MAGIC_HEADER, DEFAULT_FLASH_BASE, DEFAULT_OUTPUT_FILE); } static void print_image_info(void) { int i; INFO("Firmware version : '%s'\n" "Output file : '%s'\n" "Part count : %u\n", im.version, im.outputfile, im.part_count); for (i = 0; i < im.part_count; ++i) { const part_data_t* d = &im.parts[i]; INFO(" %10s: %08x %08x %08x %08x %8ld bytes (free: %8ld)\n", d->partition_name, d->partition_baseaddr, d->partition_length, d->partition_entryaddr, d->partition_memaddr, d->stats.st_size, d->partition_length - d->stats.st_size); } } static int filelength(const char* file) { FILE *p; int ret = -1; if ( (p = fopen(file, "rb") ) == NULL) return (-1); fseek(p, 0, SEEK_END); ret = ftell(p); fclose (p); return (ret); } int str2u32(char *arg, u_int32_t *val) { char *err = NULL; uint32_t t; errno = 0; t = strtoul(arg, &err, 0); if (errno || (err == arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } static int image_layout_add_partition(const char *part_desc) { part_data_t *d; char memaddr[16]; char entryaddr[16]; char offset[16]; char length[16]; int t; if (im.part_count >= MAX_SECTIONS) { ERROR("Too many partitions specified\n"); return (-1); } d = &im.parts[im.part_count]; t = sscanf(part_desc, "%15[a-zA-Z]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%15[0-9a-fA-Fx]:%256s", d->partition_name, offset, length, memaddr, entryaddr, d->filename); if (t != 6) { ERROR("Bad partition parameter %d, '%s'\n", t, part_desc); return (-1); } if (strlen(d->partition_name) == 0) { ERROR("No partition name specified in '%s'\n", part_desc); return (-1); } if (str2u32(offset, &d->partition_offset)) { ERROR("Bad offset value '%s'\n", offset); return (-1); } if (str2u32(length, &d->partition_length)) { ERROR("Bad length value '%s'\n", length); return (-1); } if (d->partition_length == 0) { int flen; flen = filelength(d->filename); if (flen < 0) { ERROR("Unable to determine size of '%s'\n", d->filename); return (-1); } d->partition_length = flen; } if (str2u32(memaddr, &d->partition_memaddr)) { ERROR("Bad memaddr vaule '%s'\n", memaddr); return (-1); } if (str2u32(entryaddr, &d->partition_entryaddr)) { ERROR("Bad entry address value '%s'\n", entryaddr); return (-1); } im.part_count++; d->partition_index = im.part_count; return 0; } static int image_layout_verify(void) { u_int32_t offset; int i; if (im.part_count == 0) { ERROR("No partitions specified\n"); return -1; } offset = im.parts[0].partition_offset; for (i = 0; i < im.part_count; i++) { part_data_t* d = &im.parts[i]; if (stat(d->filename, &d->stats) < 0) { ERROR("Couldn't stat file '%s' from part '%s'\n", d->filename, d->partition_name); return -2; } if (d->stats.st_size == 0) { ERROR("File '%s' from part '%s' is empty!\n", d->filename, d->partition_name); return -3; } if (d->stats.st_size > d->partition_length) { ERROR("File '%s' too big (%d) - max size: 0x%08X (exceeds %lu bytes)\n", d->filename, i, d->partition_length, d->stats.st_size - d->partition_length); return -4; } if (d->partition_offset < offset) d->partition_offset = offset; if (zero_part_baseaddr) { d->partition_baseaddr = 0; } else { d->partition_baseaddr = im.flash_baseaddr + d->partition_offset; } offset += d->partition_length; } return 0; } static int build_image(void) { char* mem; char* ptr; u_int32_t mem_size; FILE* f; int i; /* build in-memory buffer */ mem_size = sizeof(header_t) + sizeof(signature_t); for (i = 0; i < im.part_count; ++i) { part_data_t* d = &im.parts[i]; mem_size += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t); } mem = (char*)calloc(mem_size, 1); if (mem == NULL) { ERROR("Cannot allocate memory chunk of size '%u'\n", mem_size); return -1; } /* write header */ write_header(mem, im.version); ptr = mem + sizeof(header_t); /* write all parts */ for (i = 0; i < im.part_count; ++i) { part_data_t* d = &im.parts[i]; int rc; if ((rc = write_part(ptr, d)) != 0) { ERROR("ERROR: failed writing part %u '%s'\n", i, d->partition_name); return -1; } ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t); } /* write signature */ write_signature(mem, mem_size - sizeof(signature_t)); /* write in-memory buffer into file */ if ((f = fopen(im.outputfile, "w")) == NULL) { ERROR("Can not create output file: '%s'\n", im.outputfile); return -10; } if (fwrite(mem, mem_size, 1, f) != 1) { ERROR("Could not write %d bytes into file: '%s'\n", mem_size, im.outputfile); return -11; } free(mem); fclose(f); return 0; } int main(int argc, char* argv[]) { int o, rc; memset(&im, 0, sizeof(im)); strcpy(im.outputfile, DEFAULT_OUTPUT_FILE); strcpy(im.version, DEFAULT_VERSION); memcpy(im.magic, MAGIC_HEADER, MAGIC_LENGTH); im.flash_baseaddr = DEFAULT_FLASH_BASE; while ((o = getopt(argc, argv, "f:hm:o:p:v:z")) != -1) { switch (o) { case 'f': if (optarg) if (str2u32(optarg, &im.flash_baseaddr)) { ERROR("Invalid flash start address %s\n", optarg); return -1; } break; case 'h': usage(argv[0]); return -1; case 'm': if (optarg) { if (strlen(optarg) != MAGIC_LENGTH) { ERROR("Invalid magic %s\n", optarg); return -1; } memcpy(im.magic, optarg, MAGIC_LENGTH); } break; case 'o': if (optarg) strncpy(im.outputfile, optarg, sizeof(im.outputfile)); break; case 'p': if (optarg) { if (image_layout_add_partition(optarg)) return -1; } break; case 'v': if (optarg) strncpy(im.version, optarg, sizeof(im.version)); break; case 'z': zero_part_baseaddr = 1; break; } } rc = image_layout_verify(); if (rc) { ERROR("Failed validating firmware layout - error code: %d\n", rc); return -4; } print_image_info(); rc = build_image(); if (rc) { ERROR("Failed building image file '%s' - error code: %d\n", im.outputfile, rc); return -5; } return 0; } ================================================ FILE: src/firmware-tools/mkmylofw.c ================================================ /* * Copyright (C) 2006-2008 Gabor Juhos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include /* for __BYTE_ORDER */ #if defined(__CYGWIN__) # include #endif #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) #else # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) #endif #include "myloader.h" #define MAX_FW_BLOCKS 32 #define MAX_ARG_COUNT 32 #define MAX_ARG_LEN 1024 #define FILE_BUF_LEN (16*1024) #define PART_NAME_LEN 32 struct fw_block { uint32_t addr; uint32_t blocklen; /* length of the block */ uint32_t flags; char *name; /* name of the file */ uint32_t size; /* length of the file */ uint32_t crc; /* crc value of the file */ }; struct fw_part { struct mylo_partition mylo; char name[PART_NAME_LEN]; }; #define BLOCK_FLAG_HAVEHDR 0x0001 struct cpx_board { char *model; /* model number*/ char *name; /* model name*/ char *desc; /* description */ uint16_t vid; /* vendor id */ uint16_t did; /* device id */ uint16_t svid; /* sub vendor id */ uint16_t sdid; /* sub device id */ uint32_t flash_size; /* size of flash */ uint32_t part_offset; /* offset of the partition_table */ uint32_t part_size; /* size of the partition_table */ }; #define BOARD(_vid, _did, _svid, _sdid, _flash, _mod, _name, _desc, _po, _ps) { \ .model = _mod, .name = _name, .desc = _desc, \ .vid = _vid, .did = _did, .svid = _svid, .sdid = _sdid, \ .flash_size = (_flash << 20), \ .part_offset = _po, .part_size = _ps } #define CPX_BOARD(_did, _flash, _mod, _name, _desc, _po, _ps) \ BOARD(VENID_COMPEX, _did, VENID_COMPEX, _did, _flash, _mod, _name, _desc, _po, _ps) #define CPX_BOARD_ADM(_did, _flash, _mod, _name, _desc) \ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x10000, 0x10000) #define CPX_BOARD_AR71XX(_did, _flash, _mod, _name, _desc) \ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x20000, 0x8000) #define CPX_BOARD_AR23XX(_did, _flash, _mod, _name, _desc) \ CPX_BOARD(_did, _flash, _mod, _name, _desc, 0x10000, 0x10000) #define ALIGN(x,y) ((x)+((y)-1)) & ~((y)-1) char *progname; char *ofname = NULL; uint32_t flash_size = 0; int fw_num_partitions = 0; int fw_num_blocks = 0; int verblevel = 0; struct mylo_fw_header fw_header; struct fw_part fw_parts[MYLO_MAX_PARTITIONS]; struct fw_block fw_blocks[MAX_FW_BLOCKS]; struct cpx_board *board; struct cpx_board boards[] = { CPX_BOARD_ADM(DEVID_COMPEX_NP18A, 4, "NP18A", "Compex NetPassage 18A", "Dualband Wireless A+G Internet Gateway"), CPX_BOARD_ADM(DEVID_COMPEX_NP26G8M, 2, "NP26G8M", "Compex NetPassage 26G (8M)", "Wireless-G Broadband Multimedia Gateway"), CPX_BOARD_ADM(DEVID_COMPEX_NP26G16M, 4, "NP26G16M", "Compex NetPassage 26G (16M)", "Wireless-G Broadband Multimedia Gateway"), CPX_BOARD_ADM(DEVID_COMPEX_NP27G, 4, "NP27G", "Compex NetPassage 27G", "Wireless-G 54Mbps eXtended Range Router"), CPX_BOARD_ADM(DEVID_COMPEX_NP28G, 4, "NP28G", "Compex NetPassage 28G", "Wireless 108Mbps Super-G XR Multimedia Router with 4 USB Ports"), CPX_BOARD_ADM(DEVID_COMPEX_NP28GHS, 4, "NP28GHS", "Compex NetPassage 28G (HotSpot)", "HotSpot Solution"), CPX_BOARD_ADM(DEVID_COMPEX_WP18, 4, "WP18", "Compex NetPassage WP18", "Wireless-G 54Mbps A+G Dualband Access Point"), CPX_BOARD_ADM(DEVID_COMPEX_WP54G, 4, "WP54G", "Compex WP54G", "Wireless-G 54Mbps XR Access Point"), CPX_BOARD_ADM(DEVID_COMPEX_WP54Gv1C, 2, "WP54Gv1C", "Compex WP54G rev.1C", "Wireless-G 54Mbps XR Access Point"), CPX_BOARD_ADM(DEVID_COMPEX_WP54AG, 4, "WP54AG", "Compex WP54AG", "Wireless-AG 54Mbps XR Access Point"), CPX_BOARD_ADM(DEVID_COMPEX_WPP54G, 4, "WPP54G", "Compex WPP54G", "Outdoor Access Point"), CPX_BOARD_ADM(DEVID_COMPEX_WPP54AG, 4, "WPP54AG", "Compex WPP54AG", "Outdoor Access Point"), CPX_BOARD_AR71XX(DEVID_COMPEX_WP543, 2, "WP543", "Compex WP543", "BareBoard"), CPX_BOARD_AR71XX(DEVID_COMPEX_WPE72, 8, "WPE72", "Compex WPE72", "BareBoard"), CPX_BOARD_AR23XX(DEVID_COMPEX_NP25G, 4, "NP25G", "Compex NetPassage 25G", "Wireless 54Mbps XR Router"), CPX_BOARD_AR23XX(DEVID_COMPEX_WPE53G, 4, "WPE53G", "Compex NetPassage 25G", "Wireless 54Mbps XR Access Point"), {.model = NULL} }; void errmsgv(int syserr, const char *fmt, va_list arg_ptr) { int save = errno; fflush(0); fprintf(stderr, "[%s] Error: ", progname); vfprintf(stderr, fmt, arg_ptr); if (syserr != 0) { fprintf(stderr, ": %s", strerror(save)); } fprintf(stderr, "\n"); } void errmsg(int syserr, const char *fmt, ...) { va_list arg_ptr; va_start(arg_ptr, fmt); errmsgv(syserr, fmt, arg_ptr); va_end(arg_ptr); } void dbgmsg(int level, const char *fmt, ...) { va_list arg_ptr; if (verblevel >= level) { fflush(0); va_start(arg_ptr, fmt); vfprintf(stderr, fmt, arg_ptr); fprintf(stderr, "\n"); va_end(arg_ptr); } } void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct cpx_board *board; fprintf(stream, "Usage: %s [OPTION...] \n", progname); fprintf(stream, "\n" " write output to the \n" "\n" "Options:\n" " -B create firmware for the board specified with .\n" " This option set vendor id, device id, subvendor id,\n" " subdevice id, and flash size options to the right value.\n" " valid values:\n"); for (board = boards; board->model != NULL; board++){ fprintf(stream, " %-12s: %s\n", board->model, board->name); }; fprintf(stream, " -i :[:[:]]\n" " create firmware for board with vendor id , device\n" " id , subvendor id and subdevice id .\n" " -r set board revision to .\n" " -s set flash size to \n" " -b :[:[]:]\n" " define block at with length of .\n" " valid values:\n" " h : add crc header before the file data.\n" " -p :[:[:[:[:]]]]\n" " add partition at , with size of to the\n" " partition table, set partition name to , partition \n" " flags to and partition parameter to .\n" " If the is specified content of the file will be \n" " added to the firmware image.\n" " valid values:\n" " a: this is the active partition. The bootloader loads\n" " the firmware from this partition.\n" " h: the partition data have a header.\n" " l: the partition data uses LZMA compression.\n" " p: the bootloader loads data from this partition to\n" " the RAM before decompress it.\n" " -h show this screen\n" ); exit(status); } /* * Code to compute the CRC-32 table. Borrowed from * gzip-1.0.3/makecrc.c. */ static uint32_t crc_32_tab[256]; void init_crc_table(void) { /* Not copyrighted 1990 Mark Adler */ uint32_t c; /* crc shift register */ uint32_t e; /* polynomial exclusive-or pattern */ int i; /* counter for all possible eight bit values */ int k; /* byte being shifted into crc apparatus */ /* terms of polynomial defining this crc (except x^32): */ static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* Make exclusive-or pattern from polynomial */ e = 0; for (i = 0; i < sizeof(p)/sizeof(int); i++) e |= 1L << (31 - p[i]); crc_32_tab[0] = 0; for (i = 1; i < 256; i++) { c = 0; for (k = i | 256; k != 1; k >>= 1) { c = c & 1 ? (c >> 1) ^ e : c >> 1; if (k & 1) c ^= e; } crc_32_tab[i] = c; } } void update_crc(uint8_t *p, uint32_t len, uint32_t *crc) { uint32_t t; t = *crc ^ 0xFFFFFFFFUL; while (len--) { t = crc_32_tab[(t ^ *p++) & 0xff] ^ (t >> 8); } *crc = t ^ 0xFFFFFFFFUL; } uint32_t get_crc(uint8_t *p, uint32_t len) { uint32_t crc; crc = 0; update_crc(p ,len , &crc); return crc; } int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } int str2u16(char *arg, uint16_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) { return -1; } *val = t & 0xFFFF; return 0; } struct cpx_board * find_board(char *model){ struct cpx_board *board; struct cpx_board *tmp; board = NULL; for (tmp = boards; tmp->model != NULL; tmp++){ if (strcasecmp(model, tmp->model) == 0) { board = tmp; break; } }; return board; } int get_file_crc(struct fw_block *ff) { FILE *f; uint8_t buf[FILE_BUF_LEN]; uint32_t readlen = sizeof(buf); int res = -1; size_t len; if ((ff->flags & BLOCK_FLAG_HAVEHDR) == 0) { res = 0; goto out; } errno = 0; f = fopen(ff->name,"r"); if (errno) { errmsg(1,"unable to open file %s", ff->name); goto out; } ff->crc = 0; len = ff->size; while (len > 0) { if (len < readlen) readlen = len; errno = 0; fread(buf, readlen, 1, f); if (errno) { errmsg(1,"unable to read from file %s", ff->name); goto out_close; } update_crc(buf, readlen, &ff->crc); len -= readlen; } res = 0; out_close: fclose(f); out: return res; } int process_files(void) { struct fw_block *b; struct stat st; int i; for (i = 0; i < fw_num_blocks; i++) { b = &fw_blocks[i]; if ((b->addr + b->blocklen) > flash_size) { errmsg(0, "block at 0x%08X is too big", b->addr); return -1; } if (b->name == NULL) continue; if (stat(b->name, &st) < 0) { errmsg(0, "stat failed on %s",b->name); return -1; } if (b->blocklen == 0) { b->blocklen = flash_size - b->addr; } if (st.st_size > b->blocklen) { errmsg(0,"file %s is too big",b->name); return -1; } b->size = st.st_size; } return 0; } int process_partitions(void) { struct mylo_partition *part; int i; for (i = 0; i < fw_num_partitions; i++) { part = &fw_parts[i].mylo; if (part->addr > flash_size) { errmsg(0, "invalid partition at 0x%08X", part->addr); return -1; } if ((part->addr + part->size) > flash_size) { errmsg(0, "partition at 0x%08X is too big", part->addr); return -1; } } return 0; } /* * routines to write data to the output file */ int write_out_data(FILE *outfile, uint8_t *data, size_t len, uint32_t *crc) { errno = 0; fwrite(data, len, 1, outfile); if (errno) { errmsg(1,"unable to write output file"); return -1; } if (crc) { update_crc(data, len, crc); } return 0; } int write_out_desc(FILE *outfile, struct mylo_fw_blockdesc *desc, uint32_t *crc) { return write_out_data(outfile, (uint8_t *)desc, sizeof(*desc), crc); } int write_out_padding(FILE *outfile, size_t len, uint8_t padc, uint32_t *crc) { uint8_t buff[512]; size_t buflen = sizeof(buff); memset(buff, padc, buflen); while (len > 0) { if (len < buflen) buflen = len; if (write_out_data(outfile, buff, buflen, crc)) return -1; len -= buflen; } return 0; } int write_out_file(FILE *outfile, struct fw_block *block, uint32_t *crc) { char buff[FILE_BUF_LEN]; size_t buflen = sizeof(buff); FILE *f; size_t len; errno = 0; if (block->name == NULL) { return 0; } if ((block->flags & BLOCK_FLAG_HAVEHDR) != 0) { struct mylo_partition_header ph; if (get_file_crc(block) != 0) return -1; ph.crc = HOST_TO_LE32(block->crc); ph.len = HOST_TO_LE32(block->size); if (write_out_data(outfile, (uint8_t *)&ph, sizeof(ph), crc) != 0) return -1; } f = fopen(block->name,"r"); if (errno) { errmsg(1,"unable to open file: %s", block->name); return -1; } len = block->size; while (len > 0) { if (len < buflen) buflen = len; /* read data from source file */ errno = 0; fread(buff, buflen, 1, f); if (errno != 0) { errmsg(1,"unable to read from file: %s",block->name); return -1; } if (write_out_data(outfile, buff, buflen, crc) != 0) return -1; len -= buflen; } fclose(f); /* align next block on a 4 byte boundary */ len = ALIGN(len,4) - block->size; if (write_out_padding(outfile, len, 0xFF, crc)) return -1; dbgmsg(1,"file %s written out", block->name); return 0; } int write_out_header(FILE *outfile, uint32_t *crc) { struct mylo_fw_header hdr; memset(&hdr, 0, sizeof(hdr)); hdr.magic = HOST_TO_LE32(MYLO_MAGIC_FIRMWARE); hdr.crc = HOST_TO_LE32(fw_header.crc); hdr.vid = HOST_TO_LE16(fw_header.vid); hdr.did = HOST_TO_LE16(fw_header.did); hdr.svid = HOST_TO_LE16(fw_header.svid); hdr.sdid = HOST_TO_LE16(fw_header.sdid); hdr.rev = HOST_TO_LE32(fw_header.rev); hdr.fwhi = HOST_TO_LE32(fw_header.fwhi); hdr.fwlo = HOST_TO_LE32(fw_header.fwlo); hdr.flags = HOST_TO_LE32(fw_header.flags); if (fseek(outfile, 0, SEEK_SET) != 0) { errmsg(1,"fseek failed on output file"); return -1; } return write_out_data(outfile, (uint8_t *)&hdr, sizeof(hdr), crc); } int write_out_partitions(FILE *outfile, uint32_t *crc) { struct mylo_partition_table p; char part_names[MYLO_MAX_PARTITIONS][PART_NAME_LEN]; int ret; int i; if (fw_num_partitions == 0) return 0; memset(&p, 0, sizeof(p)); memset(part_names, 0, sizeof(part_names)); p.magic = HOST_TO_LE32(MYLO_MAGIC_PARTITIONS); for (i = 0; i < fw_num_partitions; i++) { struct mylo_partition *mp; struct fw_part *fp; mp = &p.partitions[i]; fp = &fw_parts[i]; mp->flags = HOST_TO_LE16(fp->mylo.flags); mp->type = HOST_TO_LE16(PARTITION_TYPE_USED); mp->addr = HOST_TO_LE32(fp->mylo.addr); mp->size = HOST_TO_LE32(fp->mylo.size); mp->param = HOST_TO_LE32(fp->mylo.param); memcpy(part_names[i], fp->name, PART_NAME_LEN); } ret = write_out_data(outfile, (uint8_t *)&p, sizeof(p), crc); if (ret) return ret; ret = write_out_data(outfile, (uint8_t *)part_names, sizeof(part_names), crc); return ret; } int write_out_blocks(FILE *outfile, uint32_t *crc) { struct mylo_fw_blockdesc desc; struct fw_block *b; uint32_t dlen; int i; /* * if at least one partition specified, write out block descriptor * for the partition table */ if (fw_num_partitions > 0) { desc.type = HOST_TO_LE32(FW_DESC_TYPE_USED); desc.addr = HOST_TO_LE32(board->part_offset); desc.dlen = HOST_TO_LE32(sizeof(struct mylo_partition_table) + (MYLO_MAX_PARTITIONS * PART_NAME_LEN)); desc.blen = HOST_TO_LE32(board->part_size); if (write_out_desc(outfile, &desc, crc) != 0) return -1; } /* * write out block descriptors for each files */ for (i = 0; i < fw_num_blocks; i++) { b = &fw_blocks[i]; /* detect block size */ dlen = b->size; if ((b->flags & BLOCK_FLAG_HAVEHDR) != 0) { dlen += sizeof(struct mylo_partition_header); } /* round up to 4 bytes */ dlen = ALIGN(dlen, 4); /* setup the descriptor */ desc.type = HOST_TO_LE32(FW_DESC_TYPE_USED); desc.addr = HOST_TO_LE32(b->addr); desc.dlen = HOST_TO_LE32(dlen); desc.blen = HOST_TO_LE32(b->blocklen); if (write_out_desc(outfile, &desc, crc) != 0) return -1; } /* * write out the null block descriptor */ memset(&desc, 0, sizeof(desc)); if (write_out_desc(outfile, &desc, crc) != 0) return -1; if (write_out_partitions(outfile, crc) != 0) return -1; /* * write out data for each blocks */ for (i = 0; i < fw_num_blocks; i++) { b = &fw_blocks[i]; if (write_out_file(outfile, b, crc) != 0) return -1; } return 0; } /* * argument parsing */ int parse_arg(char *arg, char *buf, char *argv[]) { int res = 0; size_t argl; char *tok; char **ap = &buf; int i; if ((arg == NULL)) { /* invalid argument string */ return -1; } argl = strlen(arg); if (argl == 0) { /* no arguments */ return res; } if (argl >= MAX_ARG_LEN) { /* argument is too long */ argl = MAX_ARG_LEN-1; } memset(argv, 0, MAX_ARG_COUNT * sizeof(void *)); memcpy(buf, arg, argl); buf[argl] = '\0'; for (i = 0; i < MAX_ARG_COUNT; i++) { tok = strsep(ap, ":"); if (tok == NULL) { break; } #if 0 else if (tok[0] == '\0') { break; } #endif argv[i] = tok; res++; } return res; } int required_arg(char c, char *arg) { if ((optarg != NULL) && (*arg == '-')){ errmsg(0,"option %c requires an argument\n", c); return -1; } return 0; } int is_empty_arg(char *arg) { int ret = 1; if (arg != NULL) { if (*arg) ret = 0; }; return ret; } int parse_opt_flags(char ch, char *arg) { if (required_arg(ch, arg)) { goto err_out; } if (str2u32(arg, &fw_header.flags) != 0) { errmsg(0,"invalid firmware flags: %s", arg); goto err_out; } dbgmsg(1, "firmware flags set to %X bytes", fw_header.flags); return 0; err_out: return -1; } int parse_opt_size(char ch, char *arg) { if (required_arg(ch, arg)) { goto err_out; } if (str2u32(arg, &flash_size) != 0) { errmsg(0,"invalid flash size: %s", arg); goto err_out; } dbgmsg(1, "flash size set to %d bytes", flash_size); return 0; err_out: return -1; } int parse_opt_id(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; if (required_arg(ch, arg)) { goto err_out; } argc = parse_arg(arg, buf, argv); /* processing vendor ID*/ p = argv[0]; if (is_empty_arg(p)) { errmsg(0,"vendor id is missing from -%c %s",ch, arg); goto err_out; } else if (str2u16(p, &fw_header.vid) != 0) { errmsg(0,"invalid vendor id: %s", p); goto err_out; } dbgmsg(1, "vendor id is set to 0x%04X", fw_header.vid); /* processing device ID*/ p = argv[1]; if (is_empty_arg(p)) { errmsg(0,"device id is missing from -%c %s",ch, arg); goto err_out; } else if (str2u16(p, &fw_header.did) != 0) { errmsg(0,"invalid device id: %s", p); goto err_out; } dbgmsg(1, "device id is set to 0x%04X", fw_header.did); /* processing sub vendor ID*/ p = argv[2]; if (is_empty_arg(p)) { fw_header.svid = fw_header.vid; } else if (str2u16(p, &fw_header.svid) != 0) { errmsg(0,"invalid sub vendor id: %s", p); goto err_out; } dbgmsg(1, "sub vendor id is set to 0x%04X", fw_header.svid); /* processing device ID*/ p = argv[3]; if (is_empty_arg(p)) { fw_header.sdid = fw_header.did; } else if (str2u16(p, &fw_header.sdid) != 0) { errmsg(0,"invalid sub device id: %s", p); goto err_out; } dbgmsg(1, "sub device id is set to 0x%04X", fw_header.sdid); /* processing revision */ p = argv[4]; if (is_empty_arg(p)) { fw_header.rev = 0; } else if (str2u32(arg, &fw_header.rev) != 0) { errmsg(0,"invalid revision number: %s", p); goto err_out; } dbgmsg(1, "board revision is set to 0x%08X", fw_header.rev); return 0; err_out: return -1; } int parse_opt_block(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; struct fw_block *b; char *p; if (required_arg(ch, arg)) { goto err_out; } if (fw_num_blocks >= MAX_FW_BLOCKS) { errmsg(0,"too many blocks specified"); goto err_out; } argc = parse_arg(arg, buf, argv); dbgmsg(1,"processing block option %s, count %d", arg, argc); b = &fw_blocks[fw_num_blocks++]; /* processing block address */ p = argv[0]; if (is_empty_arg(p)) { errmsg(0,"no block address specified in %s", arg); goto err_out; } else if (str2u32(p, &b->addr) != 0) { errmsg(0,"invalid block address: %s", p); goto err_out; } /* processing block length */ p = argv[1]; if (is_empty_arg(p)) { errmsg(0,"no block length specified in %s", arg); goto err_out; } else if (str2u32(p, &b->blocklen) != 0) { errmsg(0,"invalid block length: %s", p); goto err_out; } if (argc < 3) { dbgmsg(1,"empty block %s", arg); goto success; } /* processing flags */ p = argv[2]; if (is_empty_arg(p) == 0) { for ( ; *p != '\0'; p++) { switch (*p) { case 'h': b->flags |= BLOCK_FLAG_HAVEHDR; break; default: errmsg(0, "invalid block flag \"%c\"", *p); goto err_out; } } } /* processing file name */ p = argv[3]; if (is_empty_arg(p)) { errmsg(0,"file name missing in %s", arg); goto err_out; } b->name = strdup(p); if (b->name == NULL) { errmsg(0,"not enough memory"); goto err_out; } success: return 0; err_out: return -1; } int parse_opt_partition(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; struct mylo_partition *part; struct fw_part *fp; if (required_arg(ch, arg)) { goto err_out; } if (fw_num_partitions >= MYLO_MAX_PARTITIONS) { errmsg(0, "too many partitions specified"); goto err_out; } fp = &fw_parts[fw_num_partitions++]; part = &fp->mylo; argc = parse_arg(arg, buf, argv); /* processing partition address */ p = argv[0]; if (is_empty_arg(p)) { errmsg(0,"partition address missing in -%c %s",ch, arg); goto err_out; } else if (str2u32(p, &part->addr) != 0) { errmsg(0,"invalid partition address: %s", p); goto err_out; } /* processing partition size */ p = argv[1]; if (is_empty_arg(p)) { errmsg(0,"partition size missing in -%c %s",ch, arg); goto err_out; } else if (str2u32(p, &part->size) != 0) { errmsg(0,"invalid partition size: %s", p); goto err_out; } /* processing partition flags */ p = argv[2]; if (is_empty_arg(p) == 0) { for ( ; *p != '\0'; p++) { switch (*p) { case 'a': part->flags |= PARTITION_FLAG_ACTIVE; break; case 'p': part->flags |= PARTITION_FLAG_PRELOAD; break; case 'l': part->flags |= PARTITION_FLAG_LZMA; break; case 'h': part->flags |= PARTITION_FLAG_HAVEHDR; break; default: errmsg(0, "invalid partition flag \"%c\"", *p); goto err_out; } } } /* processing partition parameter */ p = argv[3]; if (is_empty_arg(p)) { /* set default partition parameter */ part->param = 0; } else if (str2u32(p, &part->param) != 0) { errmsg(0,"invalid partition parameter: %s", p); goto err_out; } p = argv[4]; if (is_empty_arg(p)) { /* set default partition parameter */ fp->name[0] = '\0'; } else { strncpy(fp->name, p, PART_NAME_LEN); } #if 1 if (part->size == 0) { part->size = flash_size - part->addr; } /* processing file parameter */ p = argv[5]; if (is_empty_arg(p) == 0) { struct fw_block *b; if (fw_num_blocks == MAX_FW_BLOCKS) { errmsg(0,"too many blocks specified", p); goto err_out; } b = &fw_blocks[fw_num_blocks++]; b->name = strdup(p); b->addr = part->addr; b->blocklen = part->size; if (part->flags & PARTITION_FLAG_HAVEHDR) { b->flags |= BLOCK_FLAG_HAVEHDR; } } #endif return 0; err_out: return -1; } int parse_opt_board(char ch, char *arg) { if (required_arg(ch, arg)) { goto err_out; } board = find_board(arg); if (board == NULL){ errmsg(0,"invalid/unknown board specified: %s", arg); goto err_out; } fw_header.vid = board->vid; fw_header.did = board->did; fw_header.svid = board->svid; fw_header.sdid = board->sdid; flash_size = board->flash_size; return 0; err_out: return -1; } int parse_opt_rev(char ch, char *arg) { if (required_arg(ch, arg)) { return -1; } if (str2u32(arg, &fw_header.rev) != 0) { errmsg(0,"invalid revision number: %s", arg); return -1; } return 0; } /* * main */ int main(int argc, char *argv[]) { int optinvalid = 0; /* flag for invalid option */ int c; int res = EXIT_FAILURE; FILE *outfile; uint32_t crc; progname=basename(argv[0]); memset(&fw_header, 0, sizeof(fw_header)); /* init header defaults */ fw_header.vid = VENID_COMPEX; fw_header.did = DEVID_COMPEX_WP54G; fw_header.svid = VENID_COMPEX; fw_header.sdid = DEVID_COMPEX_WP54G; fw_header.fwhi = 0x20000; fw_header.fwlo = 0x20000; fw_header.flags = 0; opterr = 0; /* could not print standard getopt error messages */ while ((c = getopt(argc, argv, "b:B:f:hi:p:r:s:v")) != -1) { optinvalid = 0; switch (c) { case 'b': optinvalid = parse_opt_block(c,optarg); break; case 'B': optinvalid = parse_opt_board(c,optarg); break; case 'f': optinvalid = parse_opt_flags(c,optarg); break; case 'h': usage(EXIT_SUCCESS); break; case 'i': optinvalid = parse_opt_id(c,optarg); break; case 'p': optinvalid = parse_opt_partition(c,optarg); break; case 'r': optinvalid = parse_opt_rev(c,optarg); break; case 's': optinvalid = parse_opt_size(c,optarg); break; case 'v': verblevel++; break; default: optinvalid = 1; break; } if (optinvalid != 0 ){ errmsg(0, "invalid option: -%c", optopt); goto out; } } if (optind == argc) { errmsg(0, "no output file specified"); goto out; } ofname = argv[optind++]; if (optind < argc) { errmsg(0, "invalid option: %s", argv[optind]); goto out; } if (!board) { errmsg(0, "no board specified"); goto out; } if (flash_size == 0) { errmsg(0, "no flash size specified"); goto out; } if (process_files() != 0) { goto out; } if (process_partitions() != 0) { goto out; } outfile = fopen(ofname, "w"); if (outfile == NULL) { errmsg(1, "could not open \"%s\" for writing", ofname); goto out; } crc = 0; init_crc_table(); if (write_out_header(outfile, &crc) != 0) goto out_flush; if (write_out_blocks(outfile, &crc) != 0) goto out_flush; fw_header.crc = crc; if (write_out_header(outfile, NULL) != 0) goto out_flush; dbgmsg(1,"Firmware file %s completed.", ofname); res = EXIT_SUCCESS; out_flush: fflush(outfile); fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } out: return res; } ================================================ FILE: src/firmware-tools/mkplanexfw.c ================================================ /* * Copyright (C) 2009 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include "sha1.h" #if (__BYTE_ORDER == __BIG_ENDIAN) # define HOST_TO_BE32(x) (x) # define BE32_TO_HOST(x) (x) #else # define HOST_TO_BE32(x) bswap_32(x) # define BE32_TO_HOST(x) bswap_32(x) #endif struct planex_hdr { uint8_t sha1sum[20]; char version[8]; uint8_t unk1[2]; uint32_t datalen; } __attribute__ ((packed)); struct board_info { char *id; uint32_t seed; uint8_t unk[2]; uint32_t datalen; }; /* * Globals */ static char *ifname; static char *progname; static char *ofname; static char *version = "1.00.00"; static char *board_id; static struct board_info *board; static struct board_info boards[] = { { .id = "MZK-W04NU", .seed = 2, .unk = {0x04, 0x08}, .datalen = 0x770000, }, { .id = "MZK-W300NH", .seed = 4, .unk = {0x00, 0x00}, .datalen = 0x770000, }, { /* terminating entry */ } }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) static struct board_info *find_board(char *id) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->id != NULL; board++){ if (strcasecmp(id, board->id) == 0) { ret = board; break; } }; return ret; } void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with \n" " -i read input from the file \n" " -o write output to the file \n" " -v set image version to \n" " -h show this screen\n" ); exit(status); } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int buflen; int err; struct stat st; char *buf; struct planex_hdr *hdr; sha1_context ctx; uint32_t seed; FILE *outfile, *infile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "B:i:o:v:h"); if (c == -1) break; switch (c) { case 'B': board_id = optarg; break; case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 'v': version = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } if (board_id == NULL) { ERR("no board specified"); goto err; } board = find_board(board_id); if (board == NULL) { ERR("unknown board '%s'", board_id); goto err; }; if (ifname == NULL) { ERR("no input file specified"); goto err; } if (ofname == NULL) { ERR("no output file specified"); goto err; } err = stat(ifname, &st); if (err){ ERRS("stat failed on %s", ifname); goto err; } if (st.st_size > board->datalen) { ERR("file '%s' is too big - max size: 0x%08X (exceeds %lu bytes)\n", ifname, board->datalen, st.st_size - board->datalen); goto err; } buflen = board->datalen + 0x10000; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto err; } memset(buf, 0xff, buflen); hdr = (struct planex_hdr *)buf; hdr->datalen = HOST_TO_BE32(board->datalen); hdr->unk1[0] = board->unk[0]; hdr->unk1[1] = board->unk[1]; snprintf(hdr->version, sizeof(hdr->version), "%s", version); infile = fopen(ifname, "r"); if (infile == NULL) { ERRS("could not open \"%s\" for reading", ifname); goto err_free; } errno = 0; fread(buf + sizeof(*hdr), st.st_size, 1, infile); if (errno != 0) { ERRS("unable to read from file %s", ifname); goto err_close_in; } seed = HOST_TO_BE32(board->seed); sha1_starts(&ctx); sha1_update(&ctx, (uchar *) &seed, sizeof(seed)); sha1_update(&ctx, buf + sizeof(*hdr), board->datalen); sha1_finish(&ctx, hdr->sha1sum); outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto err_close_in; } errno = 0; fwrite(buf, buflen, 1, outfile); if (errno) { ERRS("unable to write to file %s", ofname); goto err_close_out; } res = EXIT_SUCCESS; out_flush: fflush(outfile); err_close_out: fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } err_close_in: fclose(infile); err_free: free(buf); err: return res; } ================================================ FILE: src/firmware-tools/mktitanimg.c ================================================ #include #include #include #include #include "mktitanimg.h" struct checksumrecord { unsigned int magic; unsigned int chksum; /* The checksum for the complete header. Excepting the checksum block */ }; /*************************************************************************** * void print_help(void) ***************************************************************************/ void print_help(void) { static char* help_page[]= { "mknspimg version 1.0, Texas Instruments, 2004", "Syntax:", " mknspimg -o outfile -i image1 image2 -a align1 align2 [-v] [-b] [-p prod_id] [-r rel_id] [-s rel_name] [-f flags]", "Example:", " mknspimg -o nsp_image.bin -i kernel.bin files.img -a 0 4096", "This generates 'nsp_image.bin' from two input files aligning first to 0 and second to 4096 bytes." }; int num_lines = sizeof(help_page)/sizeof(char*); int i; for(i=0; i < num_lines; i++) { printf("%s\n", help_page[i]); } } /*************************************************************************** * void mknspimg_print_hdr(NSP_IMG_HDR* p_img_hdr) ***************************************************************************/ void mknspimg_print_hdr(struct nsp_img_hdr *hdr) { struct nsp_img_hdr_chksum *chksum; struct nsp_img_hdr_section_info *sect_info; struct nsp_img_hdr_sections *section; int i; printf("****************** NSP Image Summary ******************\n"); printf("Magic: 0x%x\n", hdr->head.magic); printf("Image Header Size: 0x%x bytes\n", hdr->head.hdr_size); printf("Total Image Size: %d bytes\n", hdr->head.image_size); printf("Product ID: 0x%x\n", hdr->head.prod_id); printf("Release ID: 0x%x\n", hdr->head.rel_id); printf("Version ID: 0x%x\n", hdr->head.version); printf("Offset Info: 0x%x\n", hdr->head.info_offset); printf("Offset Sect info: 0x%x\n", hdr->head.sect_info_offset); printf("Offset Sections: 0x%x\n", hdr->sect_info.sections_offset); chksum=(struct nsp_img_hdr_chksum *)(hdr+hdr->head.chksum_offset); printf("Header Checksum: 0x%x\n", chksum->hdr_chksum); printf("+++ Section Information +++\n"); printf("# of sections: %u\n", hdr->sect_info.num_sects); section=&(hdr->sections); for(i = 0; i < hdr->sect_info.num_sects; i++, section++) { printf("+++++ Section %d +++++\n", i); printf("Total size: %u bytes\n", section->total_size); printf("Raw Size: %u bytes\n", section->raw_size); printf("Offset: 0x%x\n", section->offset); printf("Type: 0x%x\n", section->type); printf("Name: %s\n", section->name); } printf("*******************************************************\n"); } CMDLINE_CFG cmd_line_cfg = { { /* MIN MAX FLAGS OPTION */ { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-a' align1 align2 */ { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-b' bootstrap */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-c' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-d' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-e' */ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-f' flags */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-g' */ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-h' */ { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-i arg1 arg2 ' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-j' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-k' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-l' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-m' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-n' */ { 1, 1, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-o arg' */ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-p' PROD_ID */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-q' */ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-r' REL_ID */ { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-s' "Release XXX.XXX" */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-t' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-u' */ { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-v' control VERBOSE/NON-VERBOSE mode */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-w' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-x' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-y' */ { 0, 0, !CMDLINE_OPTFLAG_ALLOW } /* '-z' */ }, { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* global arguments */ }; /*************************************************************************** * int nsp_img_write(void* image, char* file, int padding) * Write out the image. ***************************************************************************/ int main(int argc, char* argv[], char* env[]) { FILE* nsp_image = NULL; int header_version=1; int cmdline_err; char* cmdline_error_msg; char* filen_kernel; char* filen_files; char* filen_out; int i,count; /* loop variables */ int num_sects = 2; /* We require exactly two image with -i option (see CMDLINE_CFG structure above) */ int desc_count=0; int total = 0; int header_size=0; struct nsp_img_hdr_head *img_hdr_head; /* Start of image header */ struct nsp_img_hdr_info *img_hdr_info; struct nsp_img_hdr_section_info *img_hdr_section_info ; struct nsp_img_hdr_sections *img_hdr_sections, *section; /* Section pointers */ /* Configure the command line. */ cmdline_configure(&cmd_line_cfg); /* Read and parse the command line. */ cmdline_err = cmdline_read(argc, argv); /* Check for parsing errors. */ if(cmdline_err != 0) { /* Get the parse error message */ cmdline_error_msg = cmdline_error(cmdline_err); /* Print it out */ printf("%s\n", cmdline_error_msg); /* Print our help too */ print_help(); return -1; } if(cmdline_getopt_count('h') > 0) { header_version=atoi(argv[cmdline_getarg(cmdline_getarg_list('h'),0)]); } /* Set up arguments */ filen_kernel = argv[cmdline_getarg(cmdline_getarg_list('i'),0)]; filen_files = argv[cmdline_getarg(cmdline_getarg_list('i'),1)]; filen_out = argv[cmdline_getarg(cmdline_getarg_list('o'),0)]; /* Command line arguments have been parsed. Start doing our work. */ /* Caculate the header size, and allocate the memory, and assign the sub pointers */ header_size = sizeof(struct nsp_img_hdr_head) + /* This has a single section desc block already */ (header_version==1?0:4) + sizeof(struct nsp_img_hdr_info) + sizeof(struct nsp_img_hdr_section_info) + sizeof(struct nsp_img_hdr_sections) * num_sects ; img_hdr_head = (struct nsp_img_hdr_head *)malloc(header_size); memset(img_hdr_head, 0x0, header_size); img_hdr_info = (struct nsp_img_hdr_info*)((char *)img_hdr_head + sizeof(struct nsp_img_hdr_head) + (header_version==1?0:4)); img_hdr_section_info = (struct nsp_img_hdr_section_info*)((char *)img_hdr_info + sizeof(struct nsp_img_hdr_info)); img_hdr_sections = (struct nsp_img_hdr_sections*)((char *)img_hdr_section_info + sizeof(struct nsp_img_hdr_section_info)); section = img_hdr_sections; memset(img_hdr_head, 0xff, (void*)img_hdr_info - (void*)img_hdr_head); img_hdr_head->hdr_version = header_version; img_hdr_head->hdr_size = header_size; img_hdr_head->info_offset = (void*)img_hdr_info - (void*)img_hdr_head; img_hdr_head->sect_info_offset = (void*)img_hdr_section_info - (void*)img_hdr_head; img_hdr_section_info->num_sects = num_sects; img_hdr_section_info->sect_size = sizeof(struct nsp_img_hdr_sections); img_hdr_section_info->sections_offset = (void*)img_hdr_sections - (void*)img_hdr_head; /* chksum = (struct nsp_img_hdr_chksum *) ((unsigned int)image_hdr + header_size - sizeof(struct nsp_img_hdr_chksum));*/ /* Open the out file */ nsp_image = fopen(filen_out,"wb+"); if(nsp_image==NULL) { printf("ERROR: can't open %s for writing.\n", filen_out); return -1; } /* Skip image header. We'll come back to it after we've written out the images. */ fseek(nsp_image,header_size,SEEK_SET); total = ftell(nsp_image); total = header_size; printf("total=%x\n",total); { int align; int padding; char * buf; align = (header_version==1?0x10000:0x4000); if(align==0) { /* The user indicated no padding */ padding = 0; } else { /* Calculate number padding bytes */ if((total %align) ==0) padding=0; else padding = align - (total % align); } if(padding>0) { buf=malloc(padding); memset(buf, 0xff, padding); if(fwrite((void*)buf,1,padding,nsp_image)!=padding) { printf("ERROR: can't write to %s.\n", filen_out); free(buf); return -1; } free(buf); } total+=padding; } /* Write out all specified images (with -i option) */ for(i=0; i < num_sects; i++) { char* file_name; /* input file name */ FILE* filep; /* input file pointer */ int padding; /* number of padding bytes to prepend */ int align; /* align factor from command line */ int result; /* intermediate result */ char * buf; /* Open the specified image for reading */ file_name = argv[cmdline_getarg(cmdline_getarg_list('i'),i)]; filep = fopen(file_name, "rb"); if(filep==NULL) { printf("ERROR: can't open file %s for reading.\n", file_name); return -1; } section->flags = ~0x00; /* Determine file size */ fseek(filep,0,SEEK_END); section->raw_size=ftell(filep); fseek(filep,0,SEEK_SET); cs_calc_sum(filep,(unsigned long *)§ion->chksum,0); fseek(filep,0,SEEK_SET); /* Retrieve the alignment constant */ /* Set image offset from the beginning of the out file */ section->offset=total;// + padding; //total += padding; /* Copy the image file into nsp_image */ count = section->raw_size; buf=malloc(count); result=fread(buf, 1, count, filep); fwrite(buf, 1, result, nsp_image); free(buf); /* HACK: This is a hack to get the names and types to the files. TODO: Fix this to be a real method */ if(i==0){ section->type=NSP_IMG_SECTION_TYPE_KERNEL; strncpy(section->name, "kernel", 16); } else if(i==1){ section->type=NSP_IMG_SECTION_TYPE_FILESYSTEM_ROOT; strncpy(section->name, "root", 16); } /* Account for the total */ align = strtoul(argv[cmdline_getarg(cmdline_getarg_list('a'),i)],NULL,0); if(i==0){ if(align==0 || (((section->raw_size+ section->offset)%align)==0)) padding=0; else padding = align - ((section->raw_size+ section->offset) % align); section->total_size=section->raw_size + padding; } else{ #define EXTRA_BLOCK 0x10000 unsigned int squash_padding; squash_padding = EXTRA_BLOCK - section->raw_size % EXTRA_BLOCK; buf=malloc(EXTRA_BLOCK + 4); memset(buf, 0, squash_padding); fwrite(buf, 1, squash_padding, nsp_image); memset(buf, 0, EXTRA_BLOCK + 4); *((unsigned int *)buf)=0xdec0adde; *((unsigned int *)(buf+EXTRA_BLOCK))=0xdec0adde; fwrite(buf, 1, EXTRA_BLOCK+4, nsp_image); free(buf); if(align==0 || (((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) %align)==0)) padding=0; else padding = align - ((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) % align); section->total_size=section->raw_size + (EXTRA_BLOCK + 4 + squash_padding) + padding; } if(padding>0){ buf=malloc(padding); memset(buf, 0xff, padding); fwrite(buf, 1, padding, nsp_image); free(buf); } printf("*****padding is %d\ttotal_size=%d\traw_size=%d\n",padding, section->total_size, section->raw_size); //total += section->raw_size; total = section->total_size + section->offset; printf("total=0x%x\n",total); /* Close the input file */ fclose(filep); /* Move the section pointer to the next slot */ section++; } /* Take care of the NSP image header fields */ /* head fields */ img_hdr_head->magic = NSP_IMG_MAGIC_NUMBER; img_hdr_head->boot_offset = img_hdr_sections->offset; img_hdr_head->flags = ~0x00; /* Set to all 1's */ if(cmdline_getopt_count('b')) img_hdr_head->flags &= ~(NSP_IMG_FLAG_FAILBACK_5 | NSP_IMG_FLAG_FAILBACK_1); if(cmdline_getopt_count('f')) img_hdr_head->flags = strtoul(argv[cmdline_getarg(cmdline_getarg_list('f'),0)], 0, 16); #if 0 img_hdr_head->hdr_version = 2; img_hdr_head->hdr_size = header_size; #endif if(cmdline_getopt_count('p')) img_hdr_head->prod_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('p'),0)], 0, 16); else img_hdr_head->prod_id = 0x4C575943; if(cmdline_getopt_count('r')) img_hdr_head->rel_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('r'),0)], 0, 0); else img_hdr_head->rel_id = 0x10203040; if(cmdline_getopt_count('s')) img_hdr_head->version = strtoul(argv[cmdline_getarg(cmdline_getarg_list('s'),0)], 0, 0); else img_hdr_head->version = 0x0b040000; img_hdr_head->image_size = total; #if 0 img_hdr_head->info_offset = (unsigned int)(&(image_hdr->info)) - (unsigned int)image_hdr; img_hdr_head->sect_info_offset= (unsigned int)(&(image_hdr->sect_info)) - (unsigned int)image_hdr; #endif // image_hdr->head.chksum_offset = (unsigned int)chksum - (unsigned int)image_hdr; img_hdr_head->chksum_offset = 0xffffffff; // image_hdr->head.pad1 = 0xffffffff; /* info fields */ /* TODO: Fix. Do nothing yet */ // strncpy(nsp_img_hdr.id.prod_info,NSP_PRODINFO_STRING,sizeof(NSP_PRODINFO_STRING)); strcpy(img_hdr_info->image_filename, (const char *)basename(filen_out)); /* section fields */ #if 0 img_hdr_section_info->num_sects= num_sects; img_hdr_section_info->sect_size= sizeof(struct nsp_img_hdr_sections); img_hdr_section_info->sections_offset= (unsigned int)(&(image_hdr->sections)) - (unsigned int)image_hdr; #endif /* Calculate checksum(s) */ #if 0 chksum->hdr_chksum = cs_calc_buf_sum((char*)image_hdr, header_size - sizeof(struct nsp_img_hdr_chksum)); #endif /* Write out the NSP header. */ fseek(nsp_image,0,SEEK_SET); count = fwrite((void*)img_hdr_head, header_size, 1, nsp_image); if(count!=1) { printf("ERROR: can't write to %s.\n", filen_out); return -1; } /* Check if -v option was specified (no arg needed) */ if(cmdline_getopt_count('v') > 0) { struct nsp_img_hdr_head head; struct nsp_img_hdr *hdr; /* Rewind the file back to the beginning */ fseek(nsp_image,0,SEEK_SET); /* Read header from the file */ fread((void*)&head, sizeof(struct nsp_img_hdr_head), 1, nsp_image); /* Get memory to store the complete header */ hdr = (struct nsp_img_hdr *)malloc(head.hdr_size); /* Read header from the file */ fseek(nsp_image,0,SEEK_SET); fread((void*)hdr, head.hdr_size, 1, nsp_image); /* Print it out */ mknspimg_print_hdr(hdr); printf("Generated total %d bytes\n",total); free(hdr); } free(img_hdr_head); { struct checksumrecord cr; cr.magic=CKSUM_MAGIC_NUMBER; cs_calc_sum(nsp_image, (unsigned long *)&cr.chksum, 0); fseek(nsp_image,0, SEEK_END); fwrite(&cr, 1, sizeof(cr), nsp_image); } { FILE * non_web; char fname[256]; char * img_buf; unsigned int len; strcpy(fname, filen_out); strcat(fname, ".non_web"); non_web = fopen(fname,"wb+"); fseek(nsp_image, 0, SEEK_END); len = ftell(nsp_image); img_buf=malloc(len); fseek(nsp_image, 0, SEEK_SET); fread(img_buf, 1, len, nsp_image); img_buf[0xb] = 0x17; fwrite(img_buf, 1, len-sizeof(struct checksumrecord), non_web); fclose(non_web); free(img_buf); } /* Close NSP image file */ fclose(nsp_image); /* return result */ return(0); } #ifdef DMALLOC #include #endif /* DMALLOC */ #define BUFLEN (1 << 16) static unsigned long crctab[256] = { 0x0, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 }; int cs_is_tagged(FILE *fp) { char buf[8]; fseek(fp, -8, SEEK_END); fread(buf, 8, 1, fp); if(*(unsigned long*)buf == CKSUM_MAGIC_NUMBER) return 1; return 0; } unsigned long cs_read_sum(FILE *fp) { char buf[8]; fseek(fp, -8, SEEK_END); fread(buf, 8, 1, fp); return *((unsigned long*)&buf[4]); } int cs_calc_sum(FILE *fp, unsigned long *res, int tagged) { unsigned char buf[BUFLEN]; unsigned long crc = 0; uintmax_t length = 0; size_t bytes_read; fseek(fp, 0, SEEK_SET); while((bytes_read = fread(buf, 1, BUFLEN, fp)) > 0) { unsigned char *cp = buf; if(length + bytes_read < length) return 0; if(bytes_read != BUFLEN && tagged) bytes_read -= 8; length += bytes_read; while(bytes_read--) crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF]; } if(ferror(fp)) return 0; for(; length; length >>= 8) crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF]; crc = ~crc & 0xFFFFFFFF; *res = crc; return 1; } unsigned long cs_calc_buf_sum(char *buf, int size) { unsigned long crc = 0; char *cp = buf; unsigned long length = size; while(size--) crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF]; for(; length; length >>= 8) crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF]; crc = ~crc & 0xFFFFFFFF; return crc; } unsigned long cs_calc_buf_sum_ds(char *buf, int buf_size, char *sign, int sign_len) { unsigned long crc = 0; char *cp = buf; unsigned long length = buf_size+sign_len; while(buf_size--) crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF]; cp = sign; while(sign_len--) crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF]; for(; length; length >>= 8) crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF]; crc = ~crc & 0xFFFFFFFF; return crc; } int cs_set_sum(FILE *fp, unsigned long sum, int tagged) { unsigned long magic = CKSUM_MAGIC_NUMBER; if(tagged) fseek(fp, -8, SEEK_END); else fseek(fp, 0, SEEK_END); if(fwrite(&magic, 1, 4, fp) < 4) return 0; if(fwrite(&sum, 1, 4, fp) < 4) return 0; return 1; } void cs_get_sum(FILE *fp, unsigned long *sum) { unsigned long magic = 0; fseek(fp, -8, SEEK_END); fread(&magic, 4, 1, fp); fread(sum, 4, 1, fp); } int cs_validate_file(char *filename) { FILE *pFile = NULL; unsigned long sum = 0, res = 0; if((pFile = fopen(filename, "r")) == NULL) return 0; if(!cs_is_tagged(pFile)) { fclose(pFile); return 0; } if(!cs_calc_sum(pFile, &sum, 1)) { fclose(pFile); return 0; } cs_get_sum(pFile, &res); fclose(pFile); if(sum != res) return 0; return 1; } /* ********* Library internal data ********* */ #define CMDLINE_TRUE 1 #define CMDLINE_FALSE 0 typedef enum CMDLINE_ERR { CMDLINE_ERR_OK = 0, /* No Error (OK) */ CMDLINE_ERR_ERROR = -1, /* Unspecified error */ CMDLINE_ERR_INVKEY = -3, /* Invalid option key */ CMDLINE_ERR_MANYARG = -4, /* Too many arguments */ CMDLINE_ERR_FEWARG = -5, /* Too few arguments */ CMDLINE_ERR_ILLOPT = -6, /* Option not allowed (illegal option) */ CMDLINE_ERR_NOMEM = -7, /* No memory */ CMDLINE_ERR_OPTMIS = -8 /* A mandatory option is missing */ } CMDLINE_ERR; /* Argument list */ typedef struct CMDLINE_ARG { int index; /* Index of the argument in the command line */ struct CMDLINE_ARG* p_next; /* Next node in the linked list */ } CMDLINE_ARG; /* Master control block for an option */ typedef struct CMDLINE_ARGS { int argc; /* Total count of arguments found */ int optc; /* Total count of options found */ CMDLINE_ARG* list; /* Argument list */ } CMDLINE_ARGS; /* Master control block for all found arguments */ typedef struct CMDLINE_DATA { CMDLINE_ARGS opt_args[26]; /* Array of MCBs for each option ('a' through 'z') */ CMDLINE_ARGS glb_args; /* Global arguments */ int parsed; /* Internal flag to prevent client calls if library is not initialized */ } CMDLINE_DATA; /* ********* Local Data ********* */ static CMDLINE_CFG cmdline_cfg; static CMDLINE_DATA cmdline_data; char* cmdline_errmsg = "CMDLINE ERROR"; /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ void* cmdline_getarg_list(char opt) { int index = (opt - 'a'); /* Check the validity of the index */ if((index < 0) || (index > 25)) { /* ERROR: Wrong option */ return NULL; } /* Return a pointer to the ARGS control structure */ return((void*)(&cmdline_data.opt_args[index])); } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ int cmdline_getarg_count(void* list) { CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list; /* Return number of arguments for this option */ return(p_args->argc); } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ int cmdline_getopt_count(char opt) { int index; /* Calculate index value */ index = opt - 'a'; if(index < 0 || index > 25) return -1; /* Return number of arguments for this option */ return(cmdline_data.opt_args[index].optc); } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ int cmdline_getarg(void* list, int num) { int i; CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list; CMDLINE_ARG* p_arg; /* Search the 'num' argument in the list for this option */ for(i=0,p_arg=p_args->list; (p_arg!=NULL) && (iargc); i++, p_arg=p_arg->p_next) { /* if num matches i, we found it */ if(i==num) return(p_arg->index); } /* We did not find the specified argument or the list was empty */ return -1; } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ int cmdline_configure(CMDLINE_CFG* p_cfg) { /* reset global data */ memset(&cmdline_cfg,0,sizeof(cmdline_cfg)); memset(&cmdline_data,0,sizeof(cmdline_data)); /* Copy the user's config structure */ cmdline_cfg = *p_cfg; return 0; } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ char* cmdline_error(int err) { /* TODO: implement a table of error messages */ return(cmdline_errmsg); } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ static void cmdline_print_args(CMDLINE_ARGS* p_arglist, char* argv[]) { CMDLINE_ARG* p_arg; printf(" Number of times option was specified: %d\n", p_arglist->optc); printf(" Number of Arguments: %d\n", p_arglist->argc); if(p_arglist->argc > 0) { printf(" Argument List: "); for(p_arg=p_arglist->list; p_arg != NULL; p_arg=p_arg->p_next) printf("%s ", argv[p_arg->index]); } printf("\n"); } /* *************************************************************** * Print all found command line options and their arguments ****************************************************************** */ void cmdline_print(char* argv[]) { int i; /* Check if the command line was parsed */ if(cmdline_data.parsed != CMDLINE_TRUE) { printf("The command line has not been parsed yet.\n"); return; } /* Print out option arguments */ for( i = 0; i < 26; i++ ) { /* Check if the option was specified */ if(cmdline_data.opt_args[i].optc !=0 ) { /* Print out option name and arguments */ printf("Option: -%c\n", (char)('a'+i)); cmdline_print_args(&(cmdline_data.opt_args[i]), argv); } } /* Print out global arguments */ printf("Global arguments:\n"); cmdline_print_args(&(cmdline_data.glb_args), argv); } /* *************************************************************** * Print configuration ****************************************************************** */ void cmdline_print_cfg(void) { } static void cmdline_argadd(CMDLINE_ARGS* p_arglist, CMDLINE_ARG* p_arg) { CMDLINE_ARG* p_list; CMDLINE_ARG* p_prev=NULL; /* See if we had anything in the list */ if(p_arglist->argc == 0) { /* Link the argument in */ p_arglist->list = p_arg; } else { /* Find the tail of the list */ for(p_list=p_arglist->list; p_list != NULL; p_list=p_list->p_next) p_prev = p_list; /* Link the argument in */ p_prev->p_next=p_arg; } /* Keep track of arg number */ p_arglist->argc++; } /* *************************************************************** * cmdline_read() * Read and parse command line arguments ****************************************************************** */ int cmdline_read(int argc, char* argv[]) { int i, option=0; /* Process every command line argument in argv[] array */ for( i = 1; i < argc; i++ ) { /* Does the argument start with a dash? */ if( *argv[i] == '-' ) { /* The argument must be two characters: a dash, and a letter */ if( strlen(argv[i]) != 2 ) { /* ERROR: option syntax (needs to be a dash and one letter) */ return(CMDLINE_ERR_ERROR); } /* Check validity of the option key ('a' through 'z') */ if( ((*(argv[i] + 1)) < 'a') || ((*(argv[i] + 1)) > 'z') ) { /* ERROR: option sysntax (invalid option key) */ return(CMDLINE_ERR_INVKEY); } /* Calculate the option index */ option = (*(argv[i] + 1)) - 'a'; if((option < 0) || (option > 25)) return(CMDLINE_ERR_INVKEY); /* Check to see if the option is allowed */ if( cmdline_cfg.opts[option].flags & CMDLINE_OPTFLAG_ALLOW ) { /* Option allowed. */ cmdline_data.opt_args[option].optc++; continue; } else { /* ERROR: Option is not allowed */ return(CMDLINE_ERR_ILLOPT); } } else { /* Read the arguments for the option */ CMDLINE_ARG* p_arg; /* Allocate space for the argument node */ p_arg = (CMDLINE_ARG*)calloc(1,sizeof(CMDLINE_ARG)); if( p_arg== NULL ) { /* ERROR: Can't allocate memory for the argument index */ return(CMDLINE_ERR_NOMEM); } /* Initialize the argument */ p_arg->index = i; p_arg->p_next = NULL; /* Check if we can add to the list of arguments for this option */ if( (option < 0) /* Do we have to add to the global list? */ || (cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max) /* Did we reach MAX arguments? */ ) { /* This option does not require arguments. Keep the argument in the global list. */ cmdline_argadd(&(cmdline_data.glb_args), p_arg); continue; } else { /* See if the current count has reached max for this option */ if( cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max ) { /* ERROR: too many arguments for an option */ return(CMDLINE_ERR_MANYARG); } else { /* Link the argument to the arg list of the option */ cmdline_argadd(&(cmdline_data.opt_args[option]), p_arg); continue; } } } } /* ****** We read the complete command line. See if what we collected matches the configuration ******* */ /* Check every collected option against its configuration */ for( i=0; i < 26; i++ ) { /* Check if this option was allowed */ if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_ALLOW) { /* See if it was mandatory */ if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_MANDAT) { /* Check if we really collected this option on the command line. */ if(cmdline_data.opt_args[i].optc == 0) { /* ERROR: a missing mandatory option */ return(CMDLINE_ERR_OPTMIS); } else { /* Option was there. Check how many args we got for it. */ if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min) { /* ERROR: too few arguments for an option */ return(CMDLINE_ERR_FEWARG); } else { /* This mandatory option was proper. */ continue; } } } else /* This is non-mandatory option: */ { /* Check if the option was specified on the command line */ if(cmdline_data.opt_args[i].optc == 0) { /* option wasn't specified, go to the next */ continue; } else { /* Option was there. Check how many args we collected for it. */ if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min) { /* ERROR: too few arguments for a non-mandatory option */ return(CMDLINE_ERR_FEWARG); } else { /* This non-mandatory option was proper. */ continue; } } } } else /* Option was not allowed. */ { /* We should not get here as the non-allowed options should have been trapped eariler. */ } } /* Command line was proper as far as the number of options and their arguments */ cmdline_data.parsed = CMDLINE_TRUE; return(CMDLINE_ERR_OK); } ================================================ FILE: src/firmware-tools/mktitanimg.h ================================================ #ifndef __MKTITANIMG_H #define __MKTITANIMG_H #ifndef CFGMGR_CKSUM_H #define CFGMGR_CKSUM_H #define CKSUM_MAGIC_NUMBER 0xC453DE23 #include #include #include int cs_is_tagged(FILE*); unsigned long cs_read_sum(FILE*); int cs_calc_sum(FILE*, unsigned long*, int); int cs_set_sum(FILE*, unsigned long, int); void cs_get_sum(FILE*, unsigned long*); unsigned long cs_calc_buf_sum(char*, int); int cs_validate_file(char*); #endif #ifndef ___CMDLINE_H___ #define ___CMDLINE_H___ /* ********* Library Configuration ********* */ typedef struct CMDLINE_OPT { int min; /* Minimum number of arguments this option takes */ int max; /* Maximum number of arguments this option takes */ int flags; /* Controlling flags (whether to accept or not, etc) */ } CMDLINE_OPT; typedef struct CMDLINE_CFG { CMDLINE_OPT opts[26]; /* Options 'a' through 'z' */ CMDLINE_OPT global; /* Global option (outside 'a'..'z') */ } CMDLINE_CFG; /* ******************************************** */ #define CMDLINE_OPTFLAG_ALLOW 0x1 /* The option is allowed */ #define CMDLINE_OPTFLAG_MANDAT 0x2 /* The option is mandatory */ extern void cmdline_print(char* argv[]); extern int cmdline_configure(CMDLINE_CFG* p_cfg); extern int cmdline_read(int argc, char* argv[]); extern void* cmdline_getarg_list(char opt); extern int cmdline_getarg_count(void* list); extern int cmdline_getopt_count(char opt); extern int cmdline_getarg(void* list, int num); extern char* cmdline_error(int err); #endif #ifndef _NSPIMGHDR_H_ #define _NSPIMGHDR_H_ /* This file describes the header format for the single image. The image is broken up into several pieces. The image contains this header plus 1 or more sections. Each section contains a binary block that could be a kernel, filesystem, etc. The only garentee for this is that the very first section MUST be executable. Meaning that the bootloader will be able to take the address of the header start, add the header size, and execute that binary block. The header has its own checksum. It starts hdr_size-4 bytes from the start of the header. */ struct nsp_img_hdr_head { unsigned int magic; /* Magic number to identify this image header */ unsigned int boot_offset; /* Offset from start of header to kernel code. */ unsigned int flags; /* Image flags. */ unsigned int hdr_version; /* Version of this header. */ unsigned int hdr_size; /* The complete size of all portions of the header */ unsigned int prod_id; /* This product id */ unsigned int rel_id; /* Which release this is */ unsigned int version; /* name-MMM.nnn.ooo-rxx => 0xMMnnooxx. See comment below */ unsigned int image_size; /* Image size (including header) */ unsigned int info_offset; /* Offset from start of header to info block */ unsigned int sect_info_offset; /* Offset from start of header to section desc */ unsigned int chksum_offset; /* Offset from start of header to chksum block */ // unsigned int pad1; }; /* The patch id is a machine readable value that takes the normal patch level, and encodes the correct numbers inside of it. The format of the patches are name-MM.NN.oo-rxx.bin. Convert MM, NN, oo, and xx into hex, and encode them as 0xMMNNooxx. Thus: att-1.2.18-r14.bin => 0x0102120e */ /* The following are the flag bits for the above flags variable */ /* List of NSP status flags: */ #define NSP_IMG_FLAG_FAILBACK_MASK 0xF8000000 /* NSP Image status flag: Flag indicates individual sections image */ #define NSP_IMG_FLAG_INDIVIDUAL 0x00000001 /* NSP Image status flag 1: Image contains a bootable image when this bit is 0 */ #define NSP_IMG_FLAG_FAILBACK_1 0x08000000 /* NSP Image status flag 2: Image contains a non-bootable image when this bit is 0 */ #define NSP_IMG_FLAG_FAILBACK_2 0x10000000 /* NSP Image status flag 3: PSPBoot has tried the image when this bit is 0 */ #define NSP_IMG_FLAG_FAILBACK_3 0x20000000 /* NSP Image status flag 4: Image is now secondary image when this bit is 0 */ #define NSP_IMG_FLAG_FAILBACK_4 0x40000000 /* NSP Image status flag 5: Image contains a valid image when this bit is 0 */ #define NSP_IMG_FLAG_FAILBACK_5 0x80000000 /* NSP Single image magic number */ #define NSP_IMG_MAGIC_NUMBER 0x4D544443 struct nsp_img_hdr_info { char release_name[64]; /* Name of release */ char image_filename[64]; /* name-mm.nn.oo-rxx.bin format */ }; struct nsp_img_hdr_section_info { unsigned int num_sects; /* Number of section (and section desc blocks) in this image */ unsigned int sect_size; /* Size of a SINGLE section_desc block */ unsigned int sections_offset; /* Offset to from start of header to the start of the section blocks */ }; /* There will be one of more of the following stuctures in the image header. Each section will have one of these blocks. */ struct nsp_img_hdr_sections { unsigned int offset; /* Offset of section from start of NSP_IMG_HDR_HEAD */ unsigned int total_size; /* Size of section (including pad size.) */ unsigned int raw_size; /* Size of section only */ unsigned int flags; /* Section flags */ unsigned int chksum; /* Section checksum */ unsigned int type; /* Section type. What kind of info does this section describe */ char name[16]; /* Reference name for this section. */ }; #define NSP_IMG_SECTION_TYPE_KERNEL (0x01) #define NSP_IMG_SECTION_TYPE_FILESYSTEM_ROOT (0x02) #define NSP_IMG_SECTION_TYPE_FILESYSTEM (0x03) struct nsp_img_hdr { struct nsp_img_hdr_head head; /* Head portion */ struct nsp_img_hdr_info info; /* Info */ struct nsp_img_hdr_section_info sect_info; /* Section block */ struct nsp_img_hdr_sections sections; /* 1 or more section_description blocks. More section_desc blocks will be appended here for each additional section needed */ }; struct nsp_img_hdr_chksum { unsigned int hdr_chksum; /* The checksum for the complete header. Excepting the checksum block */ }; struct nsp_img_hdr_sections *nsp_img_hdr_get_section_ptr_by_name(struct nsp_img_hdr *hdr, char *name); unsigned int nsp_img_hdr_get_section_offset_by_name(struct nsp_img_hdr *hdr, char *name); unsigned int nsp_img_hdr_get_section_size_by_name(struct nsp_img_hdr *hdr, char *name); #endif #endif /* __MKTITANIMG_H */ ================================================ FILE: src/firmware-tools/mktplinkfw.c ================================================ /* * Copyright (C) 2009 Gabor Juhos * * This tool was based on: * TP-Link WR941 V2 firmware checksum fixing tool. * Copyright (C) 2008,2009 Wang Jian * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include #include #include "md5.h" #define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); }) #define HEADER_VERSION_V1 0x01000000 #define HWID_TL_MR3020_V1 0x30200001 #define HWID_TL_MR3220_V1 0x32200001 #define HWID_TL_MR3420_V1 0x34200001 #define HWID_TL_WA701N_V1 0x07010001 #define HWID_TL_WA7510N_V1 0x75100001 #define HWID_TL_WA901ND_V1 0x09010001 #define HWID_TL_WA901ND_V2 0x09010002 #define HWID_TL_WR703N_V1 0x07030101 #define HWID_TL_WR741ND_V1 0x07410001 #define HWID_TL_WR741ND_V4 0x07410004 #define HWID_TL_WR740N_V1 0x07400001 #define HWID_TL_WR740N_V3 0x07400003 #define HWID_TL_WR743ND_V1 0x07430001 #define HWID_TL_WR841N_V1_5 0x08410002 #define HWID_TL_WR841ND_V3 0x08410003 #define HWID_TL_WR841ND_V5 0x08410005 #define HWID_TL_WR841ND_V7 0x08410007 #define HWID_TL_WR941ND_V2 0x09410002 #define HWID_TL_WR941ND_V4 0x09410004 #define HWID_TL_WR1043ND_V1 0x10430001 #define HWID_TL_WR1041N_V2 0x10410002 #define HWID_TL_WR2543N_V1 0x25430001 #define MD5SUM_LEN 16 struct file_info { char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ }; struct fw_header { uint32_t version; /* header version */ char vendor_name[24]; char fw_version[36]; uint32_t hw_id; /* hardware id */ uint32_t hw_rev; /* hardware revision */ uint32_t unk1; uint8_t md5sum1[MD5SUM_LEN]; uint32_t unk2; uint8_t md5sum2[MD5SUM_LEN]; uint32_t unk3; uint32_t kernel_la; /* kernel load address */ uint32_t kernel_ep; /* kernel entry point */ uint32_t fw_length; /* total length of the firmware */ uint32_t kernel_ofs; /* kernel data offset */ uint32_t kernel_len; /* kernel data length */ uint32_t rootfs_ofs; /* rootfs data offset */ uint32_t rootfs_len; /* rootfs data length */ uint32_t boot_ofs; /* bootloader data offset */ uint32_t boot_len; /* bootloader data length */ uint16_t ver_hi; uint16_t ver_mid; uint16_t ver_lo; uint8_t pad[354]; } __attribute__ ((packed)); struct flash_layout { char *id; uint32_t fw_max_len; uint32_t kernel_la; uint32_t kernel_ep; uint32_t rootfs_ofs; }; struct board_info { char *id; uint32_t hw_id; uint32_t hw_rev; char *layout_id; }; /* * Globals */ static char *ofname; static char *progname; static char *vendor = "TP-LINK Technologies"; static char *version = "ver. 1.0"; static char *fw_ver = "0.0.0"; static char *board_id; static struct board_info *board; static char *layout_id; static struct flash_layout *layout; static char *opt_hw_id; static uint32_t hw_id; static char *opt_hw_rev; static uint32_t hw_rev; static int fw_ver_lo; static int fw_ver_mid; static int fw_ver_hi; static struct file_info kernel_info; static uint32_t kernel_la = 0; static uint32_t kernel_ep = 0; static uint32_t kernel_len = 0; static struct file_info rootfs_info; static uint32_t rootfs_ofs = 0; static uint32_t rootfs_align; static struct file_info boot_info; static int combined; static int strip_padding; static int add_jffs2_eof; static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde}; static struct file_info inspect_info; static int extract = 0; char md5salt_normal[MD5SUM_LEN] = { 0xdc, 0xd7, 0x3a, 0xa5, 0xc3, 0x95, 0x98, 0xfb, 0xdd, 0xf9, 0xe7, 0xf4, 0x0e, 0xae, 0x47, 0x38, }; char md5salt_boot[MD5SUM_LEN] = { 0x8c, 0xef, 0x33, 0x5b, 0xd5, 0xc5, 0xce, 0xfa, 0xa7, 0x9c, 0x28, 0xda, 0xb2, 0xe9, 0x0f, 0x42, }; static struct flash_layout layouts[] = { { .id = "4M", .fw_max_len = 0x3c0000, .kernel_la = 0x80060000, .kernel_ep = 0x80060000, .rootfs_ofs = 0x140000, }, { .id = "4Mlzma", .fw_max_len = 0x3c0000, .kernel_la = 0x80060000, .kernel_ep = 0x80060000, .rootfs_ofs = 0x100000, }, { .id = "8M", .fw_max_len = 0x7c0000, .kernel_la = 0x80060000, .kernel_ep = 0x80060000, .rootfs_ofs = 0x140000, }, { .id = "8Mlzma", .fw_max_len = 0x7c0000, .kernel_la = 0x80060000, .kernel_ep = 0x80060000, .rootfs_ofs = 0x100000, }, { /* terminating entry */ } }; static struct board_info boards[] = { { .id = "TL-MR3020v1", .hw_id = HWID_TL_MR3020_V1, .hw_rev = 1, .layout_id = "4Mlzma", }, { .id = "TL-MR3220v1", .hw_id = HWID_TL_MR3220_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-MR3420v1", .hw_id = HWID_TL_MR3420_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WA701Nv1", .hw_id = HWID_TL_WA701N_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WA7510N", .hw_id = HWID_TL_WA7510N_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WA901NDv1", .hw_id = HWID_TL_WA901ND_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WA901NDv2", .hw_id = HWID_TL_WA901ND_V2, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR741NDv1", .hw_id = HWID_TL_WR741ND_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR741NDv4", .hw_id = HWID_TL_WR741ND_V4, .hw_rev = 1, .layout_id = "4Mlzma", }, { .id = "TL-WR740Nv1", .hw_id = HWID_TL_WR740N_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR740Nv3", .hw_id = HWID_TL_WR740N_V3, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR743NDv1", .hw_id = HWID_TL_WR743ND_V1, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR841Nv1.5", .hw_id = HWID_TL_WR841N_V1_5, .hw_rev = 2, .layout_id = "4M", }, { .id = "TL-WR841NDv3", .hw_id = HWID_TL_WR841ND_V3, .hw_rev = 3, .layout_id = "4M", }, { .id = "TL-WR841NDv5", .hw_id = HWID_TL_WR841ND_V5, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR841NDv7", .hw_id = HWID_TL_WR841ND_V7, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR941NDv2", .hw_id = HWID_TL_WR941ND_V2, .hw_rev = 2, .layout_id = "4M", }, { .id = "TL-WR941NDv4", .hw_id = HWID_TL_WR941ND_V4, .hw_rev = 1, .layout_id = "4M", }, { .id = "TL-WR1041Nv2", .hw_id = HWID_TL_WR1041N_V2, .hw_rev = 1, .layout_id = "4Mlzma", }, { .id = "TL-WR1043NDv1", .hw_id = HWID_TL_WR1043ND_V1, .hw_rev = 1, .layout_id = "8M", }, { .id = "TL-WR2543Nv1", .hw_id = HWID_TL_WR2543N_V1, .hw_rev = 1, .layout_id = "8Mlzma", }, { .id = "TL-WR703Nv1", .hw_id = HWID_TL_WR703N_V1, .hw_rev = 1, .layout_id = "4Mlzma", }, { /* terminating entry */ } }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define DBG(fmt, ...) do { \ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) static struct board_info *find_board(char *id) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->id != NULL; board++){ if (strcasecmp(id, board->id) == 0) { ret = board; break; } }; return ret; } static struct board_info *find_board_by_hwid(uint32_t hw_id) { struct board_info *board; for (board = boards; board->id != NULL; board++) { if (hw_id == board->hw_id) return board; }; return NULL; } static struct flash_layout *find_layout(char *id) { struct flash_layout *ret; struct flash_layout *l; ret = NULL; for (l = layouts; l->id != NULL; l++){ if (strcasecmp(id, l->id) == 0) { ret = l; break; } }; return ret; } static void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with \n" " -c use combined kernel image\n" " -E overwrite kernel entry point with (hexval prefixed with 0x)\n" " -L overwrite kernel load address with (hexval prefixed with 0x)\n" " -H use hardware id specified with \n" " -F use flash layout specified with \n" " -k read kernel image from the file \n" " -r read rootfs image from the file \n" " -a align the rootfs start on an bytes boundary\n" " -R overwrite rootfs offset with (hexval prefixed with 0x)\n" " -o write output to the file \n" " -s strip padding from the end of the image\n" " -j add jffs2 end-of-filesystem markers\n" " -N set image vendor to \n" " -V set image version to \n" " -v set firmware version to \n" " -i inspect given firmware file \n" " -x extract kernel and rootfs while inspecting (requires -i)\n" " -h show this screen\n" ); exit(status); } static int get_md5(char *data, int size, char *md5) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, size); MD5_Final(md5, &ctx); } static int get_file_stat(struct file_info *fdata) { struct stat st; int res; if (fdata->file_name == NULL) return 0; res = stat(fdata->file_name, &st); if (res){ ERRS("stat failed on %s", fdata->file_name); return res; } fdata->file_size = st.st_size; return 0; } static int read_to_buf(struct file_info *fdata, char *buf) { FILE *f; int ret = EXIT_FAILURE; f = fopen(fdata->file_name, "r"); if (f == NULL) { ERRS("could not open \"%s\" for reading", fdata->file_name); goto out; } errno = 0; fread(buf, fdata->file_size, 1, f); if (errno != 0) { ERRS("unable to read from file \"%s\"", fdata->file_name); goto out_close; } ret = EXIT_SUCCESS; out_close: fclose(f); out: return ret; } static int check_options(void) { int ret; if (inspect_info.file_name) { ret = get_file_stat(&inspect_info); if (ret) return ret; return 0; } else if (extract) { ERR("no firmware for inspection specified"); return -1; } if (board_id == NULL && opt_hw_id == NULL) { ERR("either board or hardware id must be specified"); return -1; } if (board_id) { board = find_board(board_id); if (board == NULL) { ERR("unknown/unsupported board id \"%s\"", board_id); return -1; } if (layout_id == NULL) layout_id = board->layout_id; hw_id = board->hw_id; hw_rev = board->hw_rev; } else { if (layout_id == NULL) { ERR("flash layout is not specified"); return -1; } hw_id = strtoul(opt_hw_id, NULL, 0); if (opt_hw_rev) hw_rev = strtoul(opt_hw_rev, NULL, 0); else hw_rev = 1; } layout = find_layout(layout_id); if (layout == NULL) { ERR("unknown flash layout \"%s\"", layout_id); return -1; } if (!kernel_la) kernel_la = layout->kernel_la; if (!kernel_ep) kernel_ep = layout->kernel_ep; if (!rootfs_ofs) rootfs_ofs = layout->rootfs_ofs; if (kernel_info.file_name == NULL) { ERR("no kernel image specified"); return -1; } ret = get_file_stat(&kernel_info); if (ret) return ret; kernel_len = kernel_info.file_size; if (combined) { if (kernel_info.file_size > layout->fw_max_len - sizeof(struct fw_header)) { ERR("kernel image is too big"); return -1; } } else { if (rootfs_info.file_name == NULL) { ERR("no rootfs image specified"); return -1; } ret = get_file_stat(&rootfs_info); if (ret) return ret; if (rootfs_align) { kernel_len += sizeof(struct fw_header); kernel_len = ALIGN(kernel_len, rootfs_align); kernel_len -= sizeof(struct fw_header); DBG("kernel length aligned to %u", kernel_len); if (kernel_len + rootfs_info.file_size > layout->fw_max_len - sizeof(struct fw_header)) { ERR("images are too big"); return -1; } } else { if (kernel_info.file_size > rootfs_ofs - sizeof(struct fw_header)) { ERR("kernel image is too big"); return -1; } if (rootfs_info.file_size > (layout->fw_max_len - rootfs_ofs)) { ERR("rootfs image is too big"); return -1; } } } if (ofname == NULL) { ERR("no output file specified"); return -1; } ret = sscanf(fw_ver, "%d.%d.%d", &fw_ver_hi, &fw_ver_mid, &fw_ver_lo); if (ret != 3) { ERR("invalid firmware version '%s'", fw_ver); return -1; } return 0; } static void fill_header(char *buf, int len) { struct fw_header *hdr = (struct fw_header *)buf; memset(hdr, 0, sizeof(struct fw_header)); hdr->version = htonl(HEADER_VERSION_V1); strncpy(hdr->vendor_name, vendor, sizeof(hdr->vendor_name)); strncpy(hdr->fw_version, version, sizeof(hdr->fw_version)); hdr->hw_id = htonl(hw_id); hdr->hw_rev = htonl(hw_rev); if (boot_info.file_size == 0) memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1)); else memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1)); hdr->kernel_la = htonl(kernel_la); hdr->kernel_ep = htonl(kernel_ep); hdr->fw_length = htonl(layout->fw_max_len); hdr->kernel_ofs = htonl(sizeof(struct fw_header)); hdr->kernel_len = htonl(kernel_len); if (!combined) { hdr->rootfs_ofs = htonl(rootfs_ofs); hdr->rootfs_len = htonl(rootfs_info.file_size); } hdr->ver_hi = htons(fw_ver_hi); hdr->ver_mid = htons(fw_ver_mid); hdr->ver_lo = htons(fw_ver_lo); get_md5(buf, len, hdr->md5sum1); } static int pad_jffs2(char *buf, int currlen) { int len; uint32_t pad_mask; len = currlen; pad_mask = (64 * 1024); while ((len < layout->fw_max_len) && (pad_mask != 0)) { uint32_t mask; int i; for (i = 10; i < 32; i++) { mask = 1 << i; if (pad_mask & mask) break; } len = ALIGN(len, mask); for (i = 10; i < 32; i++) { mask = 1 << i; if ((len & (mask - 1)) == 0) pad_mask &= ~mask; } for (i = 0; i < sizeof(jffs2_eof_mark); i++) buf[len + i] = jffs2_eof_mark[i]; len += sizeof(jffs2_eof_mark); } return len; } static int write_fw(char *data, int len) { FILE *f; int ret = EXIT_FAILURE; f = fopen(ofname, "w"); if (f == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } errno = 0; fwrite(data, len, 1, f); if (errno) { ERRS("unable to write output file"); goto out_flush; } DBG("firmware file \"%s\" completed", ofname); ret = EXIT_SUCCESS; out_flush: fflush(f); fclose(f); if (ret != EXIT_SUCCESS) { unlink(ofname); } out: return ret; } static int build_fw(void) { int buflen; char *buf; char *p; int ret = EXIT_FAILURE; int writelen = 0; buflen = layout->fw_max_len; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } memset(buf, 0xff, buflen); p = buf + sizeof(struct fw_header); ret = read_to_buf(&kernel_info, p); if (ret) goto out_free_buf; writelen = sizeof(struct fw_header) + kernel_len; if (!combined) { if (rootfs_align) p = buf + writelen; else p = buf + rootfs_ofs; ret = read_to_buf(&rootfs_info, p); if (ret) goto out_free_buf; if (rootfs_align) writelen += rootfs_info.file_size; else writelen = rootfs_ofs + rootfs_info.file_size; if (add_jffs2_eof) writelen = pad_jffs2(buf, writelen); } if (!strip_padding) writelen = buflen; fill_header(buf, writelen); ret = write_fw(buf, writelen); if (ret) goto out_free_buf; ret = EXIT_SUCCESS; out_free_buf: free(buf); out: return ret; } /* Helper functions to inspect_fw() representing different output formats */ static inline void inspect_fw_pstr(char *label, char *str) { printf("%-23s: %s\n", label, str); } static inline void inspect_fw_phex(char *label, uint32_t val) { printf("%-23s: 0x%08x\n", label, val); } static inline void inspect_fw_phexpost(char *label, uint32_t val, char *post) { printf("%-23s: 0x%08x (%s)\n", label, val, post); } static inline void inspect_fw_phexdef(char *label, uint32_t val, uint32_t defval) { printf("%-23s: 0x%08x ", label, val); if (val == defval) printf("(== OpenWrt default)\n"); else printf("(OpenWrt default: 0x%08x)\n", defval); } static inline void inspect_fw_phexexp(char *label, uint32_t val, uint32_t expval) { printf("%-23s: 0x%08x ", label, val); if (val == expval) printf("(ok)\n"); else printf("(expected: 0x%08x)\n", expval); } static inline void inspect_fw_phexdec(char *label, uint32_t val) { printf("%-23s: 0x%08x / %8u bytes\n", label, val, val); } static inline void inspect_fw_phexdecdef(char *label, uint32_t val, uint32_t defval) { printf("%-23s: 0x%08x / %8u bytes ", label, val, val); if (val == defval) printf("(== OpenWrt default)\n"); else printf("(OpenWrt default: 0x%08x)\n", defval); } static inline void inspect_fw_pmd5sum(char *label, uint8_t *val, char *text) { int i; printf("%-23s:", label); for (i=0; iversion) != HEADER_VERSION_V1) { ERR("file does not seem to have V1 header!\n"); goto out_free_buf; } inspect_fw_phexdec("Version 1 Header size", sizeof(struct fw_header)); if (ntohl(hdr->unk1) != 0) inspect_fw_phexdec("Unknown value 1", hdr->unk1); memcpy(md5sum, hdr->md5sum1, sizeof(md5sum)); if (ntohl(hdr->boot_len) == 0) memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum)); else memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum)); get_md5(buf, inspect_info.file_size, hdr->md5sum1); if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) { inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)"); inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, ""); } else { inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)"); } if (ntohl(hdr->unk2) != 0) inspect_fw_phexdec("Unknown value 2", hdr->unk2); inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2, "(purpose yet unknown, unchecked here)"); if (ntohl(hdr->unk3) != 0) inspect_fw_phexdec("Unknown value 3", hdr->unk3); printf("\n"); inspect_fw_pstr("Vendor name", hdr->vendor_name); inspect_fw_pstr("Firmware version", hdr->fw_version); board = find_board_by_hwid(ntohl(hdr->hw_id)); if (board) { layout = find_layout(board->layout_id); inspect_fw_phexpost("Hardware ID", ntohl(hdr->hw_id), board->id); inspect_fw_phexexp("Hardware Revision", ntohl(hdr->hw_rev), board->hw_rev); } else { inspect_fw_phexpost("Hardware ID", ntohl(hdr->hw_id), "unknown"); inspect_fw_phex("Hardware Revision", ntohl(hdr->hw_rev)); } printf("\n"); inspect_fw_phexdec("Kernel data offset", ntohl(hdr->kernel_ofs)); inspect_fw_phexdec("Kernel data length", ntohl(hdr->kernel_len)); if (board) { inspect_fw_phexdef("Kernel load address", ntohl(hdr->kernel_la), layout ? layout->kernel_la : 0xffffffff); inspect_fw_phexdef("Kernel entry point", ntohl(hdr->kernel_ep), layout ? layout->kernel_ep : 0xffffffff); inspect_fw_phexdecdef("Rootfs data offset", ntohl(hdr->rootfs_ofs), layout ? layout->rootfs_ofs : 0xffffffff); } else { inspect_fw_phex("Kernel load address", ntohl(hdr->kernel_la)); inspect_fw_phex("Kernel entry point", ntohl(hdr->kernel_ep)); inspect_fw_phexdec("Rootfs data offset", ntohl(hdr->rootfs_ofs)); } inspect_fw_phexdec("Rootfs data length", ntohl(hdr->rootfs_len)); inspect_fw_phexdec("Boot loader data offset", ntohl(hdr->boot_ofs)); inspect_fw_phexdec("Boot loader data length", ntohl(hdr->boot_len)); inspect_fw_phexdec("Total firmware length", ntohl(hdr->fw_length)); if (extract) { FILE *fp; char *filename; printf("\n"); filename = malloc(strlen(inspect_info.file_name) + 8); sprintf(filename, "%s-kernel", inspect_info.file_name); printf("Extracting kernel to \"%s\"...\n", filename); fp = fopen(filename, "w"); if (fp) { if (!fwrite(buf + ntohl(hdr->kernel_ofs), ntohl(hdr->kernel_len), 1, fp)) { ERR("error in fwrite(): %s", strerror(errno)); } fclose(fp); } else { ERR("error in fopen(): %s", strerror(errno)); } free(filename); filename = malloc(strlen(inspect_info.file_name) + 8); sprintf(filename, "%s-rootfs", inspect_info.file_name); printf("Extracting rootfs to \"%s\"...\n", filename); fp = fopen(filename, "w"); if (fp) { if (!fwrite(buf + ntohl(hdr->rootfs_ofs), ntohl(hdr->rootfs_len), 1, fp)) { ERR("error in fwrite(): %s", strerror(errno)); } fclose(fp); } else { ERR("error in fopen(): %s", strerror(errno)); } free(filename); } out_free_buf: free(buf); out: return ret; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; int err; FILE *outfile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "a:B:H:E:F:L:V:N:W:ci:k:r:R:o:xhsjv:"); if (c == -1) break; switch (c) { case 'a': sscanf(optarg, "0x%x", &rootfs_align); break; case 'B': board_id = optarg; break; case 'H': opt_hw_id = optarg; break; case 'E': sscanf(optarg, "0x%x", &kernel_ep); break; case 'F': layout_id = optarg; break; case 'W': opt_hw_rev = optarg; break; case 'L': sscanf(optarg, "0x%x", &kernel_la); break; case 'V': version = optarg; break; case 'v': fw_ver = optarg; break; case 'N': vendor = optarg; break; case 'c': combined++; break; case 'k': kernel_info.file_name = optarg; break; case 'r': rootfs_info.file_name = optarg; break; case 'R': sscanf(optarg, "0x%x", &rootfs_ofs); break; case 'o': ofname = optarg; break; case 's': strip_padding = 1; break; case 'i': inspect_info.file_name = optarg; break; case 'j': add_jffs2_eof = 1; break; case 'x': extract = 1; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } ret = check_options(); if (ret) goto out; if (!inspect_info.file_name) ret = build_fw(); else ret = inspect_fw(); out: return ret; } ================================================ FILE: src/firmware-tools/mkwrgimg.c ================================================ /* * Copyright (C) 2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include #include #include #include #include #include #include "md5.h" #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define WRG_MAGIC 0x20040220 struct wrg_header { char signature[32]; uint32_t magic1; uint32_t magic2; uint32_t size; uint32_t offset; char devname[32]; char digest[16]; } __attribute__ ((packed)); static char *progname; static char *ifname; static char *ofname; static char *signature; static char *dev_name; static uint32_t offset; static int big_endian; void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -b create image in big endian format\n" " -i read input from the file \n" " -d set device name to \n" " -o write output to the file \n" " -O set offset to \n" " -s set image signature to \n" " -h show this screen\n" ); exit(status); } static void put_u32(void *data, uint32_t val) { unsigned char *p = data; if (big_endian) { p[0] = (val >> 24) & 0xff; p[1] = (val >> 16) & 0xff; p[2] = (val >> 8) & 0xff; p[3] = val & 0xff; } else { p[3] = (val >> 24) & 0xff; p[2] = (val >> 16) & 0xff; p[1] = (val >> 8) & 0xff; p[0] = val & 0xff; } } static void get_digest(struct wrg_header *header, char *data, int size) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset)); MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname)); MD5_Update(&ctx, data, size); MD5_Final(header->digest, &ctx); } int main(int argc, char *argv[]) { struct wrg_header *header; char *buf; struct stat st; int buflen; int err; int res = EXIT_FAILURE; FILE *outfile, *infile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "bd:i:o:s:O:h"); if (c == -1) break; switch (c) { case 'b': big_endian = 1; break; case 'd': dev_name = optarg; break; case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 's': signature = optarg; break; case 'O': offset = strtoul(optarg, NULL, 0); break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } if (signature == NULL) { ERR("no signature specified"); goto err; } if (ifname == NULL) { ERR("no input file specified"); goto err; } if (ofname == NULL) { ERR("no output file specified"); goto err; } if (dev_name == NULL) { ERR("no device name specified"); goto err; } err = stat(ifname, &st); if (err){ ERRS("stat failed on %s", ifname); goto err; } buflen = st.st_size + sizeof(struct wrg_header); buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto err; } infile = fopen(ifname, "r"); if (infile == NULL) { ERRS("could not open \"%s\" for reading", ifname); goto err_free; } errno = 0; fread(buf + sizeof(struct wrg_header), st.st_size, 1, infile); if (errno != 0) { ERRS("unable to read from file %s", ifname); goto close_in; } header = (struct wrg_header *) buf; memset(header, '\0', sizeof(struct wrg_header)); strncpy(header->signature, signature, sizeof(header->signature)); strncpy(header->devname, dev_name, sizeof(header->signature)); put_u32(&header->magic1, WRG_MAGIC); put_u32(&header->magic2, WRG_MAGIC); put_u32(&header->size, st.st_size); put_u32(&header->offset, offset); get_digest(header, buf + sizeof(struct wrg_header), st.st_size); outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto close_in; } errno = 0; fwrite(buf, buflen, 1, outfile); if (errno) { ERRS("unable to write to file %s", ofname); goto close_out; } fflush(outfile); res = EXIT_SUCCESS; close_out: fclose(outfile); if (res != EXIT_SUCCESS) unlink(ofname); close_in: fclose(infile); err_free: free(buf); err: return res; } ================================================ FILE: src/firmware-tools/mkzcfw.c ================================================ /* * Copyright (C) 2010 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include "cyg_crc.h" #if (__BYTE_ORDER == __BIG_ENDIAN) # define HOST_TO_BE32(x) (x) # define BE32_TO_HOST(x) (x) # define HOST_TO_LE32(x) bswap_32(x) # define LE32_TO_HOST(x) bswap_32(x) #else # define HOST_TO_BE32(x) bswap_32(x) # define BE32_TO_HOST(x) bswap_32(x) # define HOST_TO_LE32(x) (x) # define LE32_TO_HOST(x) (x) #endif #define MAGIC_FIRMWARE 0x6d726966 /* 'firm' */ #define MAGIC_KERNEL 0x676d694b /* 'Kimg' */ #define MAGIC_ROOTFS 0x676d6952 /* 'Rimg' */ struct file_info { char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ }; struct fw_header { uint32_t magic; uint32_t length; uint32_t unk1; uint32_t unk2; } __attribute__ ((packed)); struct fw_tail { uint32_t hw_id; uint32_t crc; } __attribute__ ((packed)); struct board_info { char *id; uint32_t hw_id; uint32_t kernel_len; uint32_t rootfs_len; }; /* * Globals */ static char *ofname; static char *progname; static char *board_id; static struct board_info *board; static struct file_info kernel_info; static struct file_info rootfs_info; static struct board_info boards[] = { { .id = "ZCN-1523H-2-8", .hw_id = 0x66661523, .kernel_len = 0x170000, .rootfs_len = 0x610000, }, { .id = "ZCN-1523H-5-16", .hw_id = 0x6615235A, .kernel_len = 0x170000, .rootfs_len = 0x610000, }, { /* terminating entry */ } }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define DBG(fmt, ...) do { \ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) static struct board_info *find_board(char *id) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->id != NULL; board++){ if (strcasecmp(id, board->id) == 0) { ret = board; break; } }; return ret; } static void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with \n" " -k read kernel image from the file \n" " -r read rootfs image from the file \n" " -o write output to the file \n" " -h show this screen\n" ); exit(status); } static int get_file_stat(struct file_info *fdata) { struct stat st; int res; if (fdata->file_name == NULL) return 0; res = stat(fdata->file_name, &st); if (res){ ERRS("stat failed on %s", fdata->file_name); return res; } fdata->file_size = st.st_size; return 0; } static int read_to_buf(struct file_info *fdata, char *buf) { FILE *f; int ret = EXIT_FAILURE; f = fopen(fdata->file_name, "r"); if (f == NULL) { ERRS("could not open \"%s\" for reading", fdata->file_name); goto out; } errno = 0; fread(buf, fdata->file_size, 1, f); if (errno != 0) { ERRS("unable to read from file \"%s\"", fdata->file_name); goto out_close; } ret = EXIT_SUCCESS; out_close: fclose(f); out: return ret; } static int check_options(void) { int ret; if (board_id == NULL) { ERR("no board specified"); return -1; } board = find_board(board_id); if (board == NULL) { ERR("unknown/unsupported board id \"%s\"", board_id); return -1; } if (kernel_info.file_name == NULL) { ERR("no kernel image specified"); return -1; } ret = get_file_stat(&kernel_info); if (ret) return ret; if (kernel_info.file_size > board->kernel_len) { ERR("kernel image is too big"); return -1; } if (rootfs_info.file_name == NULL) { ERR("no rootfs image specified"); return -1; } ret = get_file_stat(&rootfs_info); if (ret) return ret; if (rootfs_info.file_size > board->rootfs_len) { ERR("rootfs image is too big"); return -1; } if (ofname == NULL) { ERR("no output file specified"); return -1; } return 0; } static int write_fw(char *data, int len) { FILE *f; int ret = EXIT_FAILURE; f = fopen(ofname, "w"); if (f == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } errno = 0; fwrite(data, len, 1, f); if (errno) { ERRS("unable to write output file"); goto out_flush; } DBG("firmware file \"%s\" completed", ofname); ret = EXIT_SUCCESS; out_flush: fflush(f); fclose(f); if (ret != EXIT_SUCCESS) { unlink(ofname); } out: return ret; } static int build_fw(void) { int buflen; char *buf; char *p; int ret = EXIT_FAILURE; int writelen = 0; uint32_t crc; struct fw_header *hdr; struct fw_tail *tail; buflen = 3 * sizeof(struct fw_header) + kernel_info.file_size + rootfs_info.file_size + 3 * sizeof(struct fw_tail); buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto out; } p = buf; memset(p, 0, buflen); /* fill firmware header */ hdr = (struct fw_header *) p; hdr->magic = HOST_TO_LE32(MAGIC_FIRMWARE); hdr->length = HOST_TO_LE32(buflen - sizeof(struct fw_header)); p += sizeof(struct fw_header); /* fill kernel block header */ hdr = (struct fw_header *) p; hdr->magic = HOST_TO_LE32(MAGIC_KERNEL); hdr->length = HOST_TO_LE32(kernel_info.file_size + sizeof(struct fw_tail)); p += sizeof(struct fw_header); /* read kernel data */ ret = read_to_buf(&kernel_info, p); if (ret) goto out_free_buf; /* fill firmware tail */ tail = (struct fw_tail *) (p + kernel_info.file_size); tail->hw_id = HOST_TO_BE32(board->hw_id); tail->crc = HOST_TO_BE32(cyg_crc32(p, kernel_info.file_size + sizeof(struct fw_tail) - 4)); p += kernel_info.file_size + sizeof(struct fw_tail); /* fill rootfs block header */ hdr = (struct fw_header *) p; hdr->magic = HOST_TO_LE32(MAGIC_ROOTFS); hdr->length = HOST_TO_LE32(rootfs_info.file_size + sizeof(struct fw_tail)); p += sizeof(struct fw_header); /* read rootfs data */ ret = read_to_buf(&rootfs_info, p); if (ret) goto out_free_buf; /* fill firmware tail */ tail = (struct fw_tail *) (p + rootfs_info.file_size); tail->hw_id = HOST_TO_BE32(board->hw_id); tail->crc = HOST_TO_BE32(cyg_crc32(p, rootfs_info.file_size + sizeof(struct fw_tail) - 4)); p += rootfs_info.file_size + sizeof(struct fw_tail); /* fill firmware tail */ tail = (struct fw_tail *) p; tail->hw_id = HOST_TO_BE32(board->hw_id); tail->crc = HOST_TO_BE32(cyg_crc32(buf + sizeof(struct fw_header), buflen - sizeof(struct fw_header) - 4)); ret = write_fw(buf, buflen); if (ret) goto out_free_buf; ret = EXIT_SUCCESS; out_free_buf: free(buf); out: return ret; } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; int err; FILE *outfile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "B:k:r:o:h"); if (c == -1) break; switch (c) { case 'B': board_id = optarg; break; case 'k': kernel_info.file_name = optarg; break; case 'r': rootfs_info.file_name = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } ret = check_options(); if (ret) goto out; ret = build_fw(); out: return ret; } ================================================ FILE: src/firmware-tools/mkzynfw.c ================================================ /* * * Copyright (C) 2007-2008 OpenWrt.org * Copyright (C) 2007-2008 Gabor Juhos * * This code was based on the information of the ZyXEL's firmware * image format written by Kolja Waschk, can be found at: * http://www.ixo.de/info/zyxel_uclinux * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #include /* for __BYTE_ORDER */ #if defined(__CYGWIN__) # include #endif #include "zynos.h" #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) # define LE16_TO_HOST(x) (x) # define LE32_TO_HOST(x) (x) # define HOST_TO_BE16(x) bswap_16(x) # define HOST_TO_BE32(x) bswap_32(x) # define BE16_TO_HOST(x) bswap_16(x) # define BE32_TO_HOST(x) bswap_32(x) #else # define HOST_TO_BE16(x) (x) # define HOST_TO_BE32(x) (x) # define BE16_TO_HOST(x) (x) # define BE32_TO_HOST(x) (x) # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) # define LE16_TO_HOST(x) bswap_16(x) # define LE32_TO_HOST(x) bswap_32(x) #endif #define ALIGN(x,y) (((x)+((y)-1)) & ~((y)-1)) #define MAX_NUM_BLOCKS 8 #define MAX_ARG_COUNT 32 #define MAX_ARG_LEN 1024 #define FILE_BUF_LEN (16*1024) struct csum_state{ int odd; uint32_t sum; uint32_t tmp; }; struct fw_block { uint32_t align; /* alignment of this block */ char *file_name; /* name of the file */ uint32_t file_size; /* length of the file */ char *mmap_name; /* name in the MMAP table */ int type; /* block type */ uint32_t padlen; uint8_t padc; }; #define BLOCK_TYPE_BOOTEXT 0 #define BLOCK_TYPE_RAW 1 struct fw_mmap { uint32_t addr; uint32_t size; uint32_t user_addr; uint32_t user_size; }; #define MMAP_DATA_SIZE 1024 #define MMAP_ALIGN 16 struct board_info { char *name; /* model name */ char *desc; /* description */ uint16_t vendor; /* vendor id */ uint16_t model; /* model id */ uint32_t flash_base; /* flash base address */ uint32_t flash_size; /* board flash size */ uint32_t code_start; /* code start address */ uint32_t romio_offs; /* offset of the firmware within the flash */ uint32_t bootext_size; /* maximum size of bootext block */ }; /* * Globals */ char *progname; char *ofname = NULL; int verblevel = 0; struct board_info *board = NULL; struct fw_block blocks[MAX_NUM_BLOCKS]; struct fw_block *bootext_block = NULL; int num_blocks = 0; #define ADM5120_FLASH_BASE 0xBFC00000 #define ADM5120_CODE_START 0x80008000 /* TODO: check values for AR7 */ #define AR7_FLASH_BASE 0xB0000000 #define AR7_CODE_START 0x94008000 #define ATHEROS_FLASH_BASE 0xBFC00000 #define ATHEROS_CODE_START 0x80e00000 #define AR71XX_FLASH_BASE 0xBFC00000 #define AR71XX_CODE_START 0x81E00000 #define BOARD(n, d, v, m, fb, fs, cs, fo) { \ .name = (n), .desc=(d), \ .vendor = (v), .model = (m), \ .flash_base = (fb), .flash_size = (fs)<<20, \ .code_start = (cs), .romio_offs = (fo), \ .bootext_size = BOOTEXT_DEF_SIZE \ } #define ADMBOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \ ADM5120_FLASH_BASE, fs, ADM5120_CODE_START, 0x8000) #define ADMBOARD2(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \ ADM5120_FLASH_BASE, fs, ADM5120_CODE_START, 0x10000) #define AR7BOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \ AR7_FLASH_BASE, fs, AR7_CODE_START, 0x8000) #define ATHEROSBOARD1(n, d, m, fs) BOARD(n, d, ZYNOS_VENDOR_ID_ZYXEL, m, \ ATHEROS_FLASH_BASE, fs, ATHEROS_CODE_START, 0x30000) #define AR71XXBOARD1(n, d, m, fs) { \ .name = (n), .desc=(d), \ .vendor = (ZYNOS_VENDOR_ID_ZYXEL), .model = (m), \ .flash_base = (AR71XX_FLASH_BASE), .flash_size = (fs)<<20, \ .code_start = (AR71XX_CODE_START), .romio_offs = (0x40000), \ .bootext_size = 0x30000 \ } static struct board_info boards[] = { /* * Infineon/ADMtek ADM5120 based boards */ ADMBOARD2("ES-2024A", "ZyXEL ES-2024A", ZYNOS_MODEL_ES_2024A, 4), ADMBOARD2("ES-2024PWR", "ZyXEL ES-2024PWR", ZYNOS_MODEL_ES_2024PWR, 4), ADMBOARD2("ES-2108", "ZyXEL ES-2108", ZYNOS_MODEL_ES_2108, 4), ADMBOARD2("ES-2108-F", "ZyXEL ES-2108-F", ZYNOS_MODEL_ES_2108_F, 4), ADMBOARD2("ES-2108-G", "ZyXEL ES-2108-G", ZYNOS_MODEL_ES_2108_G, 4), ADMBOARD2("ES-2108-LC", "ZyXEL ES-2108-LC", ZYNOS_MODEL_ES_2108_LC, 4), ADMBOARD2("ES-2108PWR", "ZyXEL ES-2108PWR", ZYNOS_MODEL_ES_2108PWR, 4), ADMBOARD1("HS-100", "ZyXEL HomeSafe 100", ZYNOS_MODEL_HS_100, 2), ADMBOARD1("HS-100W", "ZyXEL HomeSafe 100W", ZYNOS_MODEL_HS_100W, 2), ADMBOARD1("P-334", "ZyXEL Prestige 334", ZYNOS_MODEL_P_334, 2), ADMBOARD1("P-334U", "ZyXEL Prestige 334U", ZYNOS_MODEL_P_334U, 4), ADMBOARD1("P-334W", "ZyXEL Prestige 334W", ZYNOS_MODEL_P_334W, 2), ADMBOARD1("P-334WH", "ZyXEL Prestige 334WH", ZYNOS_MODEL_P_334WH, 4), ADMBOARD1("P-334WHD", "ZyXEL Prestige 334WHD", ZYNOS_MODEL_P_334WHD, 4), ADMBOARD1("P-334WT", "ZyXEL Prestige 334WT", ZYNOS_MODEL_P_334WT, 4), ADMBOARD1("P-335", "ZyXEL Prestige 335", ZYNOS_MODEL_P_335, 4), ADMBOARD1("P-335Plus", "ZyXEL Prestige 335Plus", ZYNOS_MODEL_P_335PLUS, 4), ADMBOARD1("P-335U", "ZyXEL Prestige 335U", ZYNOS_MODEL_P_335U, 4), ADMBOARD1("P-335WT", "ZyXEL Prestige 335WT", ZYNOS_MODEL_P_335WT, 4), { .name = "P-2602HW-D1A", .desc = "ZyXEL P-2602HW-D1A", .vendor = ZYNOS_VENDOR_ID_ZYXEL, .model = ZYNOS_MODEL_P_2602HW_D1A, .flash_base = AR7_FLASH_BASE, .flash_size = 4*1024*1024, .code_start = 0x94008000, .romio_offs = 0x20000, .bootext_size = BOOTEXT_DEF_SIZE, }, #if 0 /* * Texas Instruments AR7 based boards */ AR7BOARD1("P-660H-61", "ZyXEL P-660H-61", ZYNOS_MODEL_P_660H_61, 2), AR7BOARD1("P-660H-63", "ZyXEL P-660H-63", ZYNOS_MODEL_P_660H_63, 2), AR7BOARD1("P-660H-D1", "ZyXEL P-660H-D1", ZYNOS_MODEL_P_660H_D1, 2), AR7BOARD1("P-660H-D3", "ZyXEL P-660H-D3", ZYNOS_MODEL_P_660H_D3, 2), AR7BOARD1("P-660HW-61", "ZyXEL P-660HW-61", ZYNOS_MODEL_P_660HW_61, 2), AR7BOARD1("P-660HW-63", "ZyXEL P-660HW-63", ZYNOS_MODEL_P_660HW_63, 2), AR7BOARD1("P-660HW-67", "ZyXEL P-660HW-67", ZYNOS_MODEL_P_660HW_67, 2), AR7BOARD1("P-660HW-D1", "ZyXEL P-660HW-D1", ZYNOS_MODEL_P_660HW_D1, 2), AR7BOARD1("P-660HW-D3", "ZyXEL P-660HW-D3", ZYNOS_MODEL_P_660HW_D3, 2), AR7BOARD1("P-660R-61", "ZyXEL P-660R-61", ZYNOS_MODEL_P_660R_61, 2), AR7BOARD1("P-660R-61C", "ZyXEL P-660R-61C", ZYNOS_MODEL_P_660R_61C, 2), AR7BOARD1("P-660R-63", "ZyXEL P-660R-63", ZYNOS_MODEL_P_660R_63, 2), AR7BOARD1("P-660R-63C", "ZyXEL P-660R-63C", ZYNOS_MODEL_P_660R_63C, 2), AR7BOARD1("P-660R-67", "ZyXEL P-660R-67", ZYNOS_MODEL_P_660R_67, 2), AR7BOARD1("P-660R-D1", "ZyXEL P-660R-D1", ZYNOS_MODEL_P_660R_D1, 2), AR7BOARD1("P-660R-D3", "ZyXEL P-660R-D3", ZYNOS_MODEL_P_660R_D3, 2), #endif { .name = "O2SURF", .desc = "O2 DSL Surf & Phone", .vendor = ZYNOS_VENDOR_ID_O2, .model = ZYNOS_MODEL_O2SURF, .flash_base = AR7_FLASH_BASE, .flash_size = 8*1024*1024, .code_start = 0x94014000, .romio_offs = 0x40000, .bootext_size = BOOTEXT_DEF_SIZE, }, /* :x */ ATHEROSBOARD1("NBG-318S", "ZyXEL NBG-318S", ZYNOS_MODEL_NBG_318S, 4), /* * Atheros ar71xx based boards */ AR71XXBOARD1("NBG-460N", "ZyXEL NBG-460N", ZYNOS_MODEL_NBG_460N, 4), {.name = NULL} }; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) #define WARN(fmt, ...) do { \ fprintf(stderr, "[%s] *** warning: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define DBG(lev, fmt, ...) do { \ if (verblevel < lev) \ break;\ fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \ } while (0) #define ERR_FATAL -1 #define ERR_INVALID_IMAGE -2 /* * Helper routines */ void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -B create image for the board specified with .\n" " valid values:\n" ); for (board = boards; board->name != NULL; board++){ fprintf(stream, " %-12s= %s\n", board->name, board->desc); }; fprintf(stream, " -b [:]\n" " add boot extension block to the image\n" " -r [:]\n" " add raw block to the image\n" " -o write output to the file \n" " -h show this screen\n" ); exit(status); } /* * argument parsing */ int str2u32(char *arg, uint32_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err)) { return -1; } *val = t; return 0; } int str2u16(char *arg, uint16_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x10000)) { return -1; } *val = t & 0xFFFF; return 0; } int str2u8(char *arg, uint8_t *val) { char *err = NULL; uint32_t t; errno=0; t = strtoul(arg, &err, 0); if (errno || (err==arg) || ((err != NULL) && *err) || (t >= 0x100)) { return -1; } *val = t & 0xFF; return 0; } int str2sig(char *arg, uint32_t *sig) { if (strlen(arg) != 4) return -1; *sig = arg[0] | (arg[1] << 8) | (arg[2] << 16) | (arg[3] << 24); return 0; } int parse_arg(char *arg, char *buf, char *argv[]) { int res = 0; size_t argl; char *tok; char **ap = &buf; int i; memset(argv, 0, MAX_ARG_COUNT * sizeof(void *)); if ((arg == NULL)) { /* no arguments */ return 0; } argl = strlen(arg); if (argl == 0) { /* no arguments */ return 0; } if (argl >= MAX_ARG_LEN) { /* argument is too long */ argl = MAX_ARG_LEN-1; } memcpy(buf, arg, argl); buf[argl] = '\0'; for (i = 0; i < MAX_ARG_COUNT; i++) { tok = strsep(ap, ":"); if (tok == NULL) { break; } #if 0 else if (tok[0] == '\0') { break; } #endif argv[i] = tok; res++; } return res; } int required_arg(char c, char *arg) { if (arg == NULL || *arg != '-') return 0; ERR("option -%c requires an argument\n", c); return -1; } int is_empty_arg(char *arg) { int ret = 1; if (arg != NULL) { if (*arg) ret = 0; }; return ret; } void csum_init(struct csum_state *css) { css->odd = 0; css->sum = 0; css->tmp = 0; } void csum_update(uint8_t *p, uint32_t len, struct csum_state *css) { if (len == 0) return; if (css->odd) { css->sum += (css->tmp << 8) + p[0]; if (css->sum > 0xFFFF) { css->sum += 1; css->sum &= 0xFFFF; } css->odd = 0; len--; p++; } for ( ; len > 1; len -= 2, p +=2 ) { css->sum += (p[0] << 8) + p[1]; if (css->sum > 0xFFFF) { css->sum += 1; css->sum &= 0xFFFF; } } if (len == 1){ css->tmp = p[0]; css->odd = 1; } } uint16_t csum_get(struct csum_state *css) { char pad = 0; csum_update(&pad, 1, css); return css->sum; } uint16_t csum_buf(uint8_t *p, uint32_t len) { struct csum_state css; csum_init(&css); csum_update(p, len, &css); return csum_get(&css); } /* * routines to write data to the output file */ int write_out_data(FILE *outfile, uint8_t *data, size_t len, struct csum_state *css) { errno = 0; fwrite(data, len, 1, outfile); if (errno) { ERR("unable to write output file"); return -1; } if (css) { csum_update(data, len, css); } return 0; } int write_out_padding(FILE *outfile, size_t len, uint8_t padc, struct csum_state *css) { uint8_t buf[512]; size_t buflen = sizeof(buf); memset(buf, padc, buflen); while (len > 0) { if (len < buflen) buflen = len; if (write_out_data(outfile, buf, buflen, css)) return -1; len -= buflen; } return 0; } int write_out_data_align(FILE *outfile, uint8_t *data, size_t len, size_t align, struct csum_state *css) { size_t padlen; int res; res = write_out_data(outfile, data, len, css); if (res) return res; padlen = ALIGN(len,align) - len; res = write_out_padding(outfile, padlen, 0xFF, css); return res; } int write_out_header(FILE *outfile, struct zyn_rombin_hdr *hdr) { struct zyn_rombin_hdr t; errno = 0; if (fseek(outfile, 0, SEEK_SET) != 0) { ERRS("fseek failed on output file"); return -1; } /* setup temporary header fields */ memset(&t, 0, sizeof(t)); t.addr = HOST_TO_BE32(hdr->addr); memcpy(&t.sig, ROMBIN_SIGNATURE, ROMBIN_SIG_LEN); t.type = hdr->type; t.flags = hdr->flags; t.osize = HOST_TO_BE32(hdr->osize); t.csize = HOST_TO_BE32(hdr->csize); t.ocsum = HOST_TO_BE16(hdr->ocsum); t.ccsum = HOST_TO_BE16(hdr->ccsum); t.mmap_addr = HOST_TO_BE32(hdr->mmap_addr); DBG(2, "hdr.addr = 0x%08x", hdr->addr); DBG(2, "hdr.type = 0x%02x", hdr->type); DBG(2, "hdr.osize = 0x%08x", hdr->osize); DBG(2, "hdr.csize = 0x%08x", hdr->csize); DBG(2, "hdr.flags = 0x%02x", hdr->flags); DBG(2, "hdr.ocsum = 0x%04x", hdr->ocsum); DBG(2, "hdr.ccsum = 0x%04x", hdr->ccsum); DBG(2, "hdr.mmap_addr = 0x%08x", hdr->mmap_addr); return write_out_data(outfile, (uint8_t *)&t, sizeof(t), NULL); } int write_out_mmap(FILE *outfile, struct fw_mmap *mmap, struct csum_state *css) { struct zyn_mmt_hdr *mh; uint8_t buf[MMAP_DATA_SIZE]; uint32_t user_size; char *data; int res; memset(buf, 0, sizeof(buf)); mh = (struct zyn_mmt_hdr *)buf; /* TODO: needs to recreate the memory map too? */ mh->count=0; /* Build user data section */ data = buf+sizeof(*mh); data += sprintf(data, "Vendor 1 %d", board->vendor); *data++ = '\0'; data += sprintf(data, "Model 1 %d", BE16_TO_HOST(board->model)); *data++ = '\0'; /* TODO: make hardware version configurable? */ data += sprintf(data, "HwVerRange 2 %d %d", 0, 0); *data++ = '\0'; user_size = (uint8_t *)data - buf; mh->user_start= HOST_TO_BE32(mmap->addr+sizeof(*mh)); mh->user_end= HOST_TO_BE32(mmap->addr+user_size); mh->csum = HOST_TO_BE16(csum_buf(buf+sizeof(*mh), user_size)); res = write_out_data(outfile, buf, sizeof(buf), css); return res; } int block_stat_file(struct fw_block *block) { struct stat st; int res; if (block->file_name == NULL) return 0; res = stat(block->file_name, &st); if (res){ ERRS("stat failed on %s", block->file_name); return res; } block->file_size = st.st_size; return 0; } int read_magic(uint16_t *magic) { FILE *f; int res; errno = 0; f = fopen(bootext_block->file_name,"r"); if (errno) { ERRS("unable to open file: %s", bootext_block->file_name); return -1; } errno = 0; fread(magic, 2, 1, f); if (errno != 0) { ERRS("unable to read from file: %s", bootext_block->file_name); res = -1; goto err; } res = 0; err: fclose(f); return res; } int write_out_file(FILE *outfile, char *name, size_t len, struct csum_state *css) { char buf[FILE_BUF_LEN]; size_t buflen = sizeof(buf); FILE *f; int res; DBG(2, "writing out file, name=%s, len=%d", name, len); errno = 0; f = fopen(name,"r"); if (errno) { ERRS("unable to open file: %s", name); return -1; } while (len > 0) { if (len < buflen) buflen = len; /* read data from source file */ errno = 0; fread(buf, buflen, 1, f); if (errno != 0) { ERRS("unable to read from file: %s",name); res = -1; break; } res = write_out_data(outfile, buf, buflen, css); if (res) break; len -= buflen; } fclose(f); return res; } int write_out_block(FILE *outfile, struct fw_block *block, struct csum_state *css) { int res; if (block == NULL) return 0; if (block->file_name == NULL) return 0; if (block->file_size == 0) return 0; res = write_out_file(outfile, block->file_name, block->file_size, css); return res; } int write_out_image(FILE *outfile) { struct fw_block *block; struct fw_mmap mmap; struct zyn_rombin_hdr hdr; struct csum_state css; int i, res; uint32_t offset; uint32_t padlen; uint16_t csum; uint16_t t; /* setup header fields */ memset(&hdr, 0, sizeof(hdr)); hdr.addr = board->code_start; hdr.type = OBJECT_TYPE_BOOTEXT; hdr.flags = ROMBIN_FLAG_OCSUM; offset = board->romio_offs; res = write_out_header(outfile, &hdr); if (res) return res; offset += sizeof(hdr); csum_init(&css); res = write_out_block(outfile, bootext_block, &css); if (res) return res; offset += bootext_block->file_size; if (offset > (board->romio_offs + board->bootext_size)) { ERR("bootext file '%s' is too big", bootext_block->file_name); return -1; } padlen = ALIGN(offset, MMAP_ALIGN) - offset; res = write_out_padding(outfile, padlen, 0xFF, &css); if (res) return res; offset += padlen; mmap.addr = board->flash_base + offset; res = write_out_mmap(outfile, &mmap, &css); if (res) return res; offset += MMAP_DATA_SIZE; if ((offset - board->romio_offs) < board->bootext_size) { padlen = board->romio_offs + board->bootext_size - offset; res = write_out_padding(outfile, padlen, 0xFF, &css); if (res) return res; offset += padlen; DBG(2, "bootext end at %08x", offset); } for (i = 0; i < num_blocks; i++) { block = &blocks[i]; if (block->type == BLOCK_TYPE_BOOTEXT) continue; padlen = ALIGN(offset, block->align) - offset; res = write_out_padding(outfile, padlen, 0xFF, &css); if (res) return res; offset += padlen; res = write_out_block(outfile, block, &css); if (res) return res; offset += block->file_size; } padlen = ALIGN(offset, 4) - offset; res = write_out_padding(outfile, padlen, 0xFF, &css); if (res) return res; offset += padlen; csum = csum_get(&css); hdr.mmap_addr = mmap.addr; hdr.osize = 2; res = read_magic(&hdr.ocsum); if (res) return res; hdr.ocsum = BE16_TO_HOST(hdr.ocsum); if (csum <= hdr.ocsum) t = hdr.ocsum - csum; else t = hdr.ocsum - csum - 1; DBG(2, "ocsum=%04x, csum=%04x, fix=%04x", hdr.ocsum, csum, t); t = HOST_TO_BE16(t); res = write_out_data(outfile, (uint8_t *)&t, 2, NULL); if (res) return res; res = write_out_header(outfile, &hdr); return res; } struct board_info * find_board(char *name) { struct board_info *ret; struct board_info *board; ret = NULL; for (board = boards; board->name != NULL; board++){ if (strcasecmp(name, board->name) == 0) { ret = board; break; } }; return ret; } int parse_opt_board(char ch, char *arg) { DBG(1,"parsing board option: -%c %s", ch, arg); if (board != NULL) { ERR("only one board option allowed"); return -1; } if (required_arg(ch, arg)) return -1; board = find_board(arg); if (board == NULL){ ERR("invalid/unknown board specified: %s", arg); return -1; } return 0; } int parse_opt_ofname(char ch, char *arg) { if (ofname != NULL) { ERR("only one output file allowed"); return -1; } if (required_arg(ch, arg)) return -1; ofname = arg; return 0; } int parse_opt_block(char ch, char *arg) { char buf[MAX_ARG_LEN]; char *argv[MAX_ARG_COUNT]; int argc; char *p; struct fw_block *block; int i; if ( num_blocks >= MAX_NUM_BLOCKS ) { ERR("too many blocks specified"); return -1; } block = &blocks[num_blocks++]; /* setup default field values */ block->padc = 0xFF; switch(ch) { case 'b': if (bootext_block) { ERR("only one boot extension block allowed"); break; } block->type = BLOCK_TYPE_BOOTEXT; bootext_block = block; break; case 'r': block->type = BLOCK_TYPE_RAW; break; } argc = parse_arg(arg, buf, argv); i = 0; p = argv[i++]; if (is_empty_arg(p)) { ERR("no file specified in %s", arg); return -1; } else { block->file_name = strdup(p); if (block->file_name == NULL) { ERR("not enough memory"); return -1; } } if (block->type == BLOCK_TYPE_BOOTEXT) return 0; p = argv[i++]; if (!is_empty_arg(p)) { if (str2u32(p, &block->align) != 0) { ERR("invalid block align in %s", arg); return -1; } } return 0; } int calc_block_offsets(int type, uint32_t *offset) { struct fw_block *block; uint32_t next_offs; uint32_t avail; int i, res; DBG(1,"calculating block offsets, starting with %lu", *offset); res = 0; for (i = 0; i < num_blocks; i++) { block = &blocks[i]; if (block->type != type) continue; next_offs = ALIGN(*offset, block->align); avail = board->flash_size - next_offs; if (block->file_size > avail) { ERR("file %s is too big, offset = %u, size=%u," " avail = %u, align = %u", block->file_name, (unsigned)next_offs, (unsigned)block->file_size, (unsigned)avail, (unsigned)block->align); res = -1; break; } block->padlen = next_offs - *offset; *offset += block->file_size; } return res; } int process_blocks(void) { struct fw_block *block; uint32_t offset; int i; int res; /* collecting file stats */ for (i = 0; i < num_blocks; i++) { block = &blocks[i]; res = block_stat_file(block); if (res) return res; } offset = board->romio_offs + bootext_block->file_size; res = calc_block_offsets(BLOCK_TYPE_RAW, &offset); return res; } int main(int argc, char *argv[]) { int optinvalid = 0; /* flag for invalid option */ int c; int res = EXIT_FAILURE; FILE *outfile; progname=basename(argv[0]); opterr = 0; /* could not print standard getopt error messages */ while ( 1 ) { optinvalid = 0; c = getopt(argc, argv, "b:B:ho:r:v"); if (c == -1) break; switch (c) { case 'b': case 'r': optinvalid = parse_opt_block(c,optarg); break; case 'B': optinvalid = parse_opt_board(c,optarg); break; case 'o': optinvalid = parse_opt_ofname(c,optarg); break; case 'v': verblevel++; break; case 'h': usage(EXIT_SUCCESS); break; default: optinvalid = 1; break; } if (optinvalid != 0 ) { ERR("invalid option: -%c", optopt); goto out; } } if (board == NULL) { ERR("no board specified"); goto out; } if (ofname == NULL) { ERR("no output file specified"); goto out; } if (optind < argc) { ERR("invalid option: %s", argv[optind]); goto out; } if (process_blocks() != 0) { goto out; } outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto out; } if (write_out_image(outfile) != 0) goto out_flush; DBG(1,"Image file %s completed.", ofname); res = EXIT_SUCCESS; out_flush: fflush(outfile); fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } out: return res; } ================================================ FILE: src/firmware-tools/motorola-bin.c ================================================ /* * motorola-bin.c * * Copyright (C) 2005-2006 Mike Baker, * Imre Kaloz * D. Hugh Redelmeier * OpenWrt.org * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* * Motorola's firmware flashing code requires an extra header. * The header is eight bytes (see struct motorola below). * This program will take a firmware file and create a new one * with this header: * motorola-bin --wr850g WR850G_V403.stripped.trx WR850G_V403.trx * * Note: Motorola's firmware is distributed with this header. * If you need to flash Motorola firmware on a router running OpenWRT, * you will to remove this header. Use the --strip flag: * motorola-bin --strip WR850G_V403.trx WR850G_V403.stripped.trx */ /* * February 1, 2006 * * Add support for for creating WA840G and WE800G images */ #include #include #include #include #include #include #include #include #include #include #define BPB 8 /* bits/byte */ static uint32_t crc32[1<> 1)) : (crc >> 1); crc32[n] = crc; } } static uint32_t crc32buf(unsigned char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for (; len; len--, buf++) crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB); return crc; } struct motorola { uint32_t crc; // crc32 of the remainder uint32_t flags; // unknown, 105770* }; static const struct model { char digit; /* a digit signifying model (historical) */ const char *name; uint32_t flags; } models[] = { { '1', "WR850G", 0x10577050LU }, { '2', "WA840G", 0x10577040LU }, { '3', "WE800G", 0x10577000LU }, { '\0', NULL, 0 } }; static void usage(const char *) __attribute__ (( __noreturn__ )); static void usage(const char *mess) { const struct model *m; fprintf(stderr, "Error: %s\n", mess); fprintf(stderr, "Usage: motorola-bin -device|--strip infile outfile\n"); fprintf(stderr, "Known devices: "); for (m = models; m->digit != '\0'; m++) fprintf(stderr, " %c - %s", m->digit, m->name); fprintf(stderr, "\n"); exit(1); } int main(int argc, char **argv) { off_t len; // of original firmware int fd; void *trx; // pointer to original firmware (mmmapped) struct motorola *firmware; // pionter to prefix + copy of original firmware uint32_t flags; // verify parameters if (argc != 4) usage("wrong number of arguments"); // mmap trx file if ((fd = open(argv[2], O_RDONLY)) < 0 || (len = lseek(fd, 0, SEEK_END)) < 0 || (trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) || close(fd) < 0) { fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno)); exit(1); } init_crc32(); if (strcmp(argv[1], "--strip") == 0) { const char *ugh = NULL; if (len < sizeof(struct motorola)) { ugh = "input file too short"; } else { const struct model *m; firmware = trx; if (htonl(crc32buf(trx + offsetof(struct motorola, flags), len - offsetof(struct motorola, flags))) != firmware->crc) ugh = "Invalid CRC"; for (m = models; ; m++) { if (m->digit == '\0') { if (ugh == NULL) ugh = "unrecognized flags field"; break; } if (firmware->flags == htonl(m->flags)) { fprintf(stderr, "Firmware for Motorola %s\n", m->name); break; } } } if (ugh != NULL) { fprintf(stderr, "%s\n", ugh); exit(3); } else { // all is well, write the file without the prefix if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0 || write(fd, trx + sizeof(struct motorola), len - sizeof(struct motorola)) != len - sizeof(struct motorola) || close(fd) < 0) { fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno)); exit(2); } } } else { // setup the firmware flags magic number const struct model *m; const char *df = argv[1]; if (*df != '-') usage("first argument must start with -"); if (*++df == '-') ++df; /* allow but don't require second - */ for (m = models; ; m++) { if (m->digit == '\0') usage("unrecognized device specified"); if ((df[0] == m->digit && df[1] == '\0') || strcasecmp(df, m->name) == 0) { flags = m->flags; break; } } // create a firmware image in memory // and copy the trx to it firmware = malloc(sizeof(struct motorola) + len); memcpy(&firmware[1], trx, len); // setup the motorola headers firmware->flags = htonl(flags); // CRC of flags + firmware firmware->crc = htonl(crc32buf((unsigned char *)&firmware->flags, sizeof(firmware->flags) + len)); // write the firmware if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0 || write(fd, firmware, sizeof(struct motorola) + len) != sizeof(struct motorola) + len || close(fd) < 0) { fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno)); exit(2); } free(firmware); } munmap(trx,len); return 0; } ================================================ FILE: src/firmware-tools/myloader.h ================================================ /* * Copyright (C) 2006-2008 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * */ #ifndef _MYLOADER_H_ #define _MYLOADER_H_ /* * Firmware file format: * *
* [] * ... * [] * * [] * ... * [] * * */ /* Myloader specific magic numbers */ #define MYLO_MAGIC_FIRMWARE 0x4C594D00 #define MYLO_MAGIC_20021103 0x20021103 #define MYLO_MAGIC_20021107 0x20021107 #define MYLO_MAGIC_SYS_PARAMS MYLO_MAGIC_20021107 #define MYLO_MAGIC_PARTITIONS MYLO_MAGIC_20021103 #define MYLO_MAGIC_BOARD_PARAMS MYLO_MAGIC_20021103 /* * Addresses of the data structures provided by MyLoader */ #define MYLO_MIPS_SYS_PARAMS 0x80000800 /* System Parameters */ #define MYLO_MIPS_BOARD_PARAMS 0x80000A00 /* Board Parameters */ #define MYLO_MIPS_PARTITIONS 0x80000C00 /* Partition Table */ #define MYLO_MIPS_BOOT_PARAMS 0x80000E00 /* Boot Parameters */ /* Vendor ID's (seems to be same as the PCI vendor ID's) */ #define VENID_COMPEX 0x11F6 /* Devices based on the ADM5120 */ #define DEVID_COMPEX_NP27G 0x0078 #define DEVID_COMPEX_NP28G 0x044C #define DEVID_COMPEX_NP28GHS 0x044E #define DEVID_COMPEX_WP54Gv1C 0x0514 #define DEVID_COMPEX_WP54G 0x0515 #define DEVID_COMPEX_WP54AG 0x0546 #define DEVID_COMPEX_WPP54AG 0x0550 #define DEVID_COMPEX_WPP54G 0x0555 /* Devices based on the Atheros AR2317 */ #define DEVID_COMPEX_NP25G 0x05e6 #define DEVID_COMPEX_WPE53G 0x05dc /* Devices based on the Atheros AR71xx */ #define DEVID_COMPEX_WP543 0x0640 #define DEVID_COMPEX_WPE72 0x0672 /* Devices based on the IXP422 */ #define DEVID_COMPEX_WP18 0x047E #define DEVID_COMPEX_NP18A 0x0489 /* Other devices */ #define DEVID_COMPEX_NP26G8M 0x03E8 #define DEVID_COMPEX_NP26G16M 0x03E9 struct mylo_fw_header { uint32_t magic; /* must be MYLO_MAGIC_FIRMWARE */ uint32_t crc; /* CRC of the whole firmware */ uint32_t res0; /* unknown/unused */ uint32_t res1; /* unknown/unused */ uint16_t vid; /* vendor ID */ uint16_t did; /* device ID */ uint16_t svid; /* sub vendor ID */ uint16_t sdid; /* sub device ID */ uint32_t rev; /* device revision */ uint32_t fwhi; /* FIXME: firmware version high? */ uint32_t fwlo; /* FIXME: firmware version low? */ uint32_t flags; /* firmware flags */ }; #define FW_FLAG_BOARD_PARAMS_WP 0x01 /* board parameters are write protected */ #define FW_FLAG_BOOT_SECTOR_WE 0x02 /* enable of write boot sectors (below 64K) */ struct mylo_fw_blockdesc { uint32_t type; /* block type */ uint32_t addr; /* relative address to flash start */ uint32_t dlen; /* size of block data in bytes */ uint32_t blen; /* total size of block in bytes */ }; #define FW_DESC_TYPE_UNUSED 0 #define FW_DESC_TYPE_USED 1 struct mylo_partition { uint16_t flags; /* partition flags */ uint16_t type; /* type of the partition */ uint32_t addr; /* relative address of the partition from the flash start */ uint32_t size; /* size of the partition in bytes */ uint32_t param; /* if this is the active partition, the MyLoader load code to this address */ }; #define PARTITION_FLAG_ACTIVE 0x8000 /* this is the active partition, * MyLoader loads firmware from here */ #define PARTITION_FLAG_ISRAM 0x2000 /* FIXME: this is a RAM partition? */ #define PARTIIION_FLAG_RAMLOAD 0x1000 /* FIXME: load this partition into the RAM? */ #define PARTITION_FLAG_PRELOAD 0x0800 /* the partition data preloaded to RAM * before decompression */ #define PARTITION_FLAG_LZMA 0x0100 /* the partition data compressed with LZMA */ #define PARTITION_FLAG_HAVEHDR 0x0002 /* the partition data have a header */ #define PARTITION_TYPE_FREE 0 #define PARTITION_TYPE_USED 1 #define MYLO_MAX_PARTITIONS 8 /* maximum number of partitions in the partition table */ struct mylo_partition_table { uint32_t magic; /* must be MYLO_MAGIC_PARTITIONS */ uint32_t res0; /* unknown/unused */ uint32_t res1; /* unknown/unused */ uint32_t res2; /* unknown/unused */ struct mylo_partition partitions[MYLO_MAX_PARTITIONS]; }; struct mylo_partition_header { uint32_t len; /* length of the partition data */ uint32_t crc; /* CRC value of the partition data */ }; struct mylo_system_params { uint32_t magic; /* must be MYLO_MAGIC_SYS_PARAMS */ uint32_t res0; uint32_t res1; uint32_t mylo_ver; uint16_t vid; /* Vendor ID */ uint16_t did; /* Device ID */ uint16_t svid; /* Sub Vendor ID */ uint16_t sdid; /* Sub Device ID */ uint32_t rev; /* device revision */ uint32_t fwhi; uint32_t fwlo; uint32_t tftp_addr; uint32_t prog_start; uint32_t flash_size; /* Size of boot FLASH in bytes */ uint32_t dram_size; /* Size of onboard RAM in bytes */ }; struct mylo_eth_addr { uint8_t mac[6]; uint8_t csum[2]; }; #define MYLO_ETHADDR_COUNT 8 /* maximum number of ethernet address in the board parameters */ struct mylo_board_params { uint32_t magic; /* must be MYLO_MAGIC_BOARD_PARAMS */ uint32_t res0; uint32_t res1; uint32_t res2; struct mylo_eth_addr addr[MYLO_ETHADDR_COUNT]; }; #endif /* _MYLOADER_H_*/ ================================================ FILE: src/firmware-tools/nand_ecc.c ================================================ /* * calculate ecc code for nand flash * * Copyright (C) 2008 yajin * Copyright (C) 2009 Felix Fietkau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 or * (at your option) version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include #include #include #define DEF_NAND_PAGE_SIZE 2048 #define DEF_NAND_OOB_SIZE 64 #define DEF_NAND_ECC_OFFSET 0x28 static int page_size = DEF_NAND_PAGE_SIZE; static int oob_size = DEF_NAND_OOB_SIZE; static int ecc_offset = DEF_NAND_ECC_OFFSET; /* * Pre-calculated 256-way 1 byte column parity */ static const uint8_t nand_ecc_precalc_table[] = { 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 }; /** * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block * @dat: raw data * @ecc_code: buffer for ECC */ int nand_calculate_ecc(const uint8_t *dat, uint8_t *ecc_code) { uint8_t idx, reg1, reg2, reg3, tmp1, tmp2; int i; /* Initialize variables */ reg1 = reg2 = reg3 = 0; /* Build up column parity */ for(i = 0; i < 256; i++) { /* Get CP0 - CP5 from table */ idx = nand_ecc_precalc_table[*dat++]; reg1 ^= (idx & 0x3f); /* All bit XOR = 1 ? */ if (idx & 0x40) { reg3 ^= (uint8_t) i; reg2 ^= ~((uint8_t) i); } } /* Create non-inverted ECC code from line parity */ tmp1 = (reg3 & 0x80) >> 0; /* B7 -> B7 */ tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */ tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */ tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */ tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */ tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */ tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */ tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */ tmp2 = (reg3 & 0x08) << 4; /* B3 -> B7 */ tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */ tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */ tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */ tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */ tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */ tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */ tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */ /* Calculate final ECC code */ #ifdef CONFIG_MTD_NAND_ECC_SMC ecc_code[0] = ~tmp2; ecc_code[1] = ~tmp1; #else ecc_code[0] = ~tmp1; ecc_code[1] = ~tmp2; #endif ecc_code[2] = ((~reg1) << 2) | 0x03; return 0; } /* * usage: bb-nandflash-ecc start_address size */ void usage(const char *prog) { fprintf(stderr, "Usage: %s [options] \n" "Options:\n" " -p NAND page size (default: %d)\n" " -o NAND OOB size (default: %d)\n" " -e NAND ECC offset (default: %d)\n" "\n", prog, DEF_NAND_PAGE_SIZE, DEF_NAND_OOB_SIZE, DEF_NAND_ECC_OFFSET); exit(1); } /*start_address/size does not include oob */ int main(int argc, char **argv) { uint8_t *page_data = NULL; uint8_t *ecc_data; int infd = -1, outfd = -1; int ret = 1; ssize_t bytes; int ch; while ((ch = getopt(argc, argv, "e:o:p:")) != -1) { switch(ch) { case 'p': page_size = strtoul(optarg, NULL, 0); break; case 'o': oob_size = strtoul(optarg, NULL, 0); break; case 'e': ecc_offset = strtoul(optarg, NULL, 0); break; default: usage(argv[0]); } } argc -= optind; if (argc < 2) usage(argv[0]); argv += optind; infd = open(argv[0], O_RDONLY, 0); if (infd < 0) { perror("open input file"); goto out; } outfd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644); if (outfd < 0) { perror("open output file"); goto out; } page_data = malloc(page_size + oob_size); while ((bytes = read(infd, page_data, page_size)) == page_size) { int j; ecc_data = page_data + page_size + ecc_offset; for (j = 0; j < page_size / 256; j++) { nand_calculate_ecc(page_data + j * 256, ecc_data); ecc_data += 3; } write(outfd, page_data, page_size + oob_size); } ret = 0; out: if (infd >= 0) close(infd); if (outfd >= 0) close(outfd); if (page_data) free(page_data); return ret; } ================================================ FILE: src/firmware-tools/osbridge-crc.c ================================================ /* * Copyright (C) 2009 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include #if (__BYTE_ORDER == __LITTLE_ENDIAN) # define HOST_TO_LE16(x) (x) # define HOST_TO_LE32(x) (x) # define LE16_TO_HOST(x) (x) # define LE32_TO_HOST(x) (x) #else # define HOST_TO_LE16(x) bswap_16(x) # define HOST_TO_LE32(x) bswap_32(x) # define LE16_TO_HOST(x) bswap_16(x) # define LE32_TO_HOST(x) bswap_32(x) #endif uint32_t crc32buf(char *buf, size_t len); /* * Globals */ static char *ifname; static char *progname; static char *ofname; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -i read input from the file \n" " -o write output to the file \n" " -h show this screen\n" ); exit(status); } int main(int argc, char *argv[]) { int res = EXIT_FAILURE; int buflen; int err; struct stat st; char *buf; uint32_t *hdr; uint32_t crc; FILE *outfile, *infile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "i:o:h"); if (c == -1) break; switch (c) { case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } if (ifname == NULL) { ERR("no input file specified"); goto err; } if (ofname == NULL) { ERR("no output file specified"); goto err; } err = stat(ifname, &st); if (err){ ERRS("stat failed on %s", ifname); goto err; } buflen = st.st_size; buf = malloc(buflen); if (!buf) { ERR("no memory for buffer\n"); goto err; } infile = fopen(ifname, "r"); if (infile == NULL) { ERRS("could not open \"%s\" for reading", ifname); goto err_free; } errno = 0; fread(buf, buflen, 1, infile); if (errno != 0) { ERRS("unable to read from file %s", ifname); goto err_close_in; } crc = crc32buf(buf, buflen); hdr = (uint32_t *)buf; *hdr = HOST_TO_LE32(crc); outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto err_close_in; } errno = 0; fwrite(buf, buflen, 1, outfile); if (errno) { ERRS("unable to write to file %s", ofname); goto err_close_out; } res = EXIT_SUCCESS; out_flush: fflush(outfile); err_close_out: fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } err_close_in: fclose(infile); err_free: free(buf); err: return res; } /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32buf(char *buf, size_t len) { uint32_t crc; crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc ^ 0xFFFFFFFF; } ================================================ FILE: src/firmware-tools/pc1crypt.c ================================================ /* * Copyright (C) 2009 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * This code was based on: * PC1 Cipher Algorithm ( Pukall Cipher 1 ) * By Alexander PUKALL 1991 * free code no restriction to use * please include the name of the Author in the final software * the Key is 128 bits * http://membres.lycos.fr/pc1/ * */ #include #include #include #include #include /* for unlink() */ #include #include /* for getopt() */ #include #include #include struct pc1_ctx { unsigned short ax; unsigned short bx; unsigned short cx; unsigned short dx; unsigned short si; unsigned short tmp; unsigned short x1a2; unsigned short x1a0[8]; unsigned short res; unsigned short i; unsigned short inter; unsigned short cfc; unsigned short cfd; unsigned short compte; unsigned char cle[17]; short c; }; static void pc1_finish(struct pc1_ctx *pc1) { /* erase all variables */ memset(pc1, 0, sizeof(struct pc1_ctx)); } static void pc1_code(struct pc1_ctx *pc1) { pc1->dx = pc1->x1a2 + pc1->i; pc1->ax = pc1->x1a0[pc1->i]; pc1->cx = 0x015a; pc1->bx = 0x4e35; pc1->tmp = pc1->ax; pc1->ax = pc1->si; pc1->si = pc1->tmp; pc1->tmp = pc1->ax; pc1->ax = pc1->dx; pc1->dx = pc1->tmp; if (pc1->ax != 0) { pc1->ax = pc1->ax * pc1->bx; } pc1->tmp = pc1->ax; pc1->ax = pc1->cx; pc1->cx = pc1->tmp; if (pc1->ax != 0) { pc1->ax = pc1->ax * pc1->si; pc1->cx = pc1->ax + pc1->cx; } pc1->tmp = pc1->ax; pc1->ax = pc1->si; pc1->si = pc1->tmp; pc1->ax = pc1->ax * pc1->bx; pc1->dx = pc1->cx + pc1->dx; pc1->ax = pc1->ax + 1; pc1->x1a2 = pc1->dx; pc1->x1a0[pc1->i] = pc1->ax; pc1->res = pc1->ax ^ pc1->dx; pc1->i = pc1->i + 1; } static void pc1_assemble(struct pc1_ctx *pc1) { pc1->x1a0[0] = (pc1->cle[0] * 256) + pc1->cle[1]; pc1_code(pc1); pc1->inter = pc1->res; pc1->x1a0[1] = pc1->x1a0[0] ^ ((pc1->cle[2]*256) + pc1->cle[3]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[2] = pc1->x1a0[1] ^ ((pc1->cle[4]*256) + pc1->cle[5]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[3] = pc1->x1a0[2] ^ ((pc1->cle[6]*256) + pc1->cle[7]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[4] = pc1->x1a0[3] ^ ((pc1->cle[8]*256) + pc1->cle[9]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[5] = pc1->x1a0[4] ^ ((pc1->cle[10]*256) + pc1->cle[11]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[6] = pc1->x1a0[5] ^ ((pc1->cle[12]*256) + pc1->cle[13]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->x1a0[7] = pc1->x1a0[6] ^ ((pc1->cle[14]*256) + pc1->cle[15]); pc1_code(pc1); pc1->inter = pc1->inter ^ pc1->res; pc1->i = 0; } static unsigned char pc1_decrypt(struct pc1_ctx *pc1, short c) { pc1_assemble(pc1); pc1->cfc = pc1->inter >> 8; pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */ c = c ^ (pc1->cfc ^ pc1->cfd); for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) { /* we mix the plaintext byte with the key */ pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c; } return c; } static unsigned char pc1_encrypt(struct pc1_ctx *pc1, short c) { pc1_assemble(pc1); pc1->cfc = pc1->inter >> 8; pc1->cfd = pc1->inter & 255; /* cfc^cfd = random byte */ for (pc1->compte = 0; pc1->compte <= 15; pc1->compte++) { /* we mix the plaintext byte with the key */ pc1->cle[pc1->compte] = pc1->cle[pc1->compte] ^ c; } c = c ^ (pc1->cfc ^ pc1->cfd); return c; } static void pc1_init(struct pc1_ctx *pc1) { memset(pc1, 0, sizeof(struct pc1_ctx)); /* ('Remsaalps!123456') is the key used, you can change it */ strcpy(pc1->cle, "Remsaalps!123456"); } static void pc1_decrypt_buf(struct pc1_ctx *pc1, unsigned char *buf, unsigned len) { unsigned i; for (i = 0; i < len; i++) buf[i] = pc1_decrypt(pc1, buf[i]); } static void pc1_encrypt_buf(struct pc1_ctx *pc1, unsigned char *buf, unsigned len) { unsigned i; for (i = 0; i < len; i++) buf[i] = pc1_encrypt(pc1, buf[i]); } /* * Globals */ static char *ifname; static char *progname; static char *ofname; static int decrypt; /* * Message macros */ #define ERR(fmt, ...) do { \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__ ); \ } while (0) #define ERRS(fmt, ...) do { \ int save = errno; \ fflush(0); \ fprintf(stderr, "[%s] *** error: " fmt "\n", \ progname, ## __VA_ARGS__, strerror(save)); \ } while (0) void usage(int status) { FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; struct board_info *board; fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); fprintf(stream, "\n" "Options:\n" " -d decrypt instead of encrypt" " -i read input from the file \n" " -o write output to the file \n" " -h show this screen\n" ); exit(status); } #define BUFSIZE (64 * 1024) int main(int argc, char *argv[]) { struct pc1_ctx pc1; int res = EXIT_FAILURE; int err; struct stat st; char *buf; unsigned total; FILE *outfile, *infile; progname = basename(argv[0]); while ( 1 ) { int c; c = getopt(argc, argv, "di:o:h"); if (c == -1) break; switch (c) { case 'd': decrypt = 1; break; case 'i': ifname = optarg; break; case 'o': ofname = optarg; break; case 'h': usage(EXIT_SUCCESS); break; default: usage(EXIT_FAILURE); break; } } if (ifname == NULL) { ERR("no input file specified"); goto err; } if (ofname == NULL) { ERR("no output file specified"); goto err; } err = stat(ifname, &st); if (err){ ERRS("stat failed on %s", ifname); goto err; } total = st.st_size; buf = malloc(BUFSIZE); if (!buf) { ERR("no memory for buffer\n"); goto err; } infile = fopen(ifname, "r"); if (infile == NULL) { ERRS("could not open \"%s\" for reading", ifname); goto err_free; } outfile = fopen(ofname, "w"); if (outfile == NULL) { ERRS("could not open \"%s\" for writing", ofname); goto err_close_in; } pc1_init(&pc1); while (total > 0) { unsigned datalen; if (total > BUFSIZE) datalen = BUFSIZE; else datalen = total; errno = 0; fread(buf, datalen, 1, infile); if (errno != 0) { ERRS("unable to read from file %s", ifname); goto err_close_out; } if (decrypt) pc1_decrypt_buf(&pc1, buf, datalen); else pc1_encrypt_buf(&pc1, buf, datalen); errno = 0; fwrite(buf, datalen, 1, outfile); if (errno) { ERRS("unable to write to file %s", ofname); goto err_close_out; } total -= datalen; } pc1_finish(&pc1); res = EXIT_SUCCESS; out_flush: fflush(outfile); err_close_out: fclose(outfile); if (res != EXIT_SUCCESS) { unlink(ofname); } err_close_in: fclose(infile); err_free: free(buf); err: return res; } ================================================ FILE: src/firmware-tools/ptgen.c ================================================ /* * ptgen - partition table generator * Copyright (C) 2006 by Felix Fietkau * * uses parts of afdisk * Copyright (C) 2002 by David Roetzel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #if __BYTE_ORDER == __BIG_ENDIAN #define cpu_to_le16(x) bswap_16(x) #elif __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le16(x) (x) #else #error unknown endianness! #endif /* Partition table entry */ struct pte { unsigned char active; unsigned char chs_start[3]; unsigned char type; unsigned char chs_end[3]; unsigned int start; unsigned int length; }; struct partinfo { unsigned long size; int type; }; int verbose = 0; int active = 1; int heads = -1; int sectors = -1; int kb_align = 0; struct partinfo parts[4]; char *filename = NULL; /* * parse the size argument, which is either * a simple number (K assumed) or * K, M or G * * returns the size in KByte */ static long to_kbytes(const char *string) { int exp = 0; long result; char *end; result = strtoul(string, &end, 0); switch (tolower(*end)) { case 'k' : case '\0' : exp = 0; break; case 'm' : exp = 1; break; case 'g' : exp = 2; break; default: return 0; } if (*end) end++; if (*end) { fprintf(stderr, "garbage after end of number\n"); return 0; } /* result: number + 1024^(exp) */ return result * ((2 << ((10 * exp) - 1)) ?: 1); } /* convert the sector number into a CHS value for the partition table */ static void to_chs(long sect, unsigned char chs[3]) { int c,h,s; s = (sect % sectors) + 1; sect = sect / sectors; h = sect % heads; sect = sect / heads; c = sect; chs[0] = h; chs[1] = s | ((c >> 2) & 0xC0); chs[2] = c & 0xFF; return; } /* round the sector number up to the next cylinder */ static inline unsigned long round_to_cyl(long sect) { int cyl_size = heads * sectors; return sect + cyl_size - (sect % cyl_size); } /* round the sector number up to the kb_align boundary */ static inline unsigned long round_to_kb(long sect) { return ((sect - 1) / kb_align + 1) * kb_align; } /* check the partition sizes and write the partition table */ static int gen_ptable(int nr) { struct pte pte[4]; unsigned long sect = 0; int i, fd, ret = -1, start, len; memset(pte, 0, sizeof(struct pte) * 4); for (i = 0; i < nr; i++) { if (!parts[i].size) { fprintf(stderr, "Invalid size in partition %d!\n", i); return -1; } pte[i].active = ((i + 1) == active) ? 0x80 : 0; pte[i].type = parts[i].type; start = sect + sectors; if (kb_align != 0) start = round_to_kb(start); pte[i].start = cpu_to_le16(start); sect = start + parts[i].size * 2; if (kb_align == 0) sect = round_to_cyl(sect); pte[i].length = cpu_to_le16(len = sect - start); to_chs(start, pte[i].chs_start); to_chs(start + len - 1, pte[i].chs_end); if (verbose) fprintf(stderr, "Partition %d: start=%ld, end=%ld, size=%ld\n", i, (long) start * 512, ((long) start + (long) len) * 512, (long) len * 512); printf("%ld\n", ((long) start * 512)); printf("%ld\n", ((long) len * 512)); } if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { fprintf(stderr, "Can't open output file '%s'\n",filename); return -1; } lseek(fd, 446, SEEK_SET); if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) { fprintf(stderr, "write failed.\n"); goto fail; } lseek(fd, 510, SEEK_SET); if (write(fd, "\x55\xaa", 2) != 2) { fprintf(stderr, "write failed.\n"); goto fail; } ret = 0; fail: close(fd); return ret; } static void usage(char *prog) { fprintf(stderr, "Usage: %s [-v] -h -s -o [-a 0..4] [-l ] [[-t ] -p ...] \n", prog); exit(1); } int main (int argc, char **argv) { char type = 0x83; int ch; int part = 0; while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vl:")) != -1) { switch (ch) { case 'o': filename = optarg; break; case 'v': verbose++; break; case 'h': heads = (int) strtoul(optarg, NULL, 0); break; case 's': sectors = (int) strtoul(optarg, NULL, 0); break; case 'p': if (part > 3) { fprintf(stderr, "Too many partitions\n"); exit(1); } parts[part].size = to_kbytes(optarg); parts[part++].type = type; break; case 't': type = (char) strtoul(optarg, NULL, 16); break; case 'a': active = (int) strtoul(optarg, NULL, 0); if ((active < 0) || (active > 4)) active = 0; break; case 'l': kb_align = (int) strtoul(optarg, NULL, 0) * 2; break; case '?': default: usage(argv[0]); } } argc -= optind; if (argc || (heads <= 0) || (sectors <= 0) || !filename) usage(argv[0]); return gen_ptable(part); } ================================================ FILE: src/firmware-tools/readme.txt ================================================ This is a collection of firmware packaging and obfuscation utilities. ================================================ FILE: src/firmware-tools/seama.c ================================================ /* vi: set sw=4 ts=4: */ /* * Copyright (C) 2008, Alpha Networks, Inc. * Created by David Hsieh * All right reserved. * * (SEA)ttle i(MA)ge is the image which used in project seattle. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include "md5.h" #include "seama.h" #define PROGNAME "seama" #define VERSION "0.20" #define MAX_SEAMA_META_SIZE 1024 #define MAX_META 128 #define MAX_IMAGE 128 extern int optind; extern char * optarg; static int o_verbose = 0; /* verbose mode. */ static char * o_dump = NULL; /* Seama file to dump. */ static char * o_seal = NULL; /* Seal the input images when file name exist. */ static char * o_extract = NULL; /* Extract the seama file. */ static char * o_images[MAX_IMAGE];/* The image files to pack or seal */ static int o_isize = 0; /* number of images */ static char * o_meta[MAX_META]; /* meta data array */ static int o_msize = 0; /* size of meta array */ static void verbose(const char * format, ...) { va_list marker; if (o_verbose) { va_start(marker, format); vfprintf(stdout, format, marker); va_end(marker); } } static void cleanup_exit(int exit_code) { verbose("%s: exit with code %d\n", PROGNAME, exit_code); exit(exit_code); } static void show_usage(int exit_code) { printf( PROGNAME " version " VERSION "\n" "usage: " PROGNAME " [OPTIONS]\n" " -h show this help message.\n" " -v verbose mode.\n" " -m {META data} META data.\n" " -d {file} dump the info of the seama file.\n" " -i {input file} image file name.\n" " -s {file} Seal the images to the seama file.\n" " -x {seama file} Extract the seama file.\n" "\n" " SEAMA can pack the input file (with -i) into a seama file.\n" " ex: seama -i target.file\n" " SEAMA can also seal multiple seama files into a single seama file.\n" " ex: seama -s final.file -i taget1.seama -i target2.seama\n" " To extract the raw image from SEAMA, you need to specify the meta.\n" " The first image match the specified meta will be extract to\n" " the output file which was specified with '-x'.\n" " ex: seama -x output -i seama.image -m file=sealpac\n" ); cleanup_exit(exit_code); } static int parse_args(int argc, char * argv[]) { int opt; while ((opt = getopt(argc, argv, "hvd:s:i:m:x:")) > 0) { switch (opt) { default: show_usage(-1); break; case 'h': show_usage(0); break; case 'v': o_verbose++; break; case 'd': o_dump = optarg; break; case 's': o_seal = optarg; break; case 'x': o_extract = optarg; break; case 'i': if (o_isize < MAX_IMAGE) o_images[o_isize++] = optarg; else printf("Exceed the maximum acceptable image files.!\n"); break; case 'm': if (o_msize < MAX_META) o_meta[o_msize++] = optarg; else printf("Exceed the maximum acceptable META data.!\n"); break; } } return 0; } /*******************************************************************/ static size_t calculate_digest(FILE * fh, size_t size, uint8_t * digest) { MD5_CTX ctx; size_t bytes_left, bytes_read, i; uint8_t buf[MAX_SEAMA_META_SIZE]; bytes_left = size ? size : sizeof(buf); bytes_read = 0; MD5_Init(&ctx); while (!feof(fh) && !ferror(fh) && bytes_left > 0) { i = bytes_left < sizeof(buf) ? bytes_left : sizeof(buf); i = fread(buf, sizeof(char), i, fh); if (i > 0) { MD5_Update(&ctx, buf, i); bytes_read += i; } if (size) bytes_left -= i; } MD5_Final(digest, &ctx); return bytes_read; } #define READ_BUFF_SIZE 8*1024 static size_t copy_file(FILE * to, FILE * from) { size_t i, fsize = 0; uint8_t buf[READ_BUFF_SIZE]; while (!feof(from) && !ferror(from)) { i = fread(buf, sizeof(uint8_t), READ_BUFF_SIZE, from); if (i > 0) { fsize += i; fwrite(buf, sizeof(uint8_t), i, to); } } return fsize; } static int verify_seama(const char * fname, int msg) { FILE * fh = NULL; struct stat st; seamahdr_t shdr; uint8_t checksum[16]; uint8_t digest[16]; uint8_t buf[MAX_SEAMA_META_SIZE]; size_t msize, isize, i; int ret = -1; #define ERRBREAK(fmt, args...) { if (msg) printf(fmt, ##args); break; } do { if (stat(fname, &st) < 0) ERRBREAK("Unable to get the info of '%s'\n",fname); if ((fh = fopen(fname, "r+"))==NULL) ERRBREAK("Unable to open '%s' for reading!\n",fname); /* Dump SEAMA header */ if (msg) printf("FILE - %s (%d bytes)\n", fname, (int)st.st_size); /* SEAMA */ while (!feof(fh) && !ferror(fh)) { /* read header */ if (fread(&shdr, sizeof(shdr), 1, fh) != 1) break; /* Check the magic number */ if (shdr.magic != htonl(SEAMA_MAGIC)) ERRBREAK("Invalid SEAMA magic. Probably no more SEAMA!\n"); /* Get the size */ isize = ntohl(shdr.size); msize = ntohs(shdr.metasize); /* The checksum exist only if size is greater than zero. */ if (isize > 0) { if (fread(checksum, sizeof(checksum), 1, fh) != 1) ERRBREAK("Error reading checksum !\n"); } /* Check the META size. */ if (msize > sizeof(buf)) ERRBREAK("META data in SEAMA header is too large!\n"); /* Read META data. */ if (fread(buf, sizeof(char), msize, fh) != msize) ERRBREAK("Unable to read SEAMA META data!\n"); /* dump header */ if (msg) { printf("SEAMA ==========================================\n"); printf(" magic : %08x\n", ntohl(shdr.magic)); printf(" meta size : %d bytes\n", msize); for (i=0; i 0) { if (msg) { printf(" checksum : "); for (i=0; i<16; i++) printf("%02X", checksum[i]); printf("\n"); } /* Calculate the checksum */ calculate_digest(fh, isize, digest); if (msg) { printf(" digest : "); for (i=0; i<16; i++) printf("%02X", digest[i]); printf("\n"); } if (memcmp(checksum, digest, 16)!=0) ERRBREAK("!!ERROR!! checksum error !!\n"); ret = 0; } } if (msg) printf("================================================\n"); } while (0); if (fh) fclose(fh); return ret; } static size_t write_seama_header(FILE * fh, char * meta[], size_t msize, size_t size) { seamahdr_t shdr; size_t i; uint16_t metasize = 0; /* Calculate the META size */ for (i=0; i 0) { m = fread(buf, sizeof(char), (msize < MAX_SEAMA_META_SIZE) ? msize : MAX_SEAMA_META_SIZE, ifh); if (m <= 0) break; msize -= m; } continue; } /* read checksum */ fread(buf, sizeof(char), 16, ifh); if (msize > 0) { /* read META */ fread(buf, sizeof(char), msize, ifh); if (match_meta((const char *)buf, msize)) { printf("SEAMA: found image @ '%s', image size: %d\n", o_images[i], isize); /* open output file */ ofh = fopen(output, "w"); if (!ofh) printf("SEAMA: unable to open '%s' for writting.\n",output); else { while (isize > 0) { m = fread(buf, sizeof(char), (isize < MAX_SEAMA_META_SIZE) ? isize : MAX_SEAMA_META_SIZE, ifh); if (m <= 0) break; fwrite(buf, sizeof(char), m, ofh); isize -= m; } fclose(ofh); } done++; break; } } while (isize > 0) { m = fread(buf, sizeof(char), (isize < MAX_SEAMA_META_SIZE) ? isize : MAX_SEAMA_META_SIZE, ifh); if (m <= 0) break; isize -= m; } } /* close the file. */ fclose(ifh); if (done) break; } return; } /*******************************************************************/ #ifdef RGBIN_BOX int seama_main(int argc, char * argv[], char * env[]) #else int main(int argc, char * argv[], char * env[]) #endif { verbose("SEAMA version " VERSION "\n"); /* parse the arguments */ if (parse_args(argc, argv) < 0) show_usage(9); /* Do the works */ if (o_dump) dump_seama(o_dump); else if (o_seal) seal_files(o_seal); else if (o_extract) extract_file(o_extract); else pack_files(); cleanup_exit(0); return 0; } ================================================ FILE: src/firmware-tools/seama.h ================================================ /* vi: set sw=4 ts=4: */ /* * (SEA)ttle i(MA)ge is the image which used in project seattle. * * Created by David Hsieh * Copyright (C) 2008-2009 Alpha Networks, Inc. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either' * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library is distributed in the hope that it will be useful,' * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. */ #ifndef __SEAMA_HEADER_FILE__ #define __SEAMA_HEADER_FILE__ #include #define SEAMA_MAGIC 0x5EA3A417 /* * SEAMA looks like the following map. * All the data of the header should be in network byte order. * * +-------------+-------------+------------ * | SEAMA magic | ^ * +-------------+-------------+ | * | reserved | meta size | | * +-------------+-------------+ header * | image size (0 bytes) | | * +-------------+-------------+ | * ~ Meta data ~ v * +-------------+-------------+------------ * | SEAMA magic | ^ ^ * +-------------+-------------+ | | * | reserved | meta size | | | * +-------------+-------------+ | | * | image size | | | * +-------------+-------------+ header | * | | | | * | 16 bytes of MD5 digest | | | * | | | | * | | | | * +-------------+-------------+ | | * ~ Meta data ~ v | * +-------------+-------------+------- | * | | | * | Image of the 1st entity | | * ~ ~ 1st entity * | | | * | | v * +-------------+-------------+------------- * | SEAMA magic | ^ ^ * +-------------+-------------+ | | * | reserved | meta size | | | * +-------------+-------------+ | | * | image size | | | * +-------------+-------------+ header | * | | | | * | 16 bytes of MD5 digest | | | * | | | | * | | | | * +-------------+-------------+ | | * ~ Meta data ~ v | * +-------------+-------------+------- | * | | | * | Image of the 2nd entity | | * ~ ~ 2nd entity * | | | * | | v * +-------------+-------------+------------- */ /* * SEAMA header * * |<-------- 32 bits -------->| * +-------------+-------------+ * | SEAMA magic | * +-------------+-------------+ * | reserved | meta size | * +-------------+-------------+ * | image size | * +-------------+-------------+ */ /* seama header */ typedef struct seama_hdr seamahdr_t; struct seama_hdr { uint32_t magic; /* should always be SEAMA_MAGIC. */ uint16_t reserved; /* reserved for */ uint16_t metasize; /* size of the META data */ uint32_t size; /* size of the image */ } __attribute__ ((packed)); #endif ================================================ FILE: src/firmware-tools/sha1.c ================================================ /* * FIPS-180-1 compliant SHA-1 implementation * * Copyright (C) 2003-2006 Christophe Devine * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License, version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ /* * The SHA-1 standard was published by NIST in 1993. * * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif #include #include #include "sha1.h" /* * 32-bit integer manipulation macros (big endian) */ #ifndef GET_UINT32_BE #define GET_UINT32_BE(n,b,i) \ { \ (n) = ( (ulong) (b)[(i) ] << 24 ) \ | ( (ulong) (b)[(i) + 1] << 16 ) \ | ( (ulong) (b)[(i) + 2] << 8 ) \ | ( (ulong) (b)[(i) + 3] ); \ } #endif #ifndef PUT_UINT32_BE #define PUT_UINT32_BE(n,b,i) \ { \ (b)[(i) ] = (uchar) ( (n) >> 24 ); \ (b)[(i) + 1] = (uchar) ( (n) >> 16 ); \ (b)[(i) + 2] = (uchar) ( (n) >> 8 ); \ (b)[(i) + 3] = (uchar) ( (n) ); \ } #endif /* * Core SHA-1 functions */ void sha1_starts( sha1_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; } void sha1_process( sha1_context *ctx, uchar data[64] ) { ulong temp, W[16], A, B, C, D, E; GET_UINT32_BE( W[0], data, 0 ); GET_UINT32_BE( W[1], data, 4 ); GET_UINT32_BE( W[2], data, 8 ); GET_UINT32_BE( W[3], data, 12 ); GET_UINT32_BE( W[4], data, 16 ); GET_UINT32_BE( W[5], data, 20 ); GET_UINT32_BE( W[6], data, 24 ); GET_UINT32_BE( W[7], data, 28 ); GET_UINT32_BE( W[8], data, 32 ); GET_UINT32_BE( W[9], data, 36 ); GET_UINT32_BE( W[10], data, 40 ); GET_UINT32_BE( W[11], data, 44 ); GET_UINT32_BE( W[12], data, 48 ); GET_UINT32_BE( W[13], data, 52 ); GET_UINT32_BE( W[14], data, 56 ); GET_UINT32_BE( W[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define R(t) \ ( \ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ ( W[t & 0x0F] = S(temp,1) ) \ ) #define P(a,b,c,d,e,x) \ { \ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; E = ctx->state[4]; #define F(x,y,z) (z ^ (x & (y ^ z))) #define K 0x5A827999 P( A, B, C, D, E, W[0] ); P( E, A, B, C, D, W[1] ); P( D, E, A, B, C, W[2] ); P( C, D, E, A, B, W[3] ); P( B, C, D, E, A, W[4] ); P( A, B, C, D, E, W[5] ); P( E, A, B, C, D, W[6] ); P( D, E, A, B, C, W[7] ); P( C, D, E, A, B, W[8] ); P( B, C, D, E, A, W[9] ); P( A, B, C, D, E, W[10] ); P( E, A, B, C, D, W[11] ); P( D, E, A, B, C, W[12] ); P( C, D, E, A, B, W[13] ); P( B, C, D, E, A, W[14] ); P( A, B, C, D, E, W[15] ); P( E, A, B, C, D, R(16) ); P( D, E, A, B, C, R(17) ); P( C, D, E, A, B, R(18) ); P( B, C, D, E, A, R(19) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0x6ED9EBA1 P( A, B, C, D, E, R(20) ); P( E, A, B, C, D, R(21) ); P( D, E, A, B, C, R(22) ); P( C, D, E, A, B, R(23) ); P( B, C, D, E, A, R(24) ); P( A, B, C, D, E, R(25) ); P( E, A, B, C, D, R(26) ); P( D, E, A, B, C, R(27) ); P( C, D, E, A, B, R(28) ); P( B, C, D, E, A, R(29) ); P( A, B, C, D, E, R(30) ); P( E, A, B, C, D, R(31) ); P( D, E, A, B, C, R(32) ); P( C, D, E, A, B, R(33) ); P( B, C, D, E, A, R(34) ); P( A, B, C, D, E, R(35) ); P( E, A, B, C, D, R(36) ); P( D, E, A, B, C, R(37) ); P( C, D, E, A, B, R(38) ); P( B, C, D, E, A, R(39) ); #undef K #undef F #define F(x,y,z) ((x & y) | (z & (x | y))) #define K 0x8F1BBCDC P( A, B, C, D, E, R(40) ); P( E, A, B, C, D, R(41) ); P( D, E, A, B, C, R(42) ); P( C, D, E, A, B, R(43) ); P( B, C, D, E, A, R(44) ); P( A, B, C, D, E, R(45) ); P( E, A, B, C, D, R(46) ); P( D, E, A, B, C, R(47) ); P( C, D, E, A, B, R(48) ); P( B, C, D, E, A, R(49) ); P( A, B, C, D, E, R(50) ); P( E, A, B, C, D, R(51) ); P( D, E, A, B, C, R(52) ); P( C, D, E, A, B, R(53) ); P( B, C, D, E, A, R(54) ); P( A, B, C, D, E, R(55) ); P( E, A, B, C, D, R(56) ); P( D, E, A, B, C, R(57) ); P( C, D, E, A, B, R(58) ); P( B, C, D, E, A, R(59) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0xCA62C1D6 P( A, B, C, D, E, R(60) ); P( E, A, B, C, D, R(61) ); P( D, E, A, B, C, R(62) ); P( C, D, E, A, B, R(63) ); P( B, C, D, E, A, R(64) ); P( A, B, C, D, E, R(65) ); P( E, A, B, C, D, R(66) ); P( D, E, A, B, C, R(67) ); P( C, D, E, A, B, R(68) ); P( B, C, D, E, A, R(69) ); P( A, B, C, D, E, R(70) ); P( E, A, B, C, D, R(71) ); P( D, E, A, B, C, R(72) ); P( C, D, E, A, B, R(73) ); P( B, C, D, E, A, R(74) ); P( A, B, C, D, E, R(75) ); P( E, A, B, C, D, R(76) ); P( D, E, A, B, C, R(77) ); P( C, D, E, A, B, R(78) ); P( B, C, D, E, A, R(79) ); #undef K #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; ctx->state[4] += E; } void sha1_update( sha1_context *ctx, uchar *input, uint length ) { ulong left, fill; if( ! length ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += length; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < length ) ctx->total[1]++; if( left && length >= fill ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); sha1_process( ctx, ctx->buffer ); length -= fill; input += fill; left = 0; } while( length >= 64 ) { sha1_process( ctx, input ); length -= 64; input += 64; } if( length ) { memcpy( (void *) (ctx->buffer + left), (void *) input, length ); } } static uchar sha1_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void sha1_finish( sha1_context *ctx, uchar digest[20] ) { ulong last, padn; ulong high, low; uchar msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_UINT32_BE( high, msglen, 0 ); PUT_UINT32_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); sha1_update( ctx, sha1_padding, padn ); sha1_update( ctx, msglen, 8 ); PUT_UINT32_BE( ctx->state[0], digest, 0 ); PUT_UINT32_BE( ctx->state[1], digest, 4 ); PUT_UINT32_BE( ctx->state[2], digest, 8 ); PUT_UINT32_BE( ctx->state[3], digest, 12 ); PUT_UINT32_BE( ctx->state[4], digest, 16 ); } /* * Output SHA-1(file contents), returns 0 if successful. */ int sha1_file( char *filename, uchar digest[20] ) { FILE *f; size_t n; sha1_context ctx; uchar buf[1024]; if( ( f = fopen( filename, "rb" ) ) == NULL ) return( 1 ); sha1_starts( &ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) sha1_update( &ctx, buf, (uint) n ); sha1_finish( &ctx, digest ); fclose( f ); return( 0 ); } /* * Output SHA-1(buf) */ void sha1_csum( uchar *buf, uint buflen, uchar digest[20] ) { sha1_context ctx; sha1_starts( &ctx ); sha1_update( &ctx, buf, buflen ); sha1_finish( &ctx, digest ); } /* * Output HMAC-SHA-1(key,buf) */ void sha1_hmac( uchar *key, uint keylen, uchar *buf, uint buflen, uchar digest[20] ) { uint i; sha1_context ctx; uchar k_ipad[64]; uchar k_opad[64]; uchar tmpbuf[20]; memset( k_ipad, 0x36, 64 ); memset( k_opad, 0x5C, 64 ); for( i = 0; i < keylen; i++ ) { if( i >= 64 ) break; k_ipad[i] ^= key[i]; k_opad[i] ^= key[i]; } sha1_starts( &ctx ); sha1_update( &ctx, k_ipad, 64 ); sha1_update( &ctx, buf, buflen ); sha1_finish( &ctx, tmpbuf ); sha1_starts( &ctx ); sha1_update( &ctx, k_opad, 64 ); sha1_update( &ctx, tmpbuf, 20 ); sha1_finish( &ctx, digest ); memset( k_ipad, 0, 64 ); memset( k_opad, 0, 64 ); memset( tmpbuf, 0, 20 ); memset( &ctx, 0, sizeof( sha1_context ) ); } #ifdef SELF_TEST /* * FIPS-180-1 test vectors */ static char *sha1_test_str[3] = { "abc", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL }; static uchar sha1_test_sum[3][20] = { { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } }; /* * Checkup routine */ int sha1_self_test( void ) { int i, j; uchar buf[1000]; uchar sha1sum[20]; sha1_context ctx; for( i = 0; i < 3; i++ ) { printf( " SHA-1 test #%d: ", i + 1 ); sha1_starts( &ctx ); if( i < 2 ) sha1_update( &ctx, (uchar *) sha1_test_str[i], strlen( sha1_test_str[i] ) ); else { memset( buf, 'a', 1000 ); for( j = 0; j < 1000; j++ ) sha1_update( &ctx, (uchar *) buf, 1000 ); } sha1_finish( &ctx, sha1sum ); if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) { printf( "failed\n" ); return( 1 ); } printf( "passed\n" ); } printf( "\n" ); return( 0 ); } #else int sha1_self_test( void ) { printf( "SHA-1 self-test not available\n\n" ); return( 1 ); } #endif ================================================ FILE: src/firmware-tools/sha1.h ================================================ #ifndef _SHA1_H #define _SHA1_H #ifdef __cplusplus extern "C" { #endif #ifndef _STD_TYPES #define _STD_TYPES #define uchar unsigned char #define uint unsigned int #define ulong unsigned long int #endif typedef struct { ulong total[2]; ulong state[5]; uchar buffer[64]; } sha1_context; /* * Core SHA-1 functions */ void sha1_starts( sha1_context *ctx ); void sha1_update( sha1_context *ctx, uchar *input, uint length ); void sha1_finish( sha1_context *ctx, uchar digest[20] ); /* * Output SHA-1(file contents), returns 0 if successful. */ int sha1_file( char *filename, uchar digest[20] ); /* * Output SHA-1(buf) */ void sha1_csum( uchar *buf, uint buflen, uchar digest[20] ); /* * Output HMAC-SHA-1(key,buf) */ void sha1_hmac( uchar *key, uint keylen, uchar *buf, uint buflen, uchar digest[20] ); /* * Checkup routine */ int sha1_self_test( void ); #ifdef __cplusplus } #endif #endif /* sha1.h */ ================================================ FILE: src/firmware-tools/spw303v.c ================================================ /* * spw303v.c - partially based on OpenWrt's imagetag.c and addpattern.c * * Copyright (C) 2011 Jonas Gorski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #define IMAGE_LEN 10 /* Length of Length Field */ #define ADDRESS_LEN 12 /* Length of Address field */ #define TAGID_LEN 6 /* Length of tag ID */ #define TAGINFO_LEN 20 /* Length of vendor information field in tag */ #define TAGVER_LEN 4 /* Length of Tag Version */ #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ struct spw303v_tag { unsigned char tagVersion[4]; // tag version. Will be 2 here. unsigned char signiture_1[20]; // text line for company info unsigned char signiture_2[14]; // additional info (can be version number) unsigned char chipId[6]; // chip id unsigned char boardId[16]; // board id unsigned char bigEndian[2]; // if = 1 - big, = 0 - little endia of the host unsigned char totalImageLen[IMAGE_LEN]; // the sum of all the following length unsigned char cfeAddress[ADDRESS_LEN]; // if non zero, cfe starting address unsigned char cfeLen[IMAGE_LEN]; // if non zero, cfe size in clear ASCII text. unsigned char rootfsAddress[ADDRESS_LEN]; // if non zero, filesystem starting address unsigned char rootfsLen[IMAGE_LEN]; // if non zero, filesystem size in clear ASCII text. unsigned char kernelAddress[ADDRESS_LEN]; // if non zero, kernel starting address unsigned char kernelLen[IMAGE_LEN]; // if non zero, kernel size in clear ASCII text. unsigned char certf1Address[ADDRESS_LEN]; unsigned char certf1Len[6]; unsigned char certf2Address[ADDRESS_LEN]; unsigned char certf2Len[6]; unsigned char certf3Address[ADDRESS_LEN]; unsigned char certf3Len[6]; unsigned char httpsFileSize[4]; unsigned char tr64FileSize[4]; unsigned char tr69FileSize[4]; unsigned char filesmap[4]; unsigned char imageSequence[4]; // incrments everytime an image is flashed unsigned char reserved[4]; // reserved for later use unsigned char imageCRC[4]; // 216-219: CRC32 of images unsigned char reserved2[16]; // 220-235: Unused at present unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion unsigned char reserved3[16]; // 240-255: Unused at present }; static uint32_t crc32tab[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; #define IMAGETAG_CRC_START 0xFFFFFFFF #define IMAGETAG_MAGIC1_TCOM "AAAAAAAA Corporatio" static char fake_data[] = { 0x18, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 ,0x18, 0x21, 0x24, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, }; uint32_t crc32(uint32_t crc, uint8_t *data, size_t len) { while (len--) crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF]; return crc; } void fix_header(void *buf) { struct spw303v_tag *tag = buf; uint32_t crc; /* Replace signature with custom t-com one */ memset(tag->signiture_1, 0, 20); memcpy(tag->signiture_1, IMAGETAG_MAGIC1_TCOM, strlen(IMAGETAG_MAGIC1_TCOM)); /* Clear cert fields to remove information_* data */ memset(tag->certf1Address, 0, 74); /* replace image crc with modified one */ crc = ntohl(*((uint32_t *)&tag->imageCRC)); crc = htonl(crc32(crc, fake_data, 64)); memcpy(tag->imageCRC, &crc, 4); /* Update tag crc */ crc = htonl(crc32(IMAGETAG_CRC_START, buf, 236)); memcpy(tag->headerCRC, &crc, 4); } void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Usage: spw303v [-i ] [-o ]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { char buf[1024]; /* keep this at 1k or adjust garbage calc below */ FILE *in = stdin; FILE *out = stdout; char *ifn = NULL; char *ofn = NULL; int c; int v0, v1, v2; size_t n; int first_block = 1; uint32_t image_crc = IMAGETAG_CRC_START; while ((c = getopt(argc, argv, "i:o:h")) != -1) { switch (c) { case 'i': ifn = optarg; break; case 'o': ofn = optarg; break; case 'h': default: usage(); } } if (optind != argc || optind == 1) { fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); usage(); } if (ifn && !(in = fopen(ifn, "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", ifn); usage(); } if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } while ((n = fread(buf, 1, sizeof(buf), in)) > 0) { if (n < sizeof(buf)) { if (ferror(in)) { FREAD_ERROR: fprintf(stderr, "fread error\n"); return EXIT_FAILURE; } } if (first_block && n >= 256) { fix_header(buf); first_block = 0; } image_crc = crc32(image_crc, buf, n); if (!fwrite(buf, n, 1, out)) { FWRITE_ERROR: fprintf(stderr, "fwrite error\n"); return EXIT_FAILURE; } } if (ferror(in)) { goto FREAD_ERROR; } if (fflush(out)) { goto FWRITE_ERROR; } fclose(in); fclose(out); return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/srec2bin.c ================================================ #include #include #include //Rev 0.1 Original // 8 Jan 2001 MJH Added code to write data to Binary file // note: outputfile is name.bin, where name is first part // of input file. ie tmp.rec -> tmp.bin // // srec2bin // // TAG // bit32u TAG_BIG = 0xDEADBE42; // bit32u TAG_LITTLE = 0xFEEDFA42; // // File Structure // // TAG : 32 Bits // [DATA RECORDS] // // Data Records Structure // // LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM // ADDRESS : 32 Bits // DATA : 8 Bits * LENGTH // CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data) // // Note : If Length == 0, Address will be Program Start // // // // // #define MajRevNum 0 #define MinRevNum 2 #define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) ) typedef unsigned char bit8u; typedef unsigned int bit32u; typedef int bit32; #define FALSE 0 #define TRUE (!FALSE) bit32u CheckSum; int RecStart; int debug; int verbose; FILE *OpenOutputFile( char *Name ); FILE *fOut; bit32u RecLength=0; bit32u AddressCurrent; bit32u gh(char *cp,int nibs); int BigEndian; int inputline; // char buf[16*1024]; char buffer[2048]; char *cur_ptr; int cur_line=0; int cur_len=0; int s1s2s3_total=0; bit32u PBVal; int PBValid; bit32u PBAdr; void dumpfTell(char *s, bit32u Value) { int Length; Length = (int) RecLength; if (debug) printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n", s, ftell(fOut), Length, Length, Value); } void DispHex(bit32u Hex) { // printf("%X", Hex); } void WaitDisplay(void) { static int Count=0; static int Index=0; char iline[]={"-\\|/"}; Count++; if ((Count % 32)==0) { if (verbose) printf("%c%c",iline[Index++],8); Index &= 3; } } void binOut32 ( bit32u Data ) { // On UNIX machine all 32bit writes need ENDIAN switched // Data = EndianSwitch(Data); // fwrite( &Data, sizeof(bit32u), 1, fOut); char sdat[4]; int i; for(i=0;i<4;i++) sdat[i]=(char)(Data>>(i*8)); fwrite( sdat, 1, 4, fOut); dumpfTell("Out32" , Data); } // Only update RecLength on Byte Writes // All 32 bit writes will be for Length etc void binOut8 ( bit8u Data ) { int n; dumpfTell("B4Data" , (bit32u) (Data & 0xFF) ); n = fwrite( &Data, sizeof(bit8u), 1, fOut); if (n != 1) printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent); RecLength += 1; } // Currently ONLY used for outputting Program Start void binRecStart(bit32u Address) { RecLength = 0; CheckSum = Address; RecStart = TRUE; if (debug) printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n", CheckSum, RecLength, Address); dumpfTell("RecLength", RecLength); binOut32( RecLength ); dumpfTell("Address", Address); binOut32( Address ); } void binRecEnd(void) { long RecEnd; if (!RecStart) // if no record started, do not end it { return; } RecStart = FALSE; RecEnd = ftell(fOut); // Save Current position if (debug) printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n", CheckSum, RecLength, RecLength, RecEnd); fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data dumpfTell("Data ", -1); fseek( fOut, -4, SEEK_CUR); // move back Start Of Address dumpfTell("Address ", -1); fseek( fOut, -4, SEEK_CUR); // move back Start Of Length dumpfTell("Length ", -1); binOut32( RecLength ); fseek( fOut, RecEnd, SEEK_SET); // move to end of Record CheckSum += RecLength; CheckSum = ~CheckSum + 1; // Two's complement binOut32( CheckSum ); if (verbose) printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum); } void binRecOutProgramStart(bit32u Address) { if (Address != (AddressCurrent+1)) { binRecEnd(); binRecStart(Address); } AddressCurrent = Address; } void binRecOutByte(bit32u Address, bit8u Data) { // If Address is one after Current Address, output Byte // If not, close out last record, update Length, write checksum // Then Start New Record, updating Current Address if (Address != (AddressCurrent+1)) { binRecEnd(); binRecStart(Address); } AddressCurrent = Address; CheckSum += Data; binOut8( Data ); } //============================================================================= // SUPPORT FUNCTIONS //============================================================================= int readline(FILE *fil,char *buf,int len) { int rlen; rlen=0; if (len==0) return(0); while(1) { if (cur_len==0) { cur_len=fread(buffer, 1, sizeof(buffer), fil); if (cur_len==0) { if (rlen) { *buf=0; return(rlen); } return(-1); } cur_ptr=buffer; } if (cur_len) { if (*cur_ptr=='\n') { *buf=0; cur_ptr++; cur_len--; return(rlen); } else { if ((len>1)&&(*cur_ptr!='\r')) { *buf++=*cur_ptr++; len--; } else cur_ptr++; rlen++; cur_len--; } } else { *buf=0; cur_ptr++; cur_len--; return(rlen); } } } int SRLerrorout(char *c1,char *c2) { printf("\nERROR: %s - '%s'.",c1,c2); return(FALSE); } int checksum(char *cp,int count) { char *scp; int cksum; int dum; scp=cp; while(*scp) { if (!isxdigit(*scp++)) return(SRLerrorout("Invalid hex digits",cp)); } scp=cp; cksum=count; while(count) { cksum += gh(scp,2); if (count == 2) dum = ~cksum; scp += 2; count--; } cksum&=0x0ff; // printf("\nCk:%02x",cksum); return(cksum==0x0ff); } bit32u gh(char *cp,int nibs) { int i; bit32u j; j=0; for(i=0;i='a')&&(*cp<='z')) *cp &= 0x5f; if ((*cp>='0')&&(*cp<='9')) j += (*cp-0x30); else if ((*cp>='A')&&(*cp<='F')) j += (*cp-0x37); else SRLerrorout("Bad Hex char", cp); cp++; } return(j); } //============================================================================= // PROCESS SREC LINE //============================================================================= int srecLine(char *pSrecLine) { char *scp,ch; int itmp,count,dat; bit32u adr; static bit32u RecordCounter=0; cur_line++; scp=pSrecLine; if (*pSrecLine!='S') return(SRLerrorout("Not an Srecord file",scp)); pSrecLine++; if (strlen(pSrecLine)<4) return(SRLerrorout("Srecord too short",scp)); ch=*pSrecLine++; count=gh(pSrecLine,2); pSrecLine += 2; // if(debug) // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine); RecordCounter++; DispHex(RecordCounter); if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp)); if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp)); switch(ch) { case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2; if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp)); break; case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); return(SRLerrorout("Srecord Not valid for MIPS",scp)); break; case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp)); return(SRLerrorout("Srecord Not valid for MIPS",scp)); break; case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp)); adr=gh(pSrecLine,8); pSrecLine+=8; count-=4; count--; while(count) { dat=gh(pSrecLine,2); pSrecLine+=2; count--; binRecOutByte(adr, (char) (dat & 0xFF)); adr++; } s1s2s3_total++; break; case '4': return(SRLerrorout("Invalid Srecord type",scp)); break; case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2; if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp)); break; case '6': return(SRLerrorout("Invalid Srecord type",scp)); break; case '7': // PROGRAM START if (count<5) return(SRLerrorout("Invalid Srecord count field",scp)); adr=gh(pSrecLine,8); pSrecLine+=8; count-=4; if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp)); binRecOutProgramStart(adr); break; case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp)); return(SRLerrorout("Srecord Not valid for MIPS",scp)); break; case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); return(SRLerrorout("Srecord Not valid for MIPS",scp)); break; default: break; } return(TRUE); } //============================================================================= // MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY //============================================================================= int srec2bin(int argc,char *argv[],int verbose) { int i,rlen,sts; FILE *fp; char ac; char buff[256]; bit32u TAG_BIG = 0xDEADBE42; bit32u TAG_LITTLE = 0xFEEDFA42; bit32u Tag; if(argc < 3) { printf("\nError: \n\n"); return(0); } if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE; if (BigEndian) Tag = TAG_BIG; else Tag = TAG_LITTLE; if (verbose) printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag); fp = fopen(argv[1],"rt"); if (fp==NULL) { printf("\nError: Opening input file, %s.", argv[1]); return(0); } fOut = fopen( argv[2], "wb"); if (fOut==NULL) { printf("\nError: Opening Output file, %s.", argv[2]); if(fp) fclose(fp); return(0); } RecStart = FALSE; AddressCurrent = 0xFFFFFFFFL; // Setup Tag dumpfTell("Tag", Tag); binOut32(Tag); inputline=0; sts=TRUE; rlen = readline(fp,buff,sizeof buff); while( (sts) && (rlen != -1)) { if (strlen(buff)) { sts &= srecLine(buff); WaitDisplay(); } rlen = readline(fp,buff,sizeof buff); } // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE); binRecEnd(); if(fp) fclose(fp); if(fOut) fclose(fOut); return(1); } main(int argc, char *argv[]) { debug = TRUE; debug = FALSE; verbose = FALSE; srec2bin(argc,argv,verbose); return 0; } ================================================ FILE: src/firmware-tools/trx.c ================================================ /* * Copyright (C) 2004 Manuel Novoa III * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* July 29, 2004 * * This is a hacked replacement for the 'trx' utility used to create * wrt54g .trx firmware files. It isn't pretty, but it does the job * for me. * * As an extension, you can specify a larger maximum length for the * .trx file using '-m'. It will be rounded up to be a multiple of 4K. * NOTE: This space will be malloc()'d. * * August 16, 2004 * * Sigh... Make it endian-neutral. * * TODO: Support '-b' option to specify offsets for each file. * * February 19, 2005 - mbm * * Add -a (align offset) and -b (absolute offset) * * March 24, 2010 - markus * * extend trx header struct for new version * assume v1 for as default * Add option -2 to allow v2 header */ #include #include #include #include #include #include #include #if __BYTE_ORDER == __BIG_ENDIAN #define STORE32_LE(X) bswap_32(X) #define LOAD32_LE(X) bswap_32(X) #elif __BYTE_ORDER == __LITTLE_ENDIAN #define STORE32_LE(X) (X) #define LOAD32_LE(X) (X) #else #error unkown endianness! #endif uint32_t crc32buf(char *buf, size_t len); /**********************************************************************/ /* from trxhdr.h */ #define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_MAX_LEN 0x720000 #define TRX_NO_HEADER 1 /* Do not write TRX header */ struct trx_header { uint32_t magic; /* "HDR0" */ uint32_t len; /* Length of file including header */ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[4]; /* Offsets of partitions from start of header */ }; /**********************************************************************/ void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " trx [-2] [-o outfile] [-m maxlen] [-a align] [-b absolute offset] [-x relative offset]\n"); fprintf(stderr, " [-f file] [-f file [-f file [-f file (v2 only)]]]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { FILE *out = stdout; FILE *in; char *ofn = NULL; char *buf; char *e; int c, i, append = 0; size_t n; ssize_t n2; uint32_t cur_len, fsmark=0; unsigned long maxlen = TRX_MAX_LEN; struct trx_header *p; char trx_version = 1; unsigned char binheader[32]; fprintf(stderr, "mjn3's trx replacement - v0.81.1\n"); if (!(buf = malloc(maxlen))) { fprintf(stderr, "malloc failed\n"); return EXIT_FAILURE; } p = (struct trx_header *) buf; p->magic = STORE32_LE(TRX_MAGIC); cur_len = sizeof(struct trx_header) - 4; /* assume v1 header */ in = NULL; i = 0; while ((c = getopt(argc, argv, "-:2o:m:a:x:b:f:A:F:")) != -1) { switch (c) { case '2': /* take care that nothing was written to buf so far */ if (cur_len != sizeof(struct trx_header) - 4) { fprintf(stderr, "-2 has to be used before any other argument!\n"); } else { trx_version = 2; cur_len += 4; } break; case 'F': fsmark = cur_len; case 'A': append = 1; /* fall through */ case 'f': case 1: if (!append) p->offsets[i++] = STORE32_LE(cur_len); if (!(in = fopen(optarg, "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", optarg); usage(); } n = fread(buf + cur_len, 1, maxlen - cur_len, in); if (!feof(in)) { fprintf(stderr, "fread failure or file \"%s\" too large\n",optarg); fclose(in); return EXIT_FAILURE; } fclose(in); #undef ROUND #define ROUND 4 if (n & (ROUND-1)) { memset(buf + cur_len + n, 0, ROUND - (n & (ROUND-1))); n += ROUND - (n & (ROUND-1)); } cur_len += n; append = 0; break; case 'o': ofn = optarg; if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } break; case 'm': errno = 0; maxlen = strtoul(optarg, &e, 0); if (errno || (e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } #undef ROUND #define ROUND 0x1000 if (maxlen & (ROUND-1)) { maxlen += (ROUND - (maxlen & (ROUND-1))); } if (maxlen < ROUND) { fprintf(stderr, "maxlen too small (or wrapped)\n"); usage(); } if (maxlen > TRX_MAX_LEN) { fprintf(stderr, "WARNING: maxlen exceeds default maximum! Beware of overwriting nvram!\n"); } if (!(buf = realloc(buf,maxlen))) { fprintf(stderr, "realloc failed"); return EXIT_FAILURE; } p = (struct trx_header *) buf; break; case 'a': errno = 0; n = strtoul(optarg, &e, 0); if (errno || (e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } if (cur_len & (n-1)) { n = n - (cur_len & (n-1)); memset(buf + cur_len, 0, n); cur_len += n; } break; case 'b': errno = 0; n = strtoul(optarg, &e, 0); if (errno || (e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } if (n < cur_len) { fprintf(stderr, "WARNING: current length exceeds -b %d offset\n",(int) n); } else { memset(buf + cur_len, 0, n - cur_len); cur_len = n; } break; case 'x': errno = 0; n2 = strtol(optarg, &e, 0); if (errno || (e == optarg) || *e) { fprintf(stderr, "illegal numeric string\n"); usage(); } if (n2 < 0) { if (-n2 > cur_len) { fprintf(stderr, "WARNING: current length smaller then -x %d offset\n",(int) n2); cur_len = 0; } else cur_len += n2; } else { memset(buf + cur_len, 0, n2); cur_len += n2; } break; default: usage(); } } p->flag_version = STORE32_LE((trx_version << 16)); if (!in) { fprintf(stderr, "we require atleast one filename\n"); usage(); } #undef ROUND #define ROUND 0x1000 n = cur_len & (ROUND-1); if (n) { memset(buf + cur_len, 0, ROUND - n); cur_len += ROUND - n; } /* for TRXv2 set bin-header Flags to 0xFF for CRC calculation like CFE does */ if (trx_version == 2) { if(cur_len - LOAD32_LE(p->offsets[3]) < sizeof(binheader)) { fprintf(stderr, "TRXv2 binheader too small!\n"); return EXIT_FAILURE; } memcpy(binheader, buf + LOAD32_LE(p->offsets[3]), sizeof(binheader)); /* save header */ memset(buf + LOAD32_LE(p->offsets[3]) + 22, 0xFF, 8); /* set stable and try1-3 to 0xFF */ } p->crc32 = crc32buf((char *) &p->flag_version, (fsmark)?fsmark:cur_len - offsetof(struct trx_header, flag_version)); p->crc32 = STORE32_LE(p->crc32); p->len = STORE32_LE((fsmark) ? fsmark : cur_len); p->len = STORE32_LE(p->len); /* restore TRXv2 bin-header */ if (trx_version == 2) { memcpy(buf + LOAD32_LE(p->offsets[3]), binheader, sizeof(binheader)); } if (!fwrite(buf, cur_len, 1, out) || fflush(out)) { fprintf(stderr, "fwrite failed\n"); return EXIT_FAILURE; } fclose(out); return EXIT_SUCCESS; } /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32buf(char *buf, size_t len) { uint32_t crc; crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc; } ================================================ FILE: src/firmware-tools/trx2edips.c ================================================ #include #include #include #include #include #include #include #if __BYTE_ORDER == __BIG_ENDIAN #define STORE32_LE(X) bswap_32(X) #define LOAD32_LE(X) bswap_32(X) #elif __BYTE_ORDER == __LITTLE_ENDIAN #define STORE32_LE(X) (X) #define LOAD32_LE(X) (X) #else #error unkown endianness! #endif /**********************************************************************/ /* from trxhdr.h */ #define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_VERSION 1 #define TRX_MAX_LEN 0x5A0000 #define TRX_NO_HEADER 1 /* Do not write TRX header */ struct trx_header { uint32_t magic; /* "HDR0" */ uint32_t len; /* Length of file including header */ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ uint32_t flag_version; /* 0:15 flags, 16:31 version */ uint32_t offsets[3]; /* Offsets of partitions from start of header */ }; struct edimax_header { uint32_t sign; /* signature for header */ uint32_t length; /* start address but doesn't seems to be used... */ uint32_t start_addr; /* length of data, not used too ...*/ }; #define EDIMAX_PS16 0x36315350 /* "PS16" */ #define EDIMAX_HDR_LEN 0xc /**********************************************************************/ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32buf(char *buf, size_t len) { uint32_t crc; crc = 0xFFFFFFFF; for (; len; --len, ++buf) crc = UPDC32(*buf, crc); return crc; } int main(int argc, char *argv[]) { FILE *fpIn = NULL; FILE *fpOut = NULL; struct edimax_header eh; size_t res; int length; char *buf; struct trx_header *p; if (argc != 3) { printf("Usage: %s \n", argv[0]); return -1; } fpIn = fopen(argv[1], "rb"); if (fpIn == NULL) { fprintf(stderr, "Unable to open %s\n", argv[1]); return EXIT_FAILURE; } /* compute the length of the file */ fseek(fpIn, 0, SEEK_END); length = ftell(fpIn); /* alloc enough memory to store the file */ buf = (char *)malloc(length); if (!buf) { fprintf(stderr, "malloc of buffers failed\n"); return EXIT_FAILURE; } rewind(fpIn); /* read the whole file*/ res = fread(buf, 1, length, fpIn); p = (struct trx_header *)buf; if (LOAD32_LE(p->magic) != TRX_MAGIC) { fprintf(stderr, "Not a trx file...%x\n", LOAD32_LE(p->magic)); return EXIT_FAILURE; } fclose(fpIn); fpOut = fopen(argv[2], "wb+"); if (fpOut == NULL) { fprintf(stderr, "Unable to open %s\n", argv[2]); return EXIT_FAILURE; } /* make the 3 partition beeing 12 bytes closer from the header */ memcpy(buf + LOAD32_LE(p->offsets[2]) - EDIMAX_HDR_LEN, buf + LOAD32_LE(p->offsets[2]), length - LOAD32_LE(p->offsets[2])); /* recompute the crc32 check */ p->crc32 = STORE32_LE(crc32buf((char *) &p->flag_version, length - offsetof(struct trx_header, flag_version))); eh.sign = STORE32_LE(EDIMAX_PS16); eh.length = STORE32_LE(length); eh.start_addr = STORE32_LE(0x80500000); /* write the modified file */ fwrite(&eh, sizeof(struct edimax_header), 1, fpOut); fwrite(buf, sizeof(char), length, fpOut); fclose(fpOut); } ================================================ FILE: src/firmware-tools/trx2usr.c ================================================ /* * trx2usr - Convert a TRX firmware image to a U.S. Robotics firmware * image by prepending a 28-byte header. * * This program was modeled after the usr-hdr.c program from the GPL'ed * firmware for the U.S. Robotics Wireless MAXg Router (USR5461). The * output file of this program can be uploaded via the web interface * of the original U.S. Robotics firmware. Note that this program only * works on a little-endian host platform. * * Copyright (C) 2006 Dick Streefland * * This is free software, licensed under the terms of the GNU General * Public License as published by the Free Software Foundation. */ #include #include #include #include #include #define TRX_MAGIC "HDR0" #define USR_MAGIC 0x30525355 // "USR0" #define EPI_VERSION 0x06235d03 #define COMPAT_ID 1 // USR5461 #define HARDWARE_REV 1 #define CRC32_INIT 0xffffffff #define CHUNK (64*1024) typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; struct usr_header { uint32 magic; // "USR0" uint32 len; // file length without this header uint32 crc32; // CRC32 of the file without header uint32 version; // EPI_VERSION uint16 compatibility_id; // COMPAT_ID uint16 hardware_revision; // HARDWARE_REV uint32 reserved[2]; }; static const uint32 crc_32_tab [] = // CRC polynomial 0xedb88320 { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; static char buf[CHUNK]; static uint32 crc32(uint32 crc, uint8* p, size_t n) { while (n--) { crc = crc_32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8); } return crc; } static int trx2usr(FILE* trx, FILE* usr) { struct usr_header hdr; size_t n; hdr.magic = USR_MAGIC; hdr.len = 0; hdr.crc32 = CRC32_INIT; hdr.version = EPI_VERSION; hdr.compatibility_id = COMPAT_ID; hdr.hardware_revision = HARDWARE_REV; hdr.reserved[0] = 0; hdr.reserved[1] = 0; fwrite(& hdr, sizeof(hdr), 1, usr); while ((n = fread(buf, 1, CHUNK, trx))) { if (hdr.len == 0 && strncmp(buf, TRX_MAGIC, strlen(TRX_MAGIC)) != 0) { break; } fwrite(& buf, 1, n, usr); hdr.len += n; hdr.crc32 = crc32( hdr.crc32, (uint8 *) & buf, n); } fseek(usr, 0L, SEEK_SET); fwrite(& hdr, sizeof(hdr), 1, usr); if (n != 0) { fprintf(stderr, "Input is not a TRX file\n"); return 1; } if (hdr.len == 0) { fprintf(stderr, "Empty input\n"); return 1; } if (ferror(trx)) { fprintf(stderr, "Read error\n"); return 1; } if (ferror(usr)) { fprintf(stderr, "Write error\n"); return 1; } return 0; } extern int main(int argc, char *argv[]) { FILE* in; FILE* out; int ret; if (argc != 3) { fprintf(stderr, "Usage: trx2usr \n"); exit(2); } in = fopen(argv[1], "rb"); if (!in) { fprintf(stderr, "Cannot open \"%s\": %s\n", argv[1], strerror(errno)); exit(1); } out = fopen(argv[2], "wb"); if (!out) { fprintf(stderr, "Cannot create \"%s\": %s\n", argv[2], strerror(errno)); exit(1); } ret = trx2usr(in, out); fclose(in); fclose(out); if (ret) { unlink(argv[2]); } return ret; } ================================================ FILE: src/firmware-tools/wndr3700.c ================================================ /* * wndr3700.c - partially based on OpenWrt's add_header.c * * Copyright (C) 2009 Anael Orlinski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * The add_header utility used by various vendors preprends the buf * image with a header containing a CRC32 value which is generated for the * model id + reserved space for CRC32 + buf, then replaces the reserved * area with the actual CRC32. This replacement tool mimics this behavior. */ #include #include #include #include #include #include #include #include #include #include #define BPB 8 /* bits/byte */ #define WNDR3700_MAGIC_LEN 4 static uint32_t crc32[1<> 1)) : (crc >> 1); crc32[n] = crc; } } static uint32_t crc32buf(unsigned char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for (; len; len--, buf++) crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB); return ~crc; } struct header { unsigned char magic[WNDR3700_MAGIC_LEN]; uint32_t crc; unsigned char stuff[56]; }; static void usage(const char *) __attribute__ (( __noreturn__ )); static void usage(const char *mess) { fprintf(stderr, "Error: %s\n", mess); fprintf(stderr, "Usage: wndr3700 input_file output_file [magic]\n"); fprintf(stderr, "\n"); exit(1); } int main(int argc, char **argv) { off_t len; // of original buf off_t buflen; // of the output file int fd; void *input_file; // pointer to the input file (mmmapped) struct header header; unsigned char *buf; // pointer to prefix + copy of original buf // verify parameters if (argc < 3) usage("wrong number of arguments"); if (argc > 3) magic = argv[3]; if (strlen(magic) != WNDR3700_MAGIC_LEN) { fprintf(stderr, "Invalid magic: '%s'\n", magic); exit(1); } // mmap input_file if ((fd = open(argv[1], O_RDONLY)) < 0 || (len = lseek(fd, 0, SEEK_END)) < 0 || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) || close(fd) < 0) { fprintf(stderr, "Error loading file %s: %s\n", argv[1], strerror(errno)); exit(1); } buflen = len; init_crc32(); // preload header memcpy(&header, input_file, sizeof(header)); memcpy(header.magic, magic, WNDR3700_MAGIC_LEN); header.crc = 0; // create a firmware image in memory and copy the input_file to it buf = malloc(buflen); memcpy(buf, input_file, len); // CRC of temporary header header.crc = htonl(crc32buf((unsigned char*)&header, sizeof(header))); memcpy(buf, &header, sizeof(header)); // write the buf if ((fd = open(argv[2], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0 || write(fd, buf, buflen) != buflen || close(fd) < 0) { fprintf(stderr, "Error storing file %s: %s\n", argv[2], strerror(errno)); exit(2); } free(buf); munmap(input_file,len); return 0; } ================================================ FILE: src/firmware-tools/wrt400n.c ================================================ /* * WRT400n - Firmware Generation Creator * * Creates a firmware image for the Linksys WRT400n router, * that can be uploaded via the firmware upload page, * from a kernel image file and root fs file * * Author: Sandeep Mistry */ #include #include #include #include #include #include #include "cyg_crc.h" // https://dev.openwrt.org/browser/trunk/target/linux/rdc-2.6/files/drivers/mtd/maps/rdc3210.c static uint32_t crctab[257] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 0 }; static uint32_t crc32(uint8_t* buf, uint32_t len) { register int i; uint32_t sum; register uint32_t s0; s0 = ~0; for (i = 0; i < len; i++) { s0 = (s0 >> 8) ^ crctab[(uint8_t) (s0 & 0xFF) ^ buf[i]]; } sum = ~s0; return sum; } #define HEADERSIZE 60 #define MAGIC "GMTKRT400N" // global variables uint8_t kernelbuf[0x100000]; // kernel - lzma - uImage uint8_t rootfsbuf[0x2FFFC4]; // root - squashfs uint8_t buf[0x400000]; // buffer for image // Header format: // // GPL Tarball: http://downloads.linksysbycisco.com/downloads/WRT400N_1.0.01.19_US.tar,0.gz // File: WRT400N_1.0.01.19_US/FW_WRT400N_1.0.01.19_US_20081229/GTK/user/include/fw_upgrade.h // // // Struct: // typedef struct // { // UINT32 checksum; /* CRC32 */ // UINT8 magic[11]; /* The value of GTIMG_MAGIC */ // UINT32 kernel_length; /* The length of the kernel image */ // //UINT32 kernel_entry_point; /* Kernel's entry point for RedBoot's information */ // UINT32 kernel_upgrade_flag; /* Set to 1 if we need to upgrade the kernel parition of the Flash */ // UINT32 rootfs_length; /* The length of the rootfs image */ // //UINT32 rootfs_entry_point; /* Not in use */ // UINT32 rootfs_upgrade_flag; /* Set to 1 if we need to upgrade the rootfs parition of the Flash */ // // // Add 3 items by Vic Yu, 2006-05/10 // UINT32 kernel_checksum; // UINT32 rootfs_checksum; // UINT32 fw_totalsize; // UINT32 reserved[4]; // }imghdr_t , *pLinuxFWHeader_T; // // // Description // - checksum: CRC32 of kernel and root fs, back to back // - magic: GMTKRT400N // - kernel_length: kernel length in bytes // - kernel_upgrade_flag: should we upgrade the kernel - set to 1 // - rootfs_length: root fs length in byte // - rootfs_upgrade_flag: should we upgrade the root fs - set to 1 // - kernel_checksum: Gary S. Brown's 32 bit CRC algorithm for kernel, with remaining bits // set to 0xFF upto 0x100000 bytes (total length) // - rootfs_checksum: Gary S. Brown's 32 bit CRC algorithm for root fs, with remaining bits // set to 0xFF upto 0x2FFFC4 bytes (total length) // - fw_totalsize: total firmware image file length (header length + kernel length + root fs length) // - reserved[4]: reserved ??? - set to all 0xFF int main(int argc, char *argv[]) { // file descriptors ... int kernelfd = -1; int rootfsfd = -1; int outfd = -1; char* kernelfilename = NULL; char* rootfsfilename = NULL; char* outputfilename = NULL; // file sizes uint32_t kernelsize = 0; uint32_t rootfssize = 0; uint32_t totalsize = 0; // header flags uint32_t kernelflag = 0; uint32_t rootfsflag = 0; // checksums uint32_t kernelchecksum = 0; uint32_t rootfschecksum = 0; uint32_t crc = 0; if(argc != 4) { printf("Usage:\n\t%s \n", argv[0]); return 1; } kernelfilename = argv[1]; rootfsfilename = argv[2]; outputfilename = argv[3]; // Fill the kernel, rootfs, main buffer memset(kernelbuf, 0xFF, sizeof(kernelbuf)); memset(rootfsbuf, 0xFF, sizeof(rootfsbuf)); memset(buf, 0xFF, sizeof(buf)); // open the kernel .. kernelfd = open(kernelfilename, O_RDONLY); if(kernelfd == -1) { printf("Error: opening '%s'\n", kernelfilename); goto done; } // read in the kernel ... kernelsize = read(kernelfd, kernelbuf, sizeof(kernelbuf)); if(kernelsize == -1) { printf("Error: reading '%s'\n", kernelfilename); goto done; } // calculate the kernel checksum ... kernelchecksum = cyg_crc32_accumulate(0, kernelbuf, sizeof(kernelbuf)); // print out stats printf("%s: size %d (0x%x), crc32 = 0x%x\n", kernelfilename, kernelsize, kernelsize, kernelchecksum); // open the root fs .. rootfsfd = open(rootfsfilename, O_RDONLY); if(rootfsfd == -1) { printf("Error: opening '%s'\n", rootfsfilename); goto done; } // read in the root fs .. rootfssize = read(rootfsfd, rootfsbuf, sizeof(rootfsbuf)); if(rootfssize == -1) { printf("Error: reading '%s'\n", rootfsfilename); goto done; } // calculate the root fs checksum ... rootfschecksum = cyg_crc32_accumulate(0, rootfsbuf, sizeof(rootfsbuf)); // print out stats printf("%s: size %d (0x%x), crc32 = 0x%x\n", rootfsfilename, rootfssize, rootfssize, rootfschecksum); // now for the header ... totalsize = HEADERSIZE; // copy over kernel memcpy(buf + totalsize, kernelbuf, kernelsize); totalsize += kernelsize; // copy over root fs memcpy(buf + totalsize, rootfsbuf, rootfssize); totalsize += rootfssize; // calculate crc crc = crc32(buf + HEADERSIZE, totalsize - HEADERSIZE); // print some stats out printf("crc = 0x%x, total size = %d (0x%x)\n", crc, totalsize, totalsize); // copy crc into header crc = htonl(crc); memcpy(buf, &crc, sizeof(crc)); // copy over magic strcpy((char *)buf + 4, MAGIC); // copy over kernel size kernelsize = htonl(kernelsize); memcpy(buf + 16, &kernelsize, sizeof(kernelsize)); // copy over kernal flag kernelflag = htonl(0x1); memcpy(buf + 20, &kernelflag, sizeof(kernelflag)); // copy over root fs size rootfssize = htonl(rootfssize); memcpy(buf + 24, &rootfssize, sizeof(rootfssize)); // copy over root fs flag rootfsflag = htonl(0x1); memcpy(buf + 28, &rootfsflag, sizeof(rootfsflag)); // copy over kernel check sum kernelchecksum = htonl(kernelchecksum); memcpy(buf + 32, &kernelchecksum, sizeof(kernelchecksum)); // copy over root fs checksum rootfschecksum = htonl(rootfschecksum); memcpy(buf + 36, &rootfschecksum, sizeof(rootfschecksum)); // copy over total size totalsize = htonl(totalsize); memcpy(buf + 40, &totalsize, sizeof(totalsize)); // undo the htonl (for write) totalsize = htonl(totalsize); // write out the file from the buffer outfd = open(outputfilename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(outfd == -1) { printf("ERROR: opening '%s' for write\n", outputfilename); } write(outfd, buf, totalsize); done: // close open fd's if(kernelfd != -1) { close(kernelfd); kernelfd = -1; } if(rootfsfd != -1) { close(rootfsfd); rootfsfd = -1; } if(outfd != -1) { close(outfd); outfd = -1; } return 0; } ================================================ FILE: src/firmware-tools/xorimage.c ================================================ /* * xorimage.c - partially based on OpenWrt's addpattern.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include static char default_pattern[] = "12345678"; int xor_data(uint8_t *data, size_t len, const uint8_t *pattern, int p_len, int p_off) { int offset = p_off; while (len--) { *data ^= pattern[offset]; data++; offset = (offset + 1) % p_len; } return offset; } void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { fprintf(stderr, "Usage: xorimage [-i infile] [-o outfile] [-p ]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { char buf[1024]; /* keep this at 1k or adjust garbage calc below */ FILE *in = stdin; FILE *out = stdout; char *ifn = NULL; char *ofn = NULL; const char *pattern = default_pattern; int c; int v0, v1, v2; size_t n; int p_len, p_off = 0; while ((c = getopt(argc, argv, "i:o:p:h")) != -1) { switch (c) { case 'i': ifn = optarg; break; case 'o': ofn = optarg; break; case 'p': pattern = optarg; break; case 'h': default: usage(); } } if (optind != argc || optind == 1) { fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); usage(); } if (ifn && !(in = fopen(ifn, "r"))) { fprintf(stderr, "can not open \"%s\" for reading\n", ifn); usage(); } if (ofn && !(out = fopen(ofn, "w"))) { fprintf(stderr, "can not open \"%s\" for writing\n", ofn); usage(); } p_len = strlen(pattern); if (p_len == 0) { fprintf(stderr, "pattern cannot be empty\n"); usage(); } while ((n = fread(buf, 1, sizeof(buf), in)) > 0) { if (n < sizeof(buf)) { if (ferror(in)) { FREAD_ERROR: fprintf(stderr, "fread error\n"); return EXIT_FAILURE; } } p_off = xor_data(buf, n, pattern, p_len, p_off); if (!fwrite(buf, n, 1, out)) { FWRITE_ERROR: fprintf(stderr, "fwrite error\n"); return EXIT_FAILURE; } } if (ferror(in)) { goto FREAD_ERROR; } if (fflush(out)) { goto FWRITE_ERROR; } fclose(in); fclose(out); return EXIT_SUCCESS; } ================================================ FILE: src/firmware-tools/zynos.h ================================================ /* * * Copyright (C) 2007-2008 OpenWrt.org * Copyright (C) 2007-2008 Gabor Juhos * * This code was based on the information of the ZyXEL's firmware * image format written by Kolja Waschk, can be found at: * http://www.ixo.de/info/zyxel_uclinux * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * */ #ifndef _ZYNOS_H #define _ZYNOS_H #define BOOTBASE_NAME_LEN 32 #define BOOTBASE_MAC_LEN 6 #define BOOTBASE_FEAT_LEN 22 #define BOOTEXT_DEF_SIZE 0x18000 struct zyn_bootbase_info { char vendor[BOOTBASE_NAME_LEN]; /* Vendor name */ char model[BOOTBASE_NAME_LEN]; /* Model name */ uint32_t bootext_addr; /* absolute address of the Boot Extension */ uint16_t res0; /* reserved/unknown */ uint8_t sys_type; /* system type */ uint8_t res1; /* reserved/unknown */ uint16_t model_id; /* model id */ uint8_t feat_other[BOOTBASE_FEAT_LEN]; /* other feature bits */ uint8_t feat_main; /* main feature bits */ uint8_t res2; /* reserved/unknown */ uint8_t mac[BOOTBASE_MAC_LEN]; /* mac address */ uint8_t country; /* default country code */ uint8_t dbgflag; /* debug flag */ } __attribute__((packed)); #define ROMBIN_SIG_LEN 3 #define ROMBIN_VER_LEN 15 struct zyn_rombin_hdr { uint32_t addr; /* load address of the object */ uint16_t res0; /* unknown/unused */ char sig[ROMBIN_SIG_LEN]; /* magic, must be "SIG" */ uint8_t type; /* type of the object */ uint32_t osize; /* size of the uncompressed data */ uint32_t csize; /* size of the compressed data */ uint8_t flags; /* various flags */ uint8_t res1; /* unknown/unused */ uint16_t ocsum; /* csum of the uncompressed data */ uint16_t ccsum; /* csum of the compressed data */ char ver[ROMBIN_VER_LEN]; uint32_t mmap_addr; /* address of the Memory Map Table*/ uint32_t res2; /* unknown/unused*/ uint8_t res3; /* unknown/unused*/ } __attribute__((packed)); #define ROMBIN_SIGNATURE "SIG" /* Rombin flag bits */ #define ROMBIN_FLAG_01 0x01 #define ROMBIN_FLAG_02 0x02 #define ROMBIN_FLAG_04 0x04 #define ROMBIN_FLAG_08 0x08 #define ROMBIN_FLAG_10 0x10 #define ROMBIN_FLAG_CCSUM 0x20 /* compressed checksum is valid */ #define ROMBIN_FLAG_OCSUM 0x40 /* original checksum is valid */ #define ROMBIN_FLAG_COMPRESSED 0x80 /* the binary is compressed */ /* Object types */ #define OBJECT_TYPE_ROMIMG 0x01 #define OBJECT_TYPE_ROMBOOT 0x02 #define OBJECT_TYPE_BOOTEXT 0x03 #define OBJECT_TYPE_ROMBIN 0x04 #define OBJECT_TYPE_ROMDIR 0x05 #define OBJECT_TYPE_6 0x06 #define OBJECT_TYPE_ROMMAP 0x07 #define OBJECT_TYPE_RAM 0x80 #define OBJECT_TYPE_RAMCODE 0x81 #define OBJECT_TYPE_RAMBOOT 0x82 /* * Memory Map Table header */ struct zyn_mmt_hdr { uint16_t count; uint32_t user_start; uint32_t user_end; uint16_t csum; uint8_t res[12]; } __attribute__((packed)); #define OBJECT_NAME_LEN 8 struct zyn_mmt_item { uint8_t type; /* type of the object */ uint8_t name[OBJECT_NAME_LEN]; /* name of the object */ uint8_t res0; /* unused/unknown */ uint32_t addr; uint32_t size; /* size of the object */ uint8_t res1[3]; /* unused/unknown */ uint8_t type2; } __attribute__((packed)); /* * Vendor IDs */ #define ZYNOS_VENDOR_ID_ZYXEL 0 #define ZYNOS_VENDOR_ID_NETGEAR 1 #define ZYNOS_VENDOR_ID_DLINK 2 #define ZYNOS_VENDOR_ID_03 3 #define ZYNOS_VENDOR_ID_LUCENT 4 #define ZYNOS_VENDOR_ID_O2 10 /* * Model IDs (in big-endian format) */ #define MID(x) (((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8) /* * Infineon/ADMtek ADM5120 based models */ #define ZYNOS_MODEL_ES_2024A MID( 221) #define ZYNOS_MODEL_ES_2024PWR MID( 4097) #define ZYNOS_MODEL_ES_2108 MID(61952) #define ZYNOS_MODEL_ES_2108_F MID(44801) #define ZYNOS_MODEL_ES_2108_G MID(62208) #define ZYNOS_MODEL_ES_2108_LC MID(64512) #define ZYNOS_MODEL_ES_2108PWR MID(62464) #define ZYNOS_MODEL_HS_100 MID(61855) #define ZYNOS_MODEL_HS_100W ZYNOS_MODEL_HS_100 #define ZYNOS_MODEL_P_334 MID(62879) #define ZYNOS_MODEL_P_334U MID(56735) #define ZYNOS_MODEL_P_334W MID(62367) #define ZYNOS_MODEL_P_334WH MID(57344) #define ZYNOS_MODEL_P_334WHD MID(57600) #define ZYNOS_MODEL_P_334WT MID(61343) #define ZYNOS_MODEL_P_335 MID(60831) #define ZYNOS_MODEL_P_335PLUS MID( 9472) #define ZYNOS_MODEL_P_335U MID(56479) #define ZYNOS_MODEL_P_335WT ZYNOS_MODEL_P_335 /* * Texas Instruments AR7 based models */ #define ZYNOS_MODEL_P_2602H_61C MID( 3229) #define ZYNOS_MODEL_P_2602H_63C MID( 3485) #define ZYNOS_MODEL_P_2602H_D1A /* n.a. */ #define ZYNOS_MODEL_P_2602H_D3A /* n.a. */ #define ZYNOS_MODEL_P_2602HW_61C /* n.a. */ #define ZYNOS_MODEL_P_2602HW_63 /* n.a. */ #define ZYNOS_MODEL_P_2602HW_63C ZYNOS_MODEL_P_2602H_63C #define ZYNOS_MODEL_P_2602HW_D1A MID( 6301) #define ZYNOS_MODEL_P_2602HW_D3A /* n.a. */ #define ZYNOS_MODEL_P_2602HWL_61 MID( 1181) #define ZYNOS_MODEL_P_2602HWL_61C ZYNOS_MODEL_P_2602H_61C #define ZYNOS_MODEL_P_2602HWL_63C ZYNOS_MODEL_P_2602H_63C #define ZYNOS_MODEL_P_2602HWL_D1A ZYNOS_MODEL_P_2602HW_D1A #define ZYNOS_MODEL_P_2602HWL_D3A MID( 7581) #define ZYNOS_MODEL_P_2602HWN_D7A MID(30464) #define ZYNOS_MODEL_P_2602HWNLI_D7A MID( 6813) #define ZYNOS_MODEL_P_2602R_61 MID( 2205) #define ZYNOS_MODEL_P_2602R_63 MID( 3997) #define ZYNOS_MODEL_P_2602R_D1A /* n.a. */ #define ZYNOS_MODEL_P_2602R_D3A /* n.a. */ #define ZYNOS_MODEL_P_2602RL_D1A MID( 6045) #define ZYNOS_MODEL_P_2602RL_D3A MID( 7069) #define ZYNOS_MODEL_P_660H_61 MID(19346) #define ZYNOS_MODEL_P_660H_63 MID(22162) #define ZYNOS_MODEL_P_660H_67 /* n.a. */ #define ZYNOS_MODEL_P_660H_D1 MID( 7066) #define ZYNOS_MODEL_P_660H_D3 MID(13210) #define ZYNOS_MODEL_P_660HW_61 ZYNOS_MODEL_P_660H_61 #define ZYNOS_MODEL_P_660HW_63 ZYNOS_MODEL_P_660H_63 #define ZYNOS_MODEL_P_660HW_67 ZYNOS_MODEL_P_660HW_63 #define ZYNOS_MODEL_P_660HW_D1 MID( 9114) #define ZYNOS_MODEL_P_660HW_D3 MID(12698) #define ZYNOS_MODEL_P_660R_61 MID(20882) #define ZYNOS_MODEL_P_660R_61C MID( 1178) #define ZYNOS_MODEL_P_660R_63 MID(21138) #define ZYNOS_MODEL_P_660R_63C MID( 922) #define ZYNOS_MODEL_P_660R_67 ZYNOS_MODEL_P_660R_63 #define ZYNOS_MODEL_P_660R_67C /* n.a. */ #define ZYNOS_MODEL_P_660R_D1 MID( 7322) #define ZYNOS_MODEL_P_660R_D3 MID(10138) #define ZYNOS_MODEL_P_661H_61 MID(19346) #define ZYNOS_MODEL_P_661H_63 MID( 1946) #define ZYNOS_MODEL_P_661H_D1 MID(10650) #define ZYNOS_MODEL_P_661H_D3 MID(12442) #define ZYNOS_MODEL_P_661HW_61 ZYNOS_MODEL_P_661H_61 #define ZYNOS_MODEL_P_661HW_63 ZYNOS_MODEL_P_661H_63 #define ZYNOS_MODEL_P_661HW_D1 MID(10906) #define ZYNOS_MODEL_P_661HW_D3 MID(14746) #define ZYNOS_MODEL_P_662H_61 MID(22418) #define ZYNOS_MODEL_P_662H_63 /* n.a. */ #define ZYNOS_MODEL_P_662H_67 /* n.a. */ #define ZYNOS_MODEL_P_662H_D1 /* n.a. */ #define ZYNOS_MODEL_P_662H_D3 /* n.a. */ #define ZYNOS_MODEL_P_662HW_61 /* n.a. */ #define ZYNOS_MODEL_P_662HW_63 MID(22674) #define ZYNOS_MODEL_P_662HW_67 /* n.a. */ #define ZYNOS_MODEL_P_662HW_D1 MID(10394) #define ZYNOS_MODEL_P_662HW_D3 MID(12954) /* OEM boards */ #define ZYNOS_MODEL_O2SURF ZYNOS_MODEL_P_2602HWN_D7A /* Atheros AR2318 based boards */ #define ZYNOS_MODEL_NBG_318S MID(59392) /* Atheros AR71xx based boards */ #define ZYNOS_MODEL_NBG_460N MID(61441) #endif /* _ZYNOS_H */ ================================================ FILE: src/jffs2/unjffs2 ================================================ #!/bin/bash # Script to mount a JFFS2 image and copy the file system's files to a destination directory. # # Craig Heffner # 27 August 2011 IMG="$1" DST="$2" BLOCK="/dev/mtdblock1" if [ "$IMG" == "" ] || [ "$IMG" == "-h" ] then echo "Usage: $0 [mount directory]" exit 1 fi # Need to extract file systems as ROOT #if [ "$UID" != "0" ] #then # SUDO="sudo" #else # SUDO="" #fi if [ "$DST" == "" ] then DST="jffs2-root" fi if [ -e "$DST" ] then echo "ERROR: $DST already exists! Quitting..." exit 1 fi if [ "$(file $IMG | grep little)" == "" ] then echo "Converting image to little endian..." jffs2dump -b -e $IMG.le $IMG IMG=$IMG.le fi #Make sure required modules are loaded $SUDO modprobe mtdblock $SUDO modprobe mtdchar $SUDO modprobe mtd $SUDO rmmod mtdram $SUDO modprobe mtdram total_size=$((64*1024)) #Create destination and temporary mount directories $SUDO mkdir -p $DST && $SUDO mkdir -p $DST if [ $? == 0 ] then if [ ! -e $BLOCK ] then $SUDO mknod $BLOCK b 31 0 fi #Copy JFSS2 image to MTD block $SUDO dd if="$IMG" of=$BLOCK && $SUDO mount -t jffs2 $BLOCK $DST if [ $? == 0 ] then echo "JFFS2 image mounted to $DST" exit 0 else echo "ERROR: Failed to mount $IMG to $BLOCK" $SUDO rm -rf "$DST" fi else echo "ERROR: Directory creation failed" $SUDO rm -rf "$DST" fi exit 1 ================================================ FILE: src/lzma/.built ================================================ ================================================ FILE: src/lzma/.unpacked ================================================ ================================================ FILE: src/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.23 ---------------------- 7z ANSI-C Decoder 4.23 Copyright (C) 1999-2005 Igor Pavlov 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- Read lzma.txt for information about license. Files --------------------- 7zAlloc.* - Allocate and Free 7zBuffer.* - Buffer structure 7zCrc.* - CRC32 code 7zDecode.* - Low level memory->memory decoding 7zExtract.* - High level stream->memory decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application 7zMethodID.* - MethodID structure 7zTypes.h - Base types and constants How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec : e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- .7z Decoder can be compiled in one of two modes: 1) Default mode. In that mode 7z Decoder will read full compressed block to RAM before decompressing. 2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read compressed block by parts. And you can specify desired buffer size. So memory requirements can be reduced. But decompressing speed will be 5-10% lower and code size is slightly larger. Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ISzInStream interface */ CArchiveDatabaseEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call InitCrcTable(); function to initialize CRC structures. 3) call SzArDbExInit(&db); function to initialize db structures. 4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined) - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for compressed solid block (if _LZMA_IN_CB is not defined) - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. EXIT codes ----------- 7z Decoder functions can return one of the following codes: #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) LZMA Defines ------------ _LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements _SZ_FILE_SIZE_64 - define it if you need support for files larger than 4 GB _SZ_NO_INT_64 - define it if your compiler doesn't support long long int _LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs. _SZ_ONE_DIRECTORY - define it if you want to locate all source files to one directory _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zAlloc.c ================================================ /* 7zAlloc.c */ #include #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include #endif #include int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include #include "7zTypes.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void InitCrcTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCrcPoly; else r >>= 1; g_CrcTable[i] = r; } } void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } void CrcUpdateByte(UInt32 *crc, Byte b) { *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); } void CrcUpdateUInt16(UInt32 *crc, UInt16 v) { CrcUpdateByte(crc, (Byte)v); CrcUpdateByte(crc, (Byte)(v >> 8)); } void CrcUpdateUInt32(UInt32 *crc, UInt32 v) { int i; for (i = 0; i < 4; i++) CrcUpdateByte(crc, (Byte)(v >> (8 * i))); } void CrcUpdateUInt64(UInt32 *crc, UInt64 v) { int i; for (i = 0; i < 8; i++) { CrcUpdateByte(crc, (Byte)(v)); v >>= 8; } } void CrcUpdate(UInt32 *crc, const void *data, size_t size) { UInt32 v = *crc; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); *crc = v; } UInt32 CrcCalculateDigest(const void *data, size_t size) { UInt32 crc; CrcInit(&crc); CrcUpdate(&crc, data, size); return CrcGetDigest(&crc); } int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) { return (CrcCalculateDigest(data, size) == digest); } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include #include "7zTypes.h" extern UInt32 g_CrcTable[256]; void InitCrcTable(); void CrcInit(UInt32 *crc); UInt32 CrcGetDigest(UInt32 *crc); void CrcUpdateByte(UInt32 *crc, Byte v); void CrcUpdateUInt16(UInt32 *crc, UInt16 v); void CrcUpdateUInt32(UInt32 *crc, UInt32 v); void CrcUpdateUInt64(UInt32 *crc, UInt64 v); void CrcUpdate(UInt32 *crc, const void *data, size_t size); UInt32 CrcCalculateDigest(const void *data, size_t size); int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zDecode.c ================================================ /* 7zDecode.c */ #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/LZMA_C/LzmaDecode.h" #endif CMethodID k_Copy = { { 0x0 }, 1 }; CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; size_t Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); *size = (SizeT)processedSize; if (processedSize > cb->Size) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; size_t inSize = 0; CCoderInfo *coder; if (folder->NumPackStreams != 1) return SZE_NOTIMPL; if (folder->NumCoders != 1) return SZE_NOTIMPL; coder = folder->Coders; *outSizeProcessed = 0; for (si = 0; si < folder->NumPackStreams; si++) inSize += (size_t)packSizes[si]; if (AreMethodsEqual(&coder->MethodID, &k_Copy)) { size_t i; if (inSize != outSize) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB for (i = 0; i < inSize;) { size_t j; Byte *inBuffer; size_t bufferSize; RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); if (bufferSize == 0) return SZE_DATA_ERROR; if (bufferSize > inSize - i) return SZE_FAIL; *outSizeProcessed += bufferSize; for (j = 0; j < bufferSize && i < inSize; j++, i++) outBuffer[i] = inBuffer[j]; } #else for (i = 0; i < inSize; i++) outBuffer[i] = inBuffer[i]; *outSizeProcessed = inSize; #endif return SZ_OK; } if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); *outSizeProcessed = (size_t)outSizeProcessedLoc; allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return SZ_OK; } return SZE_NOTIMPL; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSize = SzFolderGetUnPackSize(folder); #ifndef _LZMA_IN_CB CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); Byte *inBuffer = 0; size_t processedSize; #endif *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); if (res == SZ_OK && processedSize != (size_t)packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = (size_t)unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { size_t outRealSize; res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) { if (outRealSize == (size_t)unPackSize) { if (folder->UnPackCRCDefined) { if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) res = SZE_FAIL; } } else res = SZE_FAIL; } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) res = SZE_FAIL; } } } return res; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "7zTypes.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zCrc.h" #include "7zDecode.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size)) { if (size == 0) *p = 0; else { *p = allocFunc(size); RINOM(*p); } return SZ_OK; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc)); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ while(1) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) size += db->Database.PackSizes[packStreamIndex + i]; return size; } /* SZ_RESULT SzReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { Byte *inBuffer; size_t processedSize; RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc)); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc)); RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc)); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc)); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { RINOK(SzReadByte(sd, &mainByte)); coder->MethodID.IDSize = (Byte)(mainByte & 0xF); RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc)); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc)); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc)); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc)); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; while(1) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; while(1) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc)); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc)); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); while(1) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; size_t outRealSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc)); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, &outRealSize, allocTemp); RINOK(res) if (outRealSize != (UInt32)unPackSize) return SZE_FAIL; if (folder->UnPackCRCDefined) if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); CrcInit(&crc); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); CrcUpdateUInt64(&crc, nextHeaderOffset); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); CrcUpdateUInt64(&crc, nextHeaderSize); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); CrcUpdateUInt32(&crc, nextHeaderCRC); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CrcGetDigest(&crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) { while (1) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); /* #define CArchiveFileTime UInt64 */ typedef struct _CFileItem { /* CArchiveFileTime LastWriteTime; CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.26 Copyright (c) 1999-2005 Igor Pavlov (2005-08-02) */ #include #include #include #include "7zCrc.h" #include "7zIn.h" #include "7zExtract.h" typedef struct _CFileInStream { ISzInStream InStream; FILE *File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = fread(buffer, 1, size, s->File); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.30 Copyright (c) 1999-2005 Igor Pavlov 2005-11-20\n"); if (numargs == 1) { printf( "\nUsage: 7zDec \n\n" "\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; InitCrcTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; // if you need cache, use these 3 variables. // if you use external function, you can make these variable as static. UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0) Byte *outBuffer = 0; // it must be 0 before first call for each new archive. size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0) printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { FILE *outputHandle; UInt32 processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = fopen(fileName, "wb+"); if (outputHandle == 0) { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (fclose(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); fclose(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { int i; if (a1->IDSize != a2->IDSize) return 0; for (i = 0; i < a1->IDSize; i++) if (a1->ID[i] != a2->ID[i]) return 0; return 1; } ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "7zTypes.h" #define kMethodIDSize 15 typedef struct _CMethodID { Byte ID[kMethodIDSize]; Byte IDSize; } CMethodID; int AreMethodsEqual(CMethodID *a1, CMethodID *a2); #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7zTypes.h ================================================ /* 7zTypes.h */ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef UInt32 #ifdef _LZMA_UINT32_IS_ULONG #define UInt32 unsigned long #else #define UInt32 unsigned int #endif #endif #ifndef Byte #define Byte unsigned char #endif #ifndef UInt16 #define UInt16 unsigned short #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifdef _SZ_NO_INT_64 #define UInt64 unsigned long #else #ifdef _MSC_VER #define UInt64 unsigned __int64 #else #define UInt64 unsigned long long int #endif #endif /* #define _SZ_FILE_SIZE_64 */ /* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_64 #define CFileSize UInt64 #else #define CFileSize UInt32 #endif #endif #define SZ_RESULT int #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zCrc.c # End Source File # Begin Source File SOURCE=.\7zCrc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # Begin Source File SOURCE=.\7zTypes.h # End Source File # End Target # End Project ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/makefile ================================================ PROG = 7zDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zCrc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/lzma/C/7zip/Archive/7z_C/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: 7zCrc.c $(CXX) $(CFLAGS) 7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/lzma/C/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { // return result ? S_OK: E_FAIL; #ifdef _WIN32 return result ? S_OK: (::GetLastError()); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef _WIN32 #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream bool COutFileStream::Create(LPCTSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #ifdef _WIN32 #ifndef _UNICODE bool COutFileStream::Create(LPCWSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #endif #endif STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef _WIN32 UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/lzma/C/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef _WIN32 #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways); #ifdef _WIN32 #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways); #endif #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/lzma/C/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" #include "../../Common/Alloc.h" CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/lzma/C/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS class CInBufferException { public: HRESULT ErrorCode; CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/lzma/C/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" #include "../../Common/Alloc.h" bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode != S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = FlushPart(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/lzma/C/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS struct COutBufferException { HRESULT ErrorCode; COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/lzma/C/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/lzma/C/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) break; } return S_OK; } ================================================ FILE: src/lzma/C/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" #include "BranchARM.c" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" #include "BranchARMThumb.c" UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchARM.c ================================================ // BranchARM.c #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (dest >> 16); data[i + 1] = (dest >> 8); data[i + 0] = dest; } } return i; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchARM.h ================================================ // BranchARM.h #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "Common/Types.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchARMThumb.c ================================================ // BranchARMThumb.c #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; UInt32 dest; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = 0xF0 | ((dest >> 19) & 0x7); data[i + 0] = (dest >> 11); data[i + 3] = 0xF8 | ((dest >> 8) & 0x7); data[i + 2] = (dest); i += 2; } } return i; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchARMThumb.h ================================================ // BranchARMThumb.h #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "Common/Types.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "Common/Alloc.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClass2b(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClassA(Name, id, subId) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderA(Name ## _Encoder) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchIA64.c ================================================ // BranchIA64.c #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; for (int slot = 0; slot < 3; slot++, bitPos += 41) { if (((mask >> slot) & 1) == 0) continue; UInt32 bytePos = (bitPos >> 3); UInt32 bitRes = bitPos & 0x7; // UInt64 instruction = *(UInt64 *)(data + i + bytePos); UInt64 instruction = 0; int j; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); UInt64 instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 // && (instNorm & 0x3F)== 0 ) { UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF); src |= ((instNorm >> 36) & 1) << 20; src <<= 4; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~(UInt64(0x8FFFFF) << 13); instNorm |= (UInt64(dest & 0xFFFFF) << 13); instNorm |= (UInt64(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); // *(UInt64 *)(data + i + bytePos) = instruction; for (j = 0; j < 6; j++) data[i + j + bytePos] = Byte(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchIA64.h ================================================ // BranchIA64.h #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "Common/Types.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchPPC.c ================================================ // BranchPPC.c #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { // PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 // || (data[i+3] & 3) == 3 ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = 0x48 | ((dest >> 24) & 0x3); data[i + 1] = (dest >> 16); data[i + 2] = (dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchPPC.h ================================================ // BranchPPC.h #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "Common/Types.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchSPARC.c ================================================ // BranchSPARC.c #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchSPARC.h ================================================ // BranchSPARC.h #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "Common/Types.h" UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" /* static int inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } */ #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; /* void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos) { *prevMask = 0; *prevPos = (UInt32)(-5); } */ UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding) { UInt32 bufferPos = 0; UInt32 limit; if (endPos < 5) return 0; if (nowPos - *prevPos > 5) *prevPos = nowPos - 5; limit = endPos - 5; while(bufferPos <= limit) { Byte b = buffer[bufferPos]; UInt32 offset; if (b != 0xE8 && b != 0xE9) { bufferPos++; continue; } offset = (nowPos + bufferPos - *prevPos); *prevPos = (nowPos + bufferPos); if (offset > 5) *prevMask = 0; else { UInt32 i; for (i = 0; i < offset; i++) { *prevMask &= 0x77; *prevMask <<= 1; } } b = buffer[bufferPos + 4]; if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] && (*prevMask >> 1) < 0x10) { UInt32 src = ((UInt32)(b) << 24) | ((UInt32)(buffer[bufferPos + 3]) << 16) | ((UInt32)(buffer[bufferPos + 2]) << 8) | (buffer[bufferPos + 1]); UInt32 dest; while(1) { UInt32 index; if (encoding) dest = (nowPos + bufferPos + 5) + src; else dest = src - (nowPos + bufferPos + 5); if (*prevMask == 0) break; index = kMaskToBitNumber[*prevMask >> 1]; b = (Byte)(dest >> (24 - index * 8)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index * 8)) - 1); } buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1)); buffer[bufferPos + 3] = (Byte)(dest >> 16); buffer[bufferPos + 2] = (Byte)(dest >> 8); buffer[bufferPos + 1] = (Byte)dest; bufferPos += 5; *prevMask = 0; } else { bufferPos++; *prevMask |= 1; if (Test86MSByte(b)) *prevMask |= 0x10; } } return bufferPos; } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #ifndef UInt32 #define UInt32 unsigned int #endif #ifndef Byte #define Byte unsigned char #endif #define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); } UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" #include "BranchIA64.c" UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" #include "Windows/Defs.h" #include "BranchPPC.c" UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" #include "Windows/Defs.h" #include "BranchSPARC.c" UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" #include "Windows/Defs.h" #include "BranchX86.c" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0); } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" #include "BranchX86.h" struct CBranch86 { UInt32 _prevMask; UInt32 _prevPos; void x86Init() { x86_Convert_Init(_prevMask, _prevPos); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/lzma/C/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" #include "../../../Common/Alloc.h" static const int kBufferSize = 1 << 17; inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } #ifndef EXTRACT_ONLY static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CBCJ2_x86_Encoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder() { ::MidFree(_buffer); } HRESULT CBCJ2_x86_Encoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256; i++) _statusE8Encoder[i].Init(); _statusE9Encoder.Init(); _statusJccEncoder.Init(); CCoderReleaser releaser(this); CMyComPtr getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; while(true) { UInt32 processedSize = 0; while(true) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else if (IsJcc(prevByte, b)) _statusJccEncoder.Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); if (convert) { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 1); else _statusJccEncoder.Encode(&_rangeEncoder, 1); bufferPos += 5; if (b == 0xE8) { _callStream.WriteByte((Byte)(dest >> 24)); _callStream.WriteByte((Byte)(dest >> 16)); _callStream.WriteByte((Byte)(dest >> 8)); _callStream.WriteByte((Byte)(dest)); } else { _jumpStream.WriteByte((Byte)(dest >> 24)); _jumpStream.WriteByte((Byte)(dest >> 16)); _jumpStream.WriteByte((Byte)(dest >> 8)); _jumpStream.WriteByte((Byte)(dest)); } prevByte = nextByte; } else { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else _statusJccEncoder.Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256; i++) _statusE8Decoder[i].Init(); _statusE9Decoder.Init(); _statusJccDecoder.Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; while(true) { if (processedBytes > (1 << 20) && progress != NULL) { UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } processedBytes++; Byte b; if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { prevByte = b; continue; } bool status; if (b == 0xE8) status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1); else if (b == 0xE9) status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1); else status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1); if (status) { UInt32 src; if (b == 0xE8) { Byte b0; if(!_callStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } else { Byte b0; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } ================================================ FILE: src/lzma/C/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" // {23170F69-40C1-278B-0303-010100000100} #define MyClass2_a(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClass_a(Name, id, subId) \ MyClass2_a(Name ## _Encoder, id, subId, 0x01) \ MyClass2_a(Name ## _Decoder, id, subId, 0x00) MyClass_a(BCJ2_x86, 0x01, 0x1B) const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CBCJ2_x86_Encoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CBCJ2_x86_Encoder(): _buffer(0) {}; ~CBCJ2_x86_Encoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder _statusE8Encoder[256]; NCompress::NRangeCoder::CBitEncoder _statusE9Encoder; NCompress::NRangeCoder::CBitEncoder _statusJccEncoder; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CBCJ2_x86_Encoder *_coder; public: CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CBCJ2_x86_Decoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder _statusE8Decoder[256]; NCompress::NRangeCoder::CBitDecoder _statusE9Decoder; NCompress::NRangeCoder::CBitDecoder _statusJccDecoder; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CBCJ2_x86_Decoder *_coder; public: CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h ================================================ // BinTree.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace BT_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderBinTree: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderBinTree(); virtual ~CMatchFinderBinTree(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h ================================================ // BinTree2.h #ifndef __BINTREE2_H #define __BINTREE2_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT2 #include "BinTree.h" #include "BinTreeMain.h" #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h ================================================ // BinTree3.h #ifndef __BINTREE3_H #define __BINTREE3_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h ================================================ // BinTree3Z.h #ifndef __BINTREE3Z_H #define __BINTREE3Z_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ZIP #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h ================================================ // BinTree4.h #ifndef __BINTREE4_H #define __BINTREE4_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h ================================================ // BinTree4b.h #ifndef __BINTREE4B_H #define __BINTREE4B_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4B #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h ================================================ // BinTreeMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 3; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderBinTree::CMatchFinderBinTree(): _hash(0), _cutValue(0xFF) { } void CMatchFinderBinTree::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderBinTree::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderBinTree::~CMatchFinderBinTree() { FreeMemory(); } STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1); return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2]; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; #endif _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; // We don't need tree in this case } else #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; break; } Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < len) distances[++maxLen] = delta - 1; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch() { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit != kNumHashDirectBytes) #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) break; Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; } void CMatchFinderBinTree::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2); for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderBinTree::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderBinTree::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderBinTree::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HC.h ================================================ // HC.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace HC_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderHC: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderHC(); virtual ~CMatchFinderHC(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HC2.h ================================================ // HC2.h #ifndef __HC2_H #define __HC2_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC2 #include "HCMF.h" #include "HCMFMain.h" #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HC3.h ================================================ // HC3.h #ifndef __HC3_H #define __HC3_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC3 #define HASH_ARRAY_2 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HC4.h ================================================ // HC4.h #ifndef __HC4_H #define __HC4_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h ================================================ // HC4b.h #ifndef __HC4B__H #define __HC4B__H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4b #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h ================================================ // HC.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace HC_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (16); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderHC::CMatchFinderHC(): _hash(0), _cutValue(16) { } void CMatchFinderHC::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderHC::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderHC::~CMatchFinderHC() { FreeMemory(); } STDMETHODIMP CMatchFinderHC::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderHC::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderHC::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *chain = _hash + kHashSizeSum; chain[_cyclicBufferPos] = curMatch; distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; } else #endif { UInt32 count = _cutValue; do { if(curMatch <= matchMinPos) break; Byte *pby1 = _buffer + curMatch; UInt32 currentLen = kNumHashDirectBytes; do { if (pby1[currentLen] != cur[currentLen]) break; } while(++currentLen != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < currentLen) distances[++maxLen] = delta - 1; if(currentLen == lenLimit) break; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); curMatch = chain[cyclicPos]; } while(--count != 0); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch() { if (_streamPos - _pos < kNumHashBytes) return; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif _hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue]; _hash[hashValue] = _pos; } void CMatchFinderHC::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = kHashSizeSum + _cyclicBufferSize; for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderHC::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderHC::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderHC::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/IMatchFinder.h ================================================ // MatchFinders/IMatchFinder.h #ifndef __IMATCHFINDER_H #define __IMATCHFINDER_H // {23170F69-40C1-278A-0000-000200010000} DEFINE_GUID(IID_IInWindowStream, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000") IInWindowStream: public IUnknown { STDMETHOD(Init)(ISequentialInStream *inStream) PURE; STDMETHOD_(void, ReleaseStream)() PURE; STDMETHOD(MovePos)() PURE; STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020000} DEFINE_GUID(IID_IMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000") IMatchFinder: public IInWindowStream { STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE; STDMETHOD_(void, DummyLongestMatch)() PURE; }; // {23170F69-40C1-278A-0000-000200020100} DEFINE_GUID(IID_IMatchFinderCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100") IMatchFinderCallback: public IUnknown { STDMETHOD(BeforeChangingBufferPos)() PURE; STDMETHOD(AfterChangingBufferPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020200} DEFINE_GUID(IID_IMatchFinderSetCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200") IMatchFinderSetCallback: public IUnknown { STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE; }; /* // {23170F69-40C1-278A-0000-000200030000} DEFINE_GUID(IID_IInitMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000") IMatchFinderInit: public IUnknown { STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE; }; */ #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/LZInWindow.cpp ================================================ // LZInWindow.cpp #include "StdAfx.h" #include "LZInWindow.h" #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" void CLZInWindow::Free() { ::BigFree(_bufferBase); _bufferBase = 0; } bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == 0 || _blockSize != blockSize) { Free(); _blockSize = blockSize; if (_blockSize != 0) _bufferBase = (Byte *)::BigAlloc(_blockSize); } _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; if (_blockSize == 0) return true; return (_bufferBase != 0); } HRESULT CLZInWindow::Init(ISequentialInStream *stream) { _stream = stream; _buffer = _bufferBase; _pos = 0; _streamPos = 0; _streamEndWasReached = false; return ReadBlock(); } /* void CLZInWindow::ReleaseStream() { _stream.Release(); } */ /////////////////////////////////////////// // ReadBlock // In State: // (_buffer + _streamPos) <= (_bufferBase + _blockSize) // Out State: // _posLimit <= _blockSize - _keepSizeAfter; // if(_streamEndWasReached == false): // _streamPos >= _pos + _keepSizeAfter // _posLimit = _streamPos - _keepSizeAfter; // else // HRESULT CLZInWindow::ReadBlock() { if(_streamEndWasReached) return S_OK; while(true) { UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos; if(size == 0) return S_OK; UInt32 numReadBytes; RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; const Byte *pointerToPostion = _buffer + _posLimit; if(pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); _streamEndWasReached = true; return S_OK; } _streamPos += numReadBytes; if(_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; return S_OK; } } } void CLZInWindow::MoveBlock() { BeforeMoveBlock(); UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore; UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset; memmove(_bufferBase, _bufferBase + offset, numBytes); _buffer -= offset; AfterMoveBlock(); } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/LZInWindow.h ================================================ // LZInWindow.h #ifndef __LZ_IN_WINDOW_H #define __LZ_IN_WINDOW_H #include "../../IStream.h" class CLZInWindow { Byte *_bufferBase; // pointer to buffer with data ISequentialInStream *_stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream const Byte *_pointerToLastSafePosition; protected: Byte *_buffer; // Pointer to virtual Buffer begin UInt32 _blockSize; // Size of Allocated memory block UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream virtual void BeforeMoveBlock() {}; virtual void AfterMoveBlock() {}; void MoveBlock(); virtual HRESULT ReadBlock(); void Free(); public: CLZInWindow(): _bufferBase(0) {} virtual ~CLZInWindow() { Free(); } bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); HRESULT Init(ISequentialInStream *stream); // void ReleaseStream(); Byte *GetBuffer() const { return _buffer; } const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } HRESULT MovePos() { _pos++; if (_pos > _posLimit) { const Byte *pointerToPostion = _buffer + _pos; if(pointerToPostion > _pointerToLastSafePosition) MoveBlock(); return ReadBlock(); } else return S_OK; } Byte GetIndexByte(Int32 index)const { return _buffer[(size_t)_pos + index]; } // index + limit have not to exceed _keepSizeAfter; UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const { if(_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; Byte *pby = _buffer + (size_t)_pos + index; UInt32 i; for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); return i; } UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } void ReduceOffsets(Int32 subValue) { _buffer += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } }; #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "../../../Common/Alloc.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" /* #ifndef _NO_EXCEPTIONS class CLZOutWindowException { public: HRESULT ErrorCode; CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif */ typedef COutBufferException CLZOutWindowException; class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) { if (!_overDict) return false; pos += _bufferSize; } do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat.h ================================================ // Pat.h // #ifndef __PATRICIA__H // #define __PATRICIA__H #include "../../../../Common/MyCom.h" #include "../../../../Common/Types.h" #include "../LZInWindow.h" namespace PAT_NAMESPACE { struct CNode; typedef CNode *CNodePointer; // #define __AUTO_REMOVE // #define __NODE_4_BITS // #define __NODE_3_BITS // #define __NODE_2_BITS // #define __NODE_2_BITS_PADDING // #define __HASH_3 typedef UInt32 CIndex; #ifdef __NODE_4_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else #ifdef __NODE_3_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else typedef UInt32 CIndex; typedef UInt32 CSameBitsType; typedef CIndex CIndex2; #endif #endif const UInt32 kNumBitsInIndex = sizeof(CIndex) * 8; const UInt32 kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // don't change kMatchStartValue definition, since it is used in // PatMain.h: typedef CIndex CMatchPointer; const UInt32 kDescendantEmptyValue = kMatchStartValue - 1; union CDescendant { CIndex NodePointer; CMatchPointer MatchPointer; bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; } bool IsNode() const { return NodePointer < kDescendantEmptyValue; } bool IsMatch() const { return NodePointer > kDescendantEmptyValue; } void MakeEmpty() { NodePointer = kDescendantEmptyValue; } }; #undef MY_BYTE_SIZE #ifdef __NODE_4_BITS #define MY_BYTE_SIZE 8 const UInt32 kNumSubBits = 4; #else #ifdef __NODE_3_BITS #define MY_BYTE_SIZE 9 const UInt32 kNumSubBits = 3; #else #define MY_BYTE_SIZE 8 #ifdef __NODE_2_BITS const UInt32 kNumSubBits = 2; #else const UInt32 kNumSubBits = 1; #endif #endif #endif const UInt32 kNumSubNodes = 1 << kNumSubBits; const UInt32 kSubNodesMask = kNumSubNodes - 1; struct CNode { CIndex2 LastMatch; CSameBitsType NumSameBits; union { CDescendant Descendants[kNumSubNodes]; UInt32 NextFreeNode; }; #ifdef __NODE_2_BITS #ifdef __NODE_2_BITS_PADDING UInt32 Padding[2]; #endif #endif }; #undef kIDNumBitsByte #undef kIDNumBitsString #ifdef __NODE_4_BITS #define kIDNumBitsByte 0x30 #define kIDNumBitsString TEXT("4") #else #ifdef __NODE_3_BITS #define kIDNumBitsByte 0x20 #define kIDNumBitsString TEXT("3") #else #ifdef __NODE_2_BITS #define kIDNumBitsByte 0x10 #define kIDNumBitsString TEXT("2") #else #define kIDNumBitsByte 0x00 #define kIDNumBitsString TEXT("1") #endif #endif #endif #undef kIDManualRemoveByte #undef kIDManualRemoveString #ifdef __AUTO_REMOVE #define kIDManualRemoveByte 0x00 #define kIDManualRemoveString TEXT("") #else #define kIDManualRemoveByte 0x08 #define kIDManualRemoveString TEXT("R") #endif #undef kIDHash3Byte #undef kIDHash3String #ifdef __HASH_3 #define kIDHash3Byte 0x04 #define kIDHash3String TEXT("H") #else #define kIDHash3Byte 0x00 #define kIDHash3String TEXT("") #endif #undef kIDUse3BytesByte #undef kIDUse3BytesString #define kIDUse3BytesByte 0x00 #define kIDUse3BytesString TEXT("") #undef kIDPaddingByte #undef kIDPaddingString #ifdef __NODE_2_BITS_PADDING #define kIDPaddingByte 0x01 #define kIDPaddingString TEXT("P") #else #define kIDPaddingByte 0x00 #define kIDPaddingString TEXT("") #endif // #undef kIDString // #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String // {23170F69-40C1-278C-01XX-0000000000} DEFINE_GUID(PAT_CLSID, 0x23170F69, 0x40C1, 0x278C, 0x01, kIDNumBitsByte | kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // III(PAT_NAMESPACE) class CPatricia: public IMatchFinder, public IMatchFinderSetCallback, public CMyUnknownImp, CLZInWindow { MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *aStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); void FreeMemory(); public: CPatricia(); ~CPatricia(); UInt32 _sizeHistory; UInt32 _matchMaxLen; CDescendant *m_HashDescendants; #ifdef __HASH_3 CDescendant *m_Hash2Descendants; #endif CNode *m_Nodes; UInt32 m_FreeNode; UInt32 m_FreeNodeMax; #ifdef __AUTO_REMOVE UInt32 m_NumUsedNodes; UInt32 m_NumNodes; #else bool m_SpecialRemoveMode; #endif bool m_SpecialMode; UInt32 m_NumNotChangedCycles; UInt32 *m_TmpBacks; CMyComPtr m_Callback; virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); void ChangeLastMatch(UInt32 hashValue); #ifdef __AUTO_REMOVE void TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos); void TestRemoveNodes(); void RemoveNode(UInt32 index); void TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue); void TestRemoveNodesAndNormalize(); #else void NormalizeDescendant(CDescendant &descendant, UInt32 subValue); void Normalize(); void RemoveMatch(); #endif private: void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos) { while((aByteXOR & kSubNodesMask) == 0) { aByteXOR >>= kNumSubBits; aByte >>= kNumSubBits; aNumSameBits -= kNumSubBits; } // Insert New Node CNodePointer aNewNode = &m_Nodes[m_FreeNode]; UInt32 aNodeIndex = *aNodePointerPointer; *aNodePointerPointer = m_FreeNode; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = aByte & kSubNodesMask; UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex; aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits); aNewNode->LastMatch = aPos; aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits); } void AddLeafNode(CNodePointer aNode, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos, UInt32 aDescendantIndex) { for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits) { aByte >>= kNumSubBits; aByteXOR >>= kNumSubBits; } UInt32 aNewNodeIndex = m_FreeNode; CNodePointer aNewNode = &m_Nodes[m_FreeNode]; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = (aByte & kSubNodesMask); UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].MatchPointer = aNode->Descendants[aDescendantIndex].MatchPointer; aNewNode->NumSameBits = CSameBitsType(aNumSameBits); aNewNode->LastMatch = aPos; aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex; } }; } // #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h ================================================ // Pat2.h #ifndef __PAT2__H #define __PAT2__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2 #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2 #define __AUTO_REMOVE #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h ================================================ // Pat2H.h #ifndef __PAT2H__H #define __PAT2H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2H #define __AUTO_REMOVE #define __NODE_2_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #undef __HASH_3 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h ================================================ // Pat2R.h #ifndef __PAT2R__H #define __PAT2R__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2R #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2R #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __NODE_2_BITS #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h ================================================ // Pat3H.h #ifndef __PAT3H__H #define __PAT3H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat3H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat3H #define __AUTO_REMOVE #define __NODE_3_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_3_BITS #undef __HASH_3 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h ================================================ // Pat4H.h #ifndef __PAT4H__H #define __PAT4H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat4H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat4H #define __AUTO_REMOVE #define __NODE_4_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_4_BITS #undef __HASH_3 #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h ================================================ // PatMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/Alloc.h" namespace PAT_NAMESPACE { STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CPatricia::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CPatricia::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } const UInt32 kMatchStartValue2 = 2; const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1; const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1; #ifdef __HASH_3 static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kNumHash2Bytes = 2; static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes); static const UInt32 kPrevHashSize = kNumHash2Bytes; #else static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kPrevHashSize = 0; #endif CPatricia::CPatricia(): m_HashDescendants(0), #ifdef __HASH_3 m_Hash2Descendants(0), #endif m_Nodes(0), m_TmpBacks(0) { } CPatricia::~CPatricia() { FreeMemory(); } void CPatricia::FreeMemory() { MyFree(m_TmpBacks); m_TmpBacks = 0; ::BigFree(m_Nodes); m_Nodes = 0; ::BigFree(m_HashDescendants); m_HashDescendants = 0; #ifdef __HASH_3 ::BigFree(m_Hash2Descendants); m_Hash2Descendants = 0; CLZInWindow::Free(); #endif } STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { FreeMemory(); int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8; if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits))) return E_INVALIDARG; const UInt32 kAlignMask = (1 << 16) - 1; UInt32 windowReservSize = historySize; windowReservSize += kAlignMask; windowReservSize &= ~(kAlignMask); const UInt32 kMinReservSize = (1 << 19); if (windowReservSize < kMinReservSize) windowReservSize = kMinReservSize; windowReservSize += 256; if (!CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize)) return E_OUTOFMEMORY; _sizeHistory = historySize; _matchMaxLen = matchMaxLen; m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant)); if (m_HashDescendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #ifdef __HASH_3 m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant)); if (m_Hash2Descendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #endif #ifdef __AUTO_REMOVE #ifdef __HASH_3 m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19); #else m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10); #endif #else UInt32 m_NumNodes = historySize; #endif const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1); if (m_NumNodes + 32 > kMaxNumNodes) return E_INVALIDARG; // m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode)); m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode)); if (m_Nodes == 0) { FreeMemory(); return E_OUTOFMEMORY; } m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32)); if (m_TmpBacks == 0) { FreeMemory(); return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream) { RINOK(CLZInWindow::Init(aStream)); // memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0])); #ifdef __HASH_3 for (UInt32 i = 0; i < kHash2Size; i++) m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2; #else for (UInt32 i = 0; i < kHashSize; i++) m_HashDescendants[i].MakeEmpty(); #endif m_Nodes[0].NextFreeNode = 1; m_FreeNode = 0; m_FreeNodeMax = 0; #ifdef __AUTO_REMOVE m_NumUsedNodes = 0; #else m_SpecialRemoveMode = false; #endif m_SpecialMode = false; return S_OK; } STDMETHODIMP_(void) CPatricia::ReleaseStream() { // CLZInWindow::ReleaseStream(); } // pos = _pos + kNumHashBytes // fullCurrentLimit = currentLimit + kNumHashBytes // fullMatchLen = matchLen + kNumHashBytes void CPatricia::ChangeLastMatch(UInt32 hashValue) { UInt32 pos = _pos + kNumHashBytes - 1; UInt32 descendantIndex; const Byte *currentBytePointer = _buffer + pos; UInt32 numLoadedBits = 0; Byte curByte = 0; // = 0 to disable warning of GCC CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer]; while(true) { UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits < numSameBits) { numSameBits -= numLoadedBits; currentBytePointer += (numSameBits / MY_BYTE_SIZE); numSameBits %= MY_BYTE_SIZE; curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } curByte >>= numSameBits; numLoadedBits -= numSameBits; } if(numLoadedBits == 0) { curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } descendantIndex = (curByte & kSubNodesMask); node->LastMatch = pos; numLoadedBits -= kNumSubBits; curByte >>= kNumSubBits; if(node->Descendants[descendantIndex].IsNode()) node = &m_Nodes[node->Descendants[descendantIndex].NodePointer]; else break; } node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; } UInt32 CPatricia::GetLongestMatch(UInt32 *distances) { UInt32 fullCurrentLimit; if (_pos + _matchMaxLen <= _streamPos) fullCurrentLimit = _matchMaxLen; else { fullCurrentLimit = _streamPos - _pos; if(fullCurrentLimit < kNumHashBytes) return 0; } UInt32 pos = _pos + kNumHashBytes; #ifdef __HASH_3 UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1]; UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2) { if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2) { UInt32 base = hashValue & 0xFFFF00; for (UInt32 i = 0; i < 0x100; i++) m_HashDescendants[base + i].MakeEmpty(); } hash2Descendant.MatchPointer = pos + kMatchStartValue2; hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1; hash2Descendant.MatchPointer = pos + kMatchStartValue2; #ifdef __AUTO_REMOVE if (distances[kNumHash2Bytes] >= _sizeHistory) { if (hashDescendant.IsNode()) RemoveNode(hashDescendant.NodePointer); hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } #endif if (fullCurrentLimit == kNumHash2Bytes) return kNumHash2Bytes; #else UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(m_SpecialMode) { if(hashDescendant.IsMatch()) m_NumNotChangedCycles = 0; if(m_NumNotChangedCycles >= _sizeHistory - 1) { ChangeLastMatch(hashValue); m_NumNotChangedCycles = 0; } if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2)) { if(hashDescendant.IsMatch()) hashDescendant.MatchPointer = pos + kMatchStartValue; else m_NumNotChangedCycles++; for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++) distances[i] = 0; return fullCurrentLimit; } else if(m_NumNotChangedCycles > 0) ChangeLastMatch(hashValue); m_SpecialMode = false; } if(hashDescendant.IsEmpty()) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } UInt32 currentLimit = fullCurrentLimit - kNumHashBytes; if(hashDescendant.IsMatch()) { CMatchPointer matchPointer = hashDescendant.MatchPointer; UInt32 backReal = pos - (matchPointer - kMatchStartValue); UInt32 back = backReal - 1; #ifdef __AUTO_REMOVE if (back >= _sizeHistory) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } #endif UInt32 matchLen; distances += kNumHashBytes; Byte *buffer = _buffer + pos; for(matchLen = 0; true; matchLen++) { *distances++ = back; if (matchLen == currentLimit) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kNumHashBytes + matchLen; } if (buffer[matchLen] != buffer[(size_t)matchLen - backReal]) break; } // UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit); UInt32 fullMatchLen = matchLen + kNumHashBytes; hashDescendant.NodePointer = m_FreeNode; CNodePointer node = &m_Nodes[m_FreeNode]; m_FreeNode = node->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].NodePointer = kDescendantEmptyValue; node->LastMatch = pos; Byte byteNew = GetIndexByte(fullMatchLen); Byte byteOld = GetIndexByte(fullMatchLen - backReal); Byte bitsNew, bitsOld; UInt32 numSameBits = matchLen * MY_BYTE_SIZE; while (true) { bitsNew = (byteNew & kSubNodesMask); bitsOld = (byteOld & kSubNodesMask); if(bitsNew != bitsOld) break; byteNew >>= kNumSubBits; byteOld >>= kNumSubBits; numSameBits += kNumSubBits; } node->NumSameBits = CSameBitsType(numSameBits); node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue; node->Descendants[bitsOld].MatchPointer = matchPointer; return fullMatchLen; } const Byte *baseCurrentBytePointer = _buffer + pos; const Byte *currentBytePointer = baseCurrentBytePointer; UInt32 numLoadedBits = 0; Byte curByte = 0; CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[*nodePointerPointer]; distances += kNumHashBytes; const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit; const Byte *currentAddingOffset = _buffer; #ifdef __AUTO_REMOVE UInt32 lowPos; if (pos > _sizeHistory) lowPos = pos - _sizeHistory; else lowPos = 0; #endif while(true) { #ifdef __AUTO_REMOVE if (node->LastMatch < lowPos) { RemoveNode(*nodePointerPointer); *nodePointerPointer = pos + kMatchStartValue; if (currentBytePointer == baseCurrentBytePointer) return kPrevHashSize; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif if(numLoadedBits == 0) { *distances++ = pos - node->LastMatch - 1; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = 0; return fullCurrentLimit; } curByte = (*currentBytePointer++); currentAddingOffset++; numLoadedBits = MY_BYTE_SIZE; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >> (MY_BYTE_SIZE - numLoadedBits)) ^ curByte; while(numLoadedBits <= numSameBits) { if(byteXOR != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } *distances++ = pos - node->LastMatch - 1; numSameBits -= numLoadedBits; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits); return fullCurrentLimit; } numLoadedBits = MY_BYTE_SIZE; curByte = (*currentBytePointer++); byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch)); currentAddingOffset++; } if((byteXOR & ((1 << numSameBits) - 1)) != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } curByte >>= numSameBits; numLoadedBits -= numSameBits; } UInt32 descendantIndex = (curByte & kSubNodesMask); numLoadedBits -= kNumSubBits; nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; UInt32 nextNodeIndex = *nodePointerPointer; node->LastMatch = pos; if (nextNodeIndex < kDescendantEmptyValue) { curByte >>= kNumSubBits; node = &m_Nodes[nextNodeIndex]; } else if (nextNodeIndex == kDescendantEmptyValue) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } else break; } UInt32 descendantIndex = (curByte & kSubNodesMask); curByte >>= kNumSubBits; CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer; CMatchPointer realMatchPointer; realMatchPointer = matchPointer - kMatchStartValue; #ifdef __AUTO_REMOVE if (realMatchPointer < lowPos) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif Byte byteXOR; UInt32 numSameBits = 0; if(numLoadedBits != 0) { Byte matchByte = *(currentAddingOffset + realMatchPointer -1); matchByte >>= (MY_BYTE_SIZE - numLoadedBits); byteXOR = matchByte ^ curByte; if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } numSameBits += numLoadedBits; } const Byte *matchBytePointer = _buffer + realMatchPointer + (currentBytePointer - baseCurrentBytePointer); for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE) { curByte = (*currentBytePointer++); *distances++ = pos - realMatchPointer - 1; byteXOR = curByte ^ (*matchBytePointer++); if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } } *distances = pos - realMatchPointer - 1; node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; if(*distances == 0) { m_SpecialMode = true; m_NumNotChangedCycles = 0; } return fullCurrentLimit; } STDMETHODIMP_(void) CPatricia::DummyLongestMatch() { GetLongestMatch(m_TmpBacks); } // ------------------------------------ // Remove Match typedef Byte CRemoveDataWord; static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord); #ifndef __AUTO_REMOVE void CPatricia::RemoveMatch() { if(m_SpecialRemoveMode) { if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) == GetIndexByte(_matchMaxLen - _sizeHistory)) return; m_SpecialRemoveMode = false; } UInt32 pos = _pos + kNumHashBytes - _sizeHistory; #ifdef __HASH_3 const Byte *pp = _buffer + _pos - _sizeHistory; UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1]; UInt32 hashValue = (hash2Value << 8) | pp[2]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; if (hash2Descendant >= kMatchStartValue2) if(hash2Descendant.MatchPointer == pos + kMatchStartValue2) hash2Descendant.MatchPointer = kDescendantEmptyValue2; #else UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) | (UInt32(GetIndexByte(0 - _sizeHistory)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(hashDescendant.IsEmpty()) return; if(hashDescendant.IsMatch()) { if(hashDescendant.MatchPointer == pos + kMatchStartValue) hashDescendant.MakeEmpty(); return; } UInt32 descendantIndex; const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos); UInt32 numLoadedBits = 0; CRemoveDataWord curWord = 0; // = 0 to disable GCC warning CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[hashDescendant.NodePointer]; while(true) { if(numLoadedBits == 0) { curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits <= numSameBits) { numSameBits -= numLoadedBits; currentPointer += (numSameBits / kSizeRemoveDataWordInBits); numSameBits %= kSizeRemoveDataWordInBits; curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } curWord >>= numSameBits; numLoadedBits -= numSameBits; } descendantIndex = (curWord & kSubNodesMask); numLoadedBits -= kNumSubBits; curWord >>= kNumSubBits; UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer; if (nextNodeIndex < kDescendantEmptyValue) { nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; node = &m_Nodes[nextNodeIndex]; } else break; } if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue) { const Byte *currentBytePointer = _buffer + _pos - _sizeHistory; const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen; for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++) if(*currentBytePointer != *(currentBytePointer+1)) return; m_SpecialRemoveMode = true; return; } UInt32 numNodes = 0, numMatches = 0; UInt32 i; for (i = 0; i < kNumSubNodes; i++) { UInt32 nodeIndex = node->Descendants[i].NodePointer; if (nodeIndex < kDescendantEmptyValue) numNodes++; else if (nodeIndex > kDescendantEmptyValue) numMatches++; } numMatches -= 1; if (numNodes + numMatches > 1) { node->Descendants[descendantIndex].MakeEmpty(); return; } if(numNodes == 1) { UInt32 i; for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsNode()) break; UInt32 nextNodeIndex = node->Descendants[i].NodePointer; CNodePointer nextNode = &m_Nodes[nextNodeIndex]; nextNode->NumSameBits += node->NumSameBits + kNumSubBits; *node = *nextNode; nextNode->NextFreeNode = m_FreeNode; m_FreeNode = nextNodeIndex; return; } UInt32 matchPointer = 0; // = 0 to disable GCC warning for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsMatch() && i != descendantIndex) { matchPointer = node->Descendants[i].MatchPointer; break; } node->NextFreeNode = m_FreeNode; m_FreeNode = *nodePointerPointer; *nodePointerPointer = matchPointer; } #endif // Commented code is more correct, but it gives warning // on GCC: (1 << 32) // So we use kMatchStartValue twice: // kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // must be defined in Pat.h /* const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) - kMatchStartValue - kNumHashBytes - 1; */ const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1; STDMETHODIMP CPatricia::MovePos() { #ifndef __AUTO_REMOVE if(_pos >= _sizeHistory) RemoveMatch(); #endif RINOK(CLZInWindow::MovePos()); #ifdef __AUTO_REMOVE if (m_NumUsedNodes >= m_NumNodes) TestRemoveNodes(); #endif if (_pos >= kNormalizeStartPos) { #ifdef __AUTO_REMOVE TestRemoveNodesAndNormalize(); #else Normalize(); #endif } return S_OK; } #ifndef __AUTO_REMOVE void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) descendant.MatchPointer = descendant.MatchPointer - subValue; else { CNode &node = m_Nodes[descendant.NodePointer]; node.LastMatch = node.LastMatch - subValue; for (UInt32 i = 0; i < kNumSubNodes; i++) NormalizeDescendant(node.Descendants[i], subValue); } } void CPatricia::Normalize() { UInt32 subValue = _pos - _sizeHistory; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) NormalizeDescendant(m_HashDescendants[base + i], subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) NormalizeDescendant(m_HashDescendants[hash], subValue); #endif } #else void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos) { CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsEmpty()) continue; if (descendant2.IsMatch()) { if (descendant2.MatchPointer < limitPos) descendant2.MakeEmpty(); else { numChilds++; childIndex = i; } } else { TestRemoveDescendant(descendant2, limitPos); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } } if (numChilds > 1) return; CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::RemoveNode(UInt32 index) { CNode &node = m_Nodes[index]; for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsNode()) RemoveNode(descendant2.NodePointer); } node.NextFreeNode = m_FreeNode; m_FreeNode = index; m_NumUsedNodes--; } void CPatricia::TestRemoveNodes() { UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) { CDescendant &descendant = m_HashDescendants[base + i]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) { CDescendant &descendant = m_HashDescendants[hash]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } #endif } void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); else descendant.MatchPointer = descendant.MatchPointer - subValue; return; } CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } if (numChilds > 1) { node.LastMatch = node.LastMatch - subValue; return; } CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::TestRemoveNodesAndNormalize() { UInt32 subValue = _pos - _sizeHistory; UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; else descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue); #endif } #endif STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } } ================================================ FILE: src/lzma/C/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); while (true) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); return SetDecoderPropertiesRaw(lc, lp, pb, dictionarySize); } STDMETHODIMP CDecoder::SetDecoderPropertiesRaw(int lc, int lp, int pb, UInt32 dictionarySize) { if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { if (_outSizeDefined = (outSize != NULL)) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifdef _ST_MODE STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, #ifdef _ST_MODE public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifdef _ST_MODE MY_UNKNOWN_IMP4( ICompressSetDecoderProperties2, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP1( ICompressSetDecoderProperties2) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifdef _ST_MODE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // for minimal compressing code size define these: // #define COMPRESS_MF_BT // #define COMPRESS_MF_BT4 #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC) #define COMPRESS_MF_BT #define COMPRESS_MF_PAT #define COMPRESS_MF_HC #endif #ifdef COMPRESS_MF_BT #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B) #define COMPRESS_MF_BT2 #define COMPRESS_MF_BT3 #define COMPRESS_MF_BT4 #define COMPRESS_MF_BT4B #endif #ifdef COMPRESS_MF_BT2 #include "../LZ/BinTree/BinTree2.h" #endif #ifdef COMPRESS_MF_BT3 #include "../LZ/BinTree/BinTree3.h" #endif #ifdef COMPRESS_MF_BT4 #include "../LZ/BinTree/BinTree4.h" #endif #ifdef COMPRESS_MF_BT4B #include "../LZ/BinTree/BinTree4b.h" #endif #endif #ifdef COMPRESS_MF_PAT #include "../LZ/Patricia/Pat2.h" #include "../LZ/Patricia/Pat2H.h" #include "../LZ/Patricia/Pat3H.h" #include "../LZ/Patricia/Pat4H.h" #include "../LZ/Patricia/Pat2R.h" #endif #ifdef COMPRESS_MF_HC #include "../LZ/HashChain/HC3.h" #include "../LZ/HashChain/HC4.h" #endif #ifdef COMPRESS_MF_MT #include "../LZ/MT/MT.h" #endif namespace NCompress { namespace NLZMA { const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; enum { kBT2, kBT3, kBT4, kBT4B, kPat2, kPat2H, kPat3H, kPat4H, kPat2R, kHC3, kHC4 }; static const wchar_t *kMatchFinderIDs[] = { L"BT2", L"BT3", L"BT4", L"BT4B", L"PAT2", L"PAT2H", L"PAT3H", L"PAT4H", L"PAT2R", L"HC3", L"HC4" }; Byte g_FastPos[1024]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const { if(symbol < kNumLowSymbols) return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol); UInt32 price = _choice.GetPrice1(); if(symbol < kNumLowSymbols + kNumMidSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols); } return price; } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _dictionarySizePrev(UInt32(-1)), _numFastBytesPrev(UInt32(-1)), _matchFinderIndex(kBT4), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { _maxMode = false; _fastMode = false; } HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_matchFinder) { switch(_matchFinderIndex) { #ifdef COMPRESS_MF_BT #ifdef COMPRESS_MF_BT2 case kBT2: _matchFinder = new NBT2::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT3 case kBT3: _matchFinder = new NBT3::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4 case kBT4: _matchFinder = new NBT4::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4B case kBT4B: _matchFinder = new NBT4B::CMatchFinderBinTree; break; #endif #endif #ifdef COMPRESS_MF_PAT case kPat2: _matchFinder = new NPat2::CPatricia; break; case kPat2H: _matchFinder = new NPat2H::CPatricia; break; case kPat3H: _matchFinder = new NPat3H::CPatricia; break; case kPat4H: _matchFinder = new NPat4H::CPatricia; break; case kPat2R: _matchFinder = new NPat2R::CPatricia; break; #endif #ifdef COMPRESS_MF_HC case kHC3: _matchFinder = new NHC3::CMatchFinderHC; break; case kHC4: _matchFinder = new NHC4::CMatchFinderHC; break; #endif } if (_matchFinder == 0) return E_OUTOFMEMORY; #ifdef COMPRESS_MF_MT if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4))) { CMatchFinderMT *mfSpec = new CMatchFinderMT; if (mfSpec == 0) return E_OUTOFMEMORY; CMyComPtr mf = mfSpec; RINOK(mfSpec->SetMatchFinder(_matchFinder)); _matchFinder.Release(); _matchFinder = mf; } #endif } if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return S_OK; RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen * 2 + 1 - _numFastBytes)); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; return S_OK; } static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) { while (true) { wchar_t c = *testString; if (c >= 'a' && c <= 'z') c -= 0x20; if (*base != c) return false; if (c == 0) return true; base++; testString++; } } static int FindMatchFinder(const wchar_t *s) { for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) if (AreStringsEqual(kMatchFinderIDs[m], s)) return m; return -1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; int matchFinderIndexPrev = _matchFinderIndex; int m = FindMatchFinder(prop.bstrVal); if (m < 0) return E_INVALIDARG; _matchFinderIndex = m; if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } break; } #ifdef COMPRESS_MF_MT case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } _multiThread = newMultiThread; break; } #endif case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 28; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); // _repMatchLenEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } HRESULT CEncoder::MovePos(UInt32 num) { for (;num != 0; num--) { _matchFinder->DummyLongestMatch(); RINOK(_matchFinder->MovePos()); _additionalOffset++; } return S_OK; } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit) { back++; for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++); return i; } */ /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return S_OK; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } Byte currentByte = _matchFinder->GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if(lenMain < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for(len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); COptimal &optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); /* if (curOptimum.Prev1IsChar) for(int i = 0; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i]; */ } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 newLen; RINOK(ReadMatchDistances(newLen)); if(newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } UInt32 curPrice = curOptimum.Price; // Byte currentByte = _matchFinder->GetIndexByte(0 - 1); // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { // try Literal + rep0 UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) if (data[temp] != data[(size_t)temp - backOffset]) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while(lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (data[lenTest] != data[(size_t)lenTest - backOffset]) break; UInt32 lenTestTemp = lenTest; do { while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { // Try Match + Literal + Rep0 UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif)); } HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes) { lenRes = _matchFinder->GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes], kMatchMaxLen - lenRes); _additionalOffset++; return _matchFinder->MovePos(); } HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12))) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } } if (lenMain >= 2) { RINOK(ReadMatchDistances(_longestMatchLength)); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } for(UInt32 i = 0; i < kNumRepDistances; i++) { UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } } backRes = backMain + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 2); } backRes = UInt32(-1); lenRes = 1; return S_OK; } STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder) { _matchFinder = matchFinder; return S_OK; } HRESULT CEncoder::Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { _needReleaseMFStream = false; CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); while(true) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) return S_OK; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; return S_OK; } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { RINOK(_matchFinder->Init(_inStream)); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return S_OK; _finished = true; UInt64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); UInt32 len; // it's not used RINOK(ReadMatchDistances(len)); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); while(true) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos; UInt32 posState = UInt32(nowPos64) & _posStateMask; UInt32 len; HRESULT result; if (_fastMode) result = GetOptimumFast(UInt32(nowPos64), pos, len); else result = GetOptimum(UInt32(nowPos64), pos, len); RINOK(result); if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte); if(!_state.IsCharState()) { Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } else subCoder->Encode(&_rangeEncoder, curByte); _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); if(len == 1) _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0); else _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for(UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for(UInt32 i = kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; *finished = 0; return S_OK; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); } } void CEncoder::FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; for (; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } } } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = kAlignTableSize; } }} ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/IMatchFinder.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; extern Byte g_FastPos[1024]; inline UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } inline UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[GetState(pos, prevByte)]; } /* void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); } void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte matchByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, matchByte, symbol); } */ UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); UInt32 GetPrice(UInt32 symbol, UInt32 posState) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[symbol][posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[len][posState] = CEncoder::GetPrice(len, posState); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { CEncoder::Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } }; } class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { COptimal _optimum[kNumOpts]; CMyComPtr _matchFinder; // test it NRangeCoder::CEncoder _rangeEncoder; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen + 1]; bool _fastMode; bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _dictionarySizePrev; UInt32 _numFastBytesPrev; UInt64 lastPosSlotFillingPos; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; int _matchFinderIndex; #ifdef COMPRESS_MF_MT bool _multiThread; #endif bool _writeEndMark; bool _needReleaseMFStream; HRESULT ReadMatchDistances(UInt32 &len); HRESULT MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState); if(repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); void FillPosSlotPrices(); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseMFStream() { if (_matchFinder && _needReleaseMFStream) { _matchFinder->ReleaseStream(); _needReleaseMFStream = false; } } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // IInitMatchFinder interface STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder() {} }; }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Group "Pat" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\Patricia\Pat.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2R.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat3H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat4H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\PatMain.h # End Source File # End Group # Begin Group "BT" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\BinTree\BinTree.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree2.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3Z.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3ZMain.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4b.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTreeMain.h # End Source File # End Group # Begin Group "HC" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\HashChain\HC.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC2.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC3.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4b.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HCMain.h # End Source File # End Group # Begin Source File SOURCE=..\LZ\IMatchFinder.h # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.h # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\Branch\BranchX86.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\Alloc.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\String.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\String.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include #include #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBench.h" #include "LzmaRam.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kLitContext, kLitPos, kPosBits, kMatchFinder, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kSimple, false } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA inputFile outputFile [...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "\n" " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n" " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (n == 1) { PrintHelp(); return 0; } if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = 1 << 21; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 10; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchmark(stderr, numIterations, dictionary, mf.CompareNoCase(L"BT4") == 0); } bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr outStream; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; COutFileStream *outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 2; UInt32 numFastBytes = 128; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); /* NWindows::NCOM::CPropVariant properties[kNumProps]; properties[0] = UInt32(dictionary); properties[1] = UInt32(posStateBits); properties[2] = UInt32(litContextBits); properties[3] = UInt32(litPosBits); properties[4] = UInt32(algorithm); properties[5] = UInt32(numFastBytes); properties[6] = mf; properties[7] = eos; */ PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #include #endif #include "../../../Common/CRC.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" static const UInt32 kAdditionalSize = #ifdef _WIN32_WCE (1 << 20); #else (6 << 20); #endif static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public: CRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBitRandomGenerator { CRandomGenerator RG; UInt32 Value; int NumBits; public: void Init() { Value = 0; NumBits = 0; } UInt32 GetRnd(int numBits) { if (NumBits > numBits) { UInt32 result = Value & ((1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; UInt32 result = (Value << numBits); Value = RG.GetRnd(); result |= Value & ((1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG; UInt32 Pos; public: UInt32 BufferSize; Byte *Buffer; CBenchRandomGenerator(): Buffer(0) {} ~CBenchRandomGenerator() { delete []Buffer; } void Init() { RG.Init(); } void Set(UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd(len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } void Generate() { while(Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = Byte(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; UInt32 Pos; UInt32 Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, UInt32 size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CMyUnknownImp { UInt32 BufferSize; FILE *_f; public: UInt32 Pos; Byte *Buffer; CBenchmarkOutStream(): _f(0), Buffer(0) {} virtual ~CBenchmarkOutStream() { delete []Buffer; } void Init(FILE *f, UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; _f = f; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < BufferSize; i++) Buffer[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { fprintf(_f, "\nERROR: Buffer is full\n"); return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: CCRC CRC; MY_UNKNOWN_IMP void Init() { CRC.Init(); } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { CRC.Update(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; return GetTickCount(); #else return clock(); #endif } static UInt64 GetFreq() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; return 1000; #else return CLOCKS_PER_SEC; #endif } struct CProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { UInt64 ApprovedStart; UInt64 InSize; UInt64 Time; void Init() { InSize = 0; Time = 0; } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { if (*inSize >= ApprovedStart && InSize == 0) { Time = ::GetTimeCount(); InSize = *inSize; } return S_OK; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = GetFreq(); UInt64 elTime = elapsedTime; while(freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } /* static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } */ static void PrintRating(FILE *f, UInt64 rating) { fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000)); } static void PrintResults( FILE *f, UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024)); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(f, rating); } static void ThrowError(FILE *f, HRESULT result, const char *s) { fprintf(f, "\nError: "); if (result == E_ABORT) fprintf(f, "User break"); if (result == E_OUTOFMEMORY) fprintf(f, "Can not allocate memory"); else fprintf(f, s); fprintf(f, "\n"); } const wchar_t *bt2 = L"BT2"; const wchar_t *bt4 = L"BT4"; int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations == 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n"); return 1; } fprintf(f, "\n Compressing Decompressing\n\n"); NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream; CMyComPtr propStream = propStreamSpec; propStreamSpec->Init(f, kMaxLzmaPropSize); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMatchFinder }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = UInt32(dictionarySize); properties[1].vt = VT_BSTR; properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2; const UInt32 kBufferSize = dictionarySize + kAdditionalSize; const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) { fprintf(f, "\nError: Incorrect command\n"); return 1; } encoderSpec->WriteCoderProperties(propStream); CBenchRandomGenerator rg; rg.Init(); rg.Set(kBufferSize); rg.Generate(); CCRC crc; crc.Update(rg.Buffer, rg.BufferSize); CProgressInfo *progressInfoSpec = new CProgressInfo; CMyComPtr progressInfo = progressInfoSpec; progressInfoSpec->ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; for (UInt32 i = 0; i < numIterations; i++) { progressInfoSpec->Init(); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; inStreamSpec->Init(rg.Buffer, rg.BufferSize); CMyComPtr inStream = inStreamSpec; CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream; outStreamSpec->Init(f, kCompressedBufferSize); CMyComPtr outStream = outStreamSpec; HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo); UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time; UInt32 compressedSize = outStreamSpec->Pos; if(result != S_OK) { ThrowError(f, result, "Encoder Error"); return 1; } if (progressInfoSpec->InSize == 0) { fprintf(f, "\nError: Internal ERROR 1282\n"); return 1; } /////////////////////// // Decompressing CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr crcOutStream = crcOutStreamSpec; UInt64 decodeTime; for (int j = 0; j < 2; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK) { fprintf(f, "\nError: Set Decoder Properties Error\n"); return 1; } UInt64 outSize = kBufferSize; UInt64 startTime = ::GetTimeCount(); result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0); decodeTime = ::GetTimeCount() - startTime; if(result != S_OK) { ThrowError(f, result, "Decode Error"); return 1; } if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest()) { fprintf(f, "\nError: CRC Error\n"); return 1; } } UInt64 benchSize = kBufferSize - progressInfoSpec->InSize; PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); fprintf(f, "\n"); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } fprintf(f, "---------------------------------------------------\n"); PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, totalDecodeTime, kBufferSize * numIterations, true, totalCompressedSize); fprintf(f, " Average\n"); return 0; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LzmaBench_h #define __LzmaBench_h #include #include "../../../Common/Types.h" int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4); #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZE_FAIL (1) #define SZE_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZE_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1); } UInt32 minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZE_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZE_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZE_OUTOFMEMORY; } #endif } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../LZMA_C/LzmaDecode.h" #include "../Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0); } return 0; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) -I ../../../ LIBS = $(LIBS) oleaut32.lib user32.lib !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\Alloc.obj \ $O\CRC.obj \ $O\CommandLineParser.obj \ $O\String.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Vector.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ $O\LZOutWindow.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaRam.o \ LzmaRamDecode.o \ LzmaDecode.o \ BranchX86.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c LzmaDecode.o: ../LZMA_C/LzmaDecode.c $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c BranchX86.o: ../Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c ================================================ /* 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; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h ================================================ /* 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 #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 ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.27 Copyright (c) 1999-2005 Igor Pavlov (2005-08-07) 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 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) 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. */ #include "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; while(1) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ /* #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 #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 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include #include #include #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include #include #include #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/makefile ================================================ PROG = lzmaDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** OBJS = \ $O\LzmaTest.obj \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\LzmaTest.obj: $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_C/makefile.gcc ================================================ PROG = lzmadec CXX = gcc LIB = RM = rm -f CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 OBJS = LzmaTest.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaTest.o: LzmaTest.c $(CXX) $(CFLAGS) LzmaTest.c LzmaDecode.o: LzmaDecode.c $(CXX) $(CFLAGS) LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp ================================================ /* * lzma zlib simplified wrapper * * Copyright (c) 2005-2006 Oleg I. Vdovikin * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA */ /* * default values for encoder/decoder used by wrapper */ #include #define ZLIB_LC 3 #define ZLIB_LP 0 #define ZLIB_PB 2 #ifdef WIN32 #include #else #define INITGUID #endif #include "../../../Common/MyWindows.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #define STG_E_SEEKERROR ((HRESULT)0x80030019L) #define STG_E_MEDIUMFULL ((HRESULT)0x80030070L) class CInMemoryStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: CInMemoryStream(const Bytef *data, UInt64 size) : m_data(data), m_size(size), m_offset(0) {} virtual ~CInMemoryStream() {} MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (size > m_size - m_offset) size = m_size - m_offset; if (size) { memcpy(data, m_data + m_offset, size); } m_offset += size; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) { return Read(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_size) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(GetSize)(UInt64 *size) { *size = m_size; return S_OK; } protected: const Bytef *m_data; UInt64 m_size; UInt64 m_offset; }; class COutMemoryStream: public IOutStream, public CMyUnknownImp { public: COutMemoryStream(Bytef *data, UInt64 maxsize) : m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {} virtual ~COutMemoryStream() {} MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (size > m_maxsize - m_offset) size = m_maxsize - m_offset; if (size) { memcpy(m_data + m_offset, data, size); } m_offset += size; if (m_offset > m_size) m_size = m_offset; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) { return Write(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_maxsize) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(SetSize)(Int64 newSize) { if ((UInt64)newSize > m_maxsize) return STG_E_MEDIUMFULL; return S_OK; } protected: Bytef *m_data; UInt64 m_size; UInt64 m_maxsize; UInt64 m_offset; }; ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr outStream = outStreamSpec; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(1 << (level + 14)); properties[1].ulVal = UInt32(ZLIB_PB); properties[2].ulVal = UInt32(ZLIB_LC); // for normal files properties[3].ulVal = UInt32(ZLIB_LP); // for normal files properties[4].ulVal = UInt32(2); properties[5].ulVal = UInt32(128); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4"; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_TRUE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return Z_MEM_ERROR; // should not happen HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { return Z_MEM_ERROR; } else if (result != S_OK) { return Z_BUF_ERROR; // should not happen } UInt64 fileSize; outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)) { /* CJH: 7zip ID implemented by some LZMA implementations */ if(strncmp((char *) source, "7zip", 4) == 0) { source += 4; sourceLen -= 4; } CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr outStream = outStreamSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_LC, ZLIB_LP, ZLIB_PB, (1 << 23)) != S_OK) return Z_DATA_ERROR; UInt64 fileSize = *destLen; if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { return Z_DATA_ERROR; } outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ================================================ FILE: src/lzma/C/7zip/Compress/LZMA_Lib/makefile ================================================ PROG = liblzma.a CXX = g++ -O3 -Wall AR = ar RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ ZLib.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ StreamUtils.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(AR) r $(PROG) $(OBJS) ZLib.o: ZLib.cpp $(CXX) $(CFLAGS) ZLib.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template class CBitEncoder: public CBitModel { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template class CBitDecoder: public CBitModel { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template class CBitTreeEncoder { CBitEncoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template class CBitTreeDecoder { CBitDecoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template void ReverseBitTreeEncode(CBitEncoder *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template UInt32 ReverseBitTreeDecode(CBitDecoder *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/lzma/C/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/lzma/C/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" // "23170F69-40C1-278A-0000-000400xx0000" #define CODER_INTERFACE(i, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ struct i: public IUnknown CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription }; } #endif ================================================ FILE: src/lzma/C/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" // "23170F69-40C1-278A-0000-000300xx0000" #define STREAM_INTERFACE_SUB(i, b, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ struct i: public b #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/lzma/C/Common/Alloc.cpp ================================================ // Common/Alloc.cpp #include "StdAfx.h" #ifdef _WIN32 #include "MyWindows.h" #else #include #endif #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return ::malloc(size); } void MyFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif ::free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } static SIZE_T g_LargePageSize = #ifdef _WIN64 (1 << 21); #else (1 << 22); #endif typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); bool SetLargePageSize() { GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return false; SIZE_T size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return false; g_LargePageSize = size; return true; } void *BigAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif if (size >= (1 << 18)) { void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/lzma/C/Common/Alloc.h ================================================ // Common/Alloc.h #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size) throw(); void MyFree(void *address) throw(); #ifdef _WIN32 bool SetLargePageSize(); void *MidAlloc(size_t size) throw(); void MidFree(void *address) throw(); void *BigAlloc(size_t size) throw(); void BigFree(void *address) throw(); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/lzma/C/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" #include "CRC.h" static const UInt32 kCRCPoly = 0xEDB88320; UInt32 CCRC::Table[256]; void CCRC::InitTable() { for (UInt32 i = 0; i < 256; i++) { UInt32 r = i; for (int j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCRCPoly; else r >>= 1; CCRC::Table[i] = r; } } class CCRCTableInit { public: CCRCTableInit() { CCRC::InitTable(); } } g_CRCTableInit; void CCRC::UpdateByte(Byte b) { _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); } void CCRC::UpdateUInt16(UInt16 v) { UpdateByte(Byte(v)); UpdateByte(Byte(v >> 8)); } void CCRC::UpdateUInt32(UInt32 v) { for (int i = 0; i < 4; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::UpdateUInt64(UInt64 v) { for (int i = 0; i < 8; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::Update(const void *data, size_t size) { UInt32 v = _value; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); _value = v; } ================================================ FILE: src/lzma/C/Common/CRC.h ================================================ // Common/CRC.h #ifndef __COMMON_CRC_H #define __COMMON_CRC_H #include #include "Types.h" class CCRC { UInt32 _value; public: static UInt32 Table[256]; static void InitTable(); CCRC(): _value(0xFFFFFFFF){}; void Init() { _value = 0xFFFFFFFF; } void UpdateByte(Byte v); void UpdateUInt16(UInt16 v); void UpdateUInt32(UInt32 v); void UpdateUInt64(UInt64 v); void Update(const void *data, size_t size); UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } static UInt32 CalculateDigest(const void *data, size_t size) { CCRC crc; crc.Update(data, size); return crc.GetDigest(); } static bool VerifyDigest(UInt32 digest, const void *data, size_t size) { return (CalculateDigest(data, size) == digest); } }; #endif ================================================ FILE: src/lzma/C/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include #include namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/lzma/C/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include #include #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/lzma/C/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/lzma/C/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); while (true) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) return; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices) { indices.Clear(); int numUsedChars = 0; for(int i = 0; i < numForms; i++) { const CCommandSubCharsSet &set = forms[i]; int currentIndex = -1; int len = MyStringLen(set.Chars); for(int j = 0; j < len; j++) { wchar_t c = set.Chars[j]; int newIndex = commandString.Find(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.Find(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if(currentIndex == -1 && !set.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length()); } } ================================================ FILE: src/lzma/C/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "Common/String.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); struct CCommandSubCharsSet { wchar_t *Chars; bool EmptyAllowed; }; // Returns: indices of finded chars; -1 if there is no match bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices); } #endif ================================================ FILE: src/lzma/C/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } template inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/lzma/C/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } template class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/lzma/C/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline bool operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return false; return true; } inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/lzma/C/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include #else #define INITGUID #include "MyGuidDef.h" #endif #endif ================================================ FILE: src/lzma/C/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include #else #define MIDL_INTERFACE(x) struct #endif #else #include #endif #include #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/lzma/C/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include #else #include // for wchar_t #include #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; }; typedef IUnknown *LPUNKNOWN; #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/lzma/C/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/lzma/C/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif ================================================ FILE: src/lzma/C/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/lzma/C/Common/String.cpp ================================================ // Common/String.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include #endif #include "Common/String.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { while (true) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/lzma/C/Common/String.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include // #include #include "Vector.h" #ifdef _WIN32 #include "MyWindows.h" #endif static const char *kTrimDefaultCharSet = " \n\t"; template inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)CharUpperW((LPWSTR)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)CharLowerW((LPWSTR)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; while (true) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; while (true) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase charSet; for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / sizeof(kTrimDefaultCharSet[0])); i++) charSet += (T)kTrimDefaultCharSet[i]; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template CStringBase operator+(const CStringBase& s1, const CStringBase& s2) { CStringBase result(s1); result += s2; return result; } template CStringBase operator+(const CStringBase& s, T c) { CStringBase result(s); result += c; return result; } template CStringBase operator+(T c, const CStringBase& s) { CStringBase result(c); result += s; return result; } template CStringBase operator+(const CStringBase& s, const T * chars) { CStringBase result(s); result += chars; return result; } template CStringBase operator+(const T * chars, const CStringBase& s) { CStringBase result(chars); result += s; return result; } template bool operator==(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) == 0); } template bool operator<(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) < 0); } template bool operator==(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) == 0); } template bool operator==(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) == 0); } template bool operator!=(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) != 0); } template bool operator!=(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) != 0); } template bool operator!=(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase AString; typedef CStringBase UString; typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector CSysStringVector; #endif ================================================ FILE: src/lzma/C/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, NULL, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/lzma/C/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "Common/String.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT codePage) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/lzma/C/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; while(true) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/lzma/C/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/lzma/C/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; typedef int Int32; typedef unsigned int UInt32; #ifdef _MSC_VER typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif ================================================ FILE: src/lzma/C/Common/Vector.cpp ================================================ // Common/Vector.cpp #include "StdAfx.h" #include #include "Vector.h" CBaseRecordVector::~CBaseRecordVector() { delete []((unsigned char *)_items); } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if(_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if(newCapacity <= _capacity) return; /* #ifndef _DEBUG static const unsigned int kMaxVectorSize = 0xF0000000; if(newCapacity < _size || ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize) throw 1052354; #endif */ unsigned char *p = new unsigned char[newCapacity * _itemSize]; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/lzma/C/Common/Vector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } void Sort(int left, int right) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (operator[](i) < operator[](left)) Swap(++last, i); Swap(left, last); Sort(left, last); Sort(last + 1, right); } void Sort() { Sort(0, Size()); } void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (compare(&operator[](i), &operator[](left), param) < 0) Swap(++last, i); Swap(left, last); Sort(left, last, compare, param); Sort(last + 1, right, compare, param); } void Sort(int (*compare)(const T*, const T*, void *), void *param) { Sort(0, Size(), compare, param); } }; typedef CRecordVector CIntVector; typedef CRecordVector CUIntVector; typedef CRecordVector CBoolVector; typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void *param) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/lzma/C/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/lzma/C/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { Close(); _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (g_IsNT) { Close(); _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); } #endif bool CFileBase::Close() { if(!_fileIsOpen) return true; bool result = BOOLToBool(::CloseHandle(_handle)); _fileIsOpen = !result; return result; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCTSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCWSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). static UInt32 kChunkSizeMax = (1 << 24); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/lzma/C/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: bool _fileIsOpen; HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _fileIsOpen(false){}; virtual ~CFileBase(); virtual bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/lzma/C/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/lzma/CPL.html ================================================ Common Public License - v 1.0

Common Public License - v 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

    a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
    b) in the case of each subsequent Contributor:
    i) changes to the Program, and
    ii) additions to the Program;
    where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

    a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
    b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
    c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
    d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

    a) it complies with the terms and conditions of this Agreement; and
    b) its license agreement:
    i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
    ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
    iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
    iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

    a) it must be made available under this Agreement; and
    b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

================================================ FILE: src/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void Init(System.IO.Stream inStream); void ReleaseStream(); void MovePos(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetLongestMatch(UInt32[] distances); void DummyLongestMatch(); } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; UInt32 _historySize; UInt32 _matchMaxLen; // UInt32 []_dummy; UInt32[] _son; UInt32[] _hash; UInt32[] _hash2; UInt32[] _hash3; UInt32 _cutValue = 0xFF; bool HASH_ARRAY = true; bool HASH_BIG = false; const UInt32 kHash3Size = 1 << 18; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kBT4Hash2Size = 1 << 10; const UInt32 kBT4Hash4Size = 1 << 20; const UInt32 kBT4bHash4Size = 1 << 23; const UInt32 kBT2NumHashDirectBytes = 2; const UInt32 kBT4NumHashDirectBytes = 0; UInt32 kHash2Size = kBT4Hash2Size; UInt32 kNumHashDirectBytes = kBT4NumHashDirectBytes; UInt32 kNumHashBytes = 4; UInt32 kHashSize = kBT4Hash4Size; public void SetType(int numHashBytes, bool big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size; } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 Hash(UInt32 offset, out UInt32 hash2Value, out UInt32 hash3Value) { UInt32 temp = CRC.Table[_bufferBase[offset]] ^ _bufferBase[offset + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[offset + 2]) << 8); hash3Value = temp & (kHash3Size - 1); return (temp ^ (CRC.Table[_bufferBase[offset + 3]] << 5)) & (kHashSize - 1); } UInt32 Hash(UInt32 offset) { return _bufferBase[offset] ^ ((UInt32)(_bufferBase[offset + 1]) << 8); } public new void Init(System.IO.Stream inStream) { base.Init(inStream); UInt32 i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void ReleaseStream() { base.ReleaseStream(); } public new void MovePos() { _cyclicBufferPos++; if (_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { // _dummy = new UInt32[matchMaxLen + 1]; UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) throw new Exception(); _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new UInt32[_cyclicBufferSize * 2]; _hash = new UInt32[kHashSize]; if (HASH_ARRAY) { _hash2 = new UInt32[kHash2Size]; _hash3 = new UInt32[kHash3Size]; } } public UInt32 GetLongestMatch(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 matchHashLenMax = 0; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; UInt32 len2Distance = 0; UInt32 len3Distance = 0; bool matchLen2Exist = false; bool matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 startItem = _pos - _historySize; UInt32 subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public virtual void BeforeMoveBlock() { } public virtual void AfterMoveBlock() { } public void MoveBlock() { BeforeMoveBlock(); UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; AfterMoveBlock(); } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void Init(System.IO.Stream stream) { _stream = stream; _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void ReleaseStream() { _stream = null; } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) ; return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; } } public void Init(System.IO.Stream stream) { Init(stream, false); } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; public const int kDicLogSizeMax = 28; public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, BT4B }; static string[] kMatchFinderIDs = { "BT2", "BT4", "BT4B", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1024]; static Encoder() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return (UInt32)(g_FastPos[pos >> 9] + 18); return (UInt32)(g_FastPos[pos >> 18] + 36); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 25)) return (UInt32)(g_FastPos[pos >> 15] + 30); return (UInt32)(g_FastPos[pos >> 24] + 48); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[GetState(pos, prevByte)]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumLowBits RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumMidBits RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { UInt32 price = 0; if (symbol < Base.kNumLowLenSymbols) { price += _choice.GetPrice0(); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += _choice.GetPrice1(); if (symbol < Base.kNumMidLenSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public new UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = base.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; // posNext; public UInt32 BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; // test it RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen + 1]; bool _fastMode = false; bool _maxMode = false; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 lastPosSlotFillingPos; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark; bool _needReleaseMFStream; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; bool big = false; switch (_matchFinderType) { case EMatchFinderType.BT2: numHashBytes = 2; break; case EMatchFinderType.BT4: break; case EMatchFinderType.BT4B: big = true; break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes) { lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); } void MovePos(UInt32 num) { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes = _optimum[1].BackPrev; return 1; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for (UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 newLen; ReadMatchDistances(out newLen); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte((Int32)temp - 1) != _matchFinder.GetIndexByte((Int32)temp - (Int32)backOffset - 1)) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte((Int32)(-1 - (Int32)backOffset)) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte((Int32)(0 - (Int32)backOffset))) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte((Int32)lenTest - 1) != _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)backOffset)) break; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1)) != _matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1 - (Int32)backOffset))) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)backOffset)), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)lenTest2 - 1) != _matchFinder.GetIndexByte((Int32)lenTest2 - (Int32)backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, // data[(size_t)lenTest - 1], _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, // data[(size_t)lenTest - backOffset], data[lenTest] _matchFinder.GetIndexByte((Int32)lenTest - (Int32)backOffset - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1) ); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } UInt32 GetOptimumFast(UInt32 position, out UInt32 backRes) { UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { ReadMatchDistances(out _longestMatchLength); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } } backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = 0xFFFFFFFF; return 1; } void InitMatchFinder(LZ.IMatchFinder matchFinder) { _matchFinder = matchFinder; } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.Init(_inStream); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len; // it's not used ReadMatchDistances(out len); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 len; if (_fastMode) len = GetOptimumFast((UInt32)nowPos64, out pos); else len = GetOptimum((UInt32)nowPos64, out pos); UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 28; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + RangeCoder.BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[12]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary, mf == "bt4"); } bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; FileStream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================  Debug AnyCPU 8.0.40607 2.0 {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973} Exe LzmaAlone Lzma# 4 true full false .\bin\Debug\ DEBUG;TRACE false true .\bin\Release\ TRACE Common\CommandLineParser.cs Common\CRC.cs ICoder.cs LZ\IMatchFinder.cs LZ\LzBinTree.cs LZ\LzInWindow.cs LZ\LzOutWindow.cs LZMA\LzmaBase.cs LZMA\LzmaDecoder.cs LZMA\LzmaEncoder.cs RangeCoder\RangeCoder.cs RangeCoder\RangeCoderBit.cs RangeCoder\RangeCoderBitTree.cs Code Code True Settings.settings SettingsSingleFileGenerator Settings.cs ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// /// LZMA Benchmark /// internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } const string bt2 = "BT2"; const string bt4 = "BT4"; static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.MatchFinder }; object[] properties = { (Int32)(dictionarySize), isBT4 ? bt4: bt2 }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// /// The exception that is thrown when an error in input stream occurs during decoding. /// class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// /// The exception that is thrown when the value of an argument is outside the allowable range. /// class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// /// Callback progress. /// /// /// input size. -1 if unknown. /// /// /// output size. -1 if unknown. /// void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// /// Codes streams. /// /// /// input Stream. /// /// /// output Stream. /// /// /// input Size. -1 if unknown. /// /// /// output Size. -1 if unknown. /// /// /// callback progress reference. /// /// /// if input stream is not valid /// void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// /// Provides the fields that represent properties idenitifiers for compressing. /// public enum CoderPropID { /// /// Specifies size of dictionary. /// DictionarySize = 0x400, /// /// Specifies size of memory for PPM*. /// UsedMemorySize, /// /// Specifies order for PPM methods. /// Order, /// /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// PosStateBits = 0x440, /// /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// LitContextBits, /// /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// LitPosBits, /// /// Specifies number of fast bytes for LZ*. /// NumFastBytes = 0x450, /// /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// MatchFinder, /// /// Specifies number of passes. /// NumPasses = 0x460, /// /// Specifies number of algorithm. /// Algorithm = 0x470, /// /// Specifies multithread mode. /// MultiThread = 0x480, /// /// Specifies mode with end marker. /// EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize; int _historySize; int _matchMaxLen; int[] _son; int[] _hash; int[] _hash2; int[] _hash3; int _cutValue = 0xFF; boolean HASH_ARRAY = true; boolean HASH_BIG = false; static final int kHash3Size = 1 << 18; static final int kBT2HashSize = 1 << 16; static final int kBT4Hash2Size = 1 << 10; static final int kBT4Hash4Size = 1 << 20; static final int kBT4bHash4Size = 1 << 23; static final int kBT2NumHashDirectBytes = 2; static final int kBT4NumHashDirectBytes = 0; int kHash2Size = kBT4Hash2Size; int kNumHashDirectBytes = kBT4NumHashDirectBytes; int kNumHashBytes = 4; int kHashSize = kBT4Hash4Size; private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } public void SetType(int numHashBytes, boolean big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = (HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size); } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = ((int)1 << 30) - 1; public void Init() throws IOException { super.Init(); int i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) return false; _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new int[_cyclicBufferSize * 2]; _hash = new int[kHashSize]; if (HASH_ARRAY) { _hash2 = new int[kHash2Size]; _hash3 = new int[kHash3Size]; } return true; } public int GetLongestMatch(int[] distances) { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int matchHashLenMax = 0; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; int len2Distance = 0; int len3Distance = 0; boolean matchLen2Exist = false; boolean matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int startItem = _pos - _historySize; int subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindows package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos int _keepSizeReserv; // how many BYTEs must be kept as reserv public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; public static final int kDicLogSizeMax = 28; public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; public static final int EMatchFinderTypeBT4B = 2; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1024]; static { int kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } static int GetPosSlot2(int pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 20; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public int GetPrice(int symbol, int posState) { int price = 0; if (symbol < Base.kNumLowLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); if (symbol < Base.kNumMidLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); price += _midCoder[posState].GetPrice(symbol); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(int posState) { for (int len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = super.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } public static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; // posNext; public int BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; // test it SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen + 1]; boolean _fastMode = false; boolean _maxMode = true; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int [] _posSlotPrices = new int [Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; int [] _distancesPrices = new int [Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; int [] _alignPrices = new int [Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long lastPosSlotFillingPos; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; boolean big = false; switch (_matchFinderType) { case EMatchFinderTypeBT2: numHashBytes = 2; break; case EMatchFinderTypeBT4: break; case EMatchFinderTypeBT4B: big = true; break; default: break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); return lenRes; } void MovePos(int num) throws java.io.IOException { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetPosLenPrice(int pos, int len, int posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int[] backRes, int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes[0] = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int GetOptimum(int position, int []backRes) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes[0] = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { int backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; byte matchByte; matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes[0] = _optimum[1].BackPrev; return 1; } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; int len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; for (int lenTest = 2; lenTest <= repLen; lenTest++) { int curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } int cur = 0; int lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(backRes, cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int newLen = ReadMatchDistances(); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); int numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { int backOffset = reps[0] + 1; int temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte(temp - 1) != _matchFinder.GetIndexByte(temp - backOffset - 1)) break; int lenTest2 = temp - 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // int repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; int backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte(-1 - backOffset) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte(0 - backOffset)) continue; int lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte(lenTest - 1) != _matchFinder.GetIndexByte(lenTest - 1 - backOffset)) break; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - 1 - backOffset)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - backOffset), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (int lenTest = newLen; lenTest >= 2; lenTest--) { int curBack = _matchDistances[lenTest]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { int backOffset = curBack + 1; int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - backOffset - 1), _matchFinder.GetIndexByte(lenTest - 1) ); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } int GetOptimumFast(int position, int[] backRes) throws IOException { int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; for (int i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes[0] = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; int backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { _longestMatchLength = ReadMatchDistances(); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } for (int i = 0; i < Base.kNumRepDistances; i++) { int repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } } backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes[0] = -1; return 1; } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } int[] posTemp = new int[1]; public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int posState = ((int)nowPos64) & _posStateMask; int len; if (_fastMode) len = GetOptimumFast((int)nowPos64, posTemp); else len = GetOptimum((int)nowPos64, posTemp); int pos = posTemp[0]; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = ((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } public boolean SetAlgorithm(int algorithm) { if (algorithm < 0 || algorithm > 2) return false; _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = Base.kDicLogSizeMax; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++); _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary, params.MatchFinder >= 1); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int offset = GetOffset(); while (offset >= Pos) offset >>>= 1; offset += 1; int len = 2 + GetLen(); for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, boolean isBT4, long elapsedTime, long size) { long numCommandsForOne; if (isBT4) { long t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >>> (2 * kSubBits)); } else { long t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >>> (2 * kSubBits)); } long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, boolean isBT4, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, boolean isBT4, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } String bt2 = "BT2"; String bt4 = "BT4"; static public int LzmaBenchmark(int numIterations, int dictionarySize, boolean isBT4) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.out.println("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetMatchFinder(isBT4 ? SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT4: SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT2)) throw new Exception("Incorrect MatchFinder"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/lzma/LGPL.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: src/lzma/Methods.txt ================================================ Compression method IDs (4.27) ----------------------------- Each compression method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 15 bytes. List of defined IDs ------------------- 00 - Copy 01 - Reserved 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 04 Delta (subject to change) 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - BC_PPC_B (Big Endian) 03 - Alpha 01 - BC_Alpha 04 - IA64 01 - BC_IA64 05 - ARM 01 - BC_ARM 06 - M68 05 - BC_M68_B (Big Endian) 07 - ARM Thumb 01 - BC_ARMThumb 08 - SPARC 05 - BC_SPARC 04 - PPMD 01 - Version 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- Version 4.32 2005-12-09 -------------------------------------- - Java version of LZMA SDK was included Version 4.30 2005-11-20 -------------------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - Bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included Version 4.27 (Updated) 2005-09-21 -------------------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart Version 4.27 2005-08-07 -------------------------------------- - Bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. Version 4.26 2005-08-05 -------------------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 Version 4.23 2005-06-29 -------------------------------------- - Small fixes in C++ code Version 4.22 2005-06-10 -------------------------------------- - Small fixes Version 4.21 2005-06-08 -------------------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB Version 4.17 2005-04-18 -------------------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe Version 4.16 2005-03-29 -------------------------------------- - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included Version 4.06 2004-09-05 -------------------------------------- - Bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. Version 4.05 2004-08-25 -------------------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes Version 4.04 2004-07-28 -------------------------------------- - More compatibility with some C++ compilers Version 4.03 2004-06-18 -------------------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. Version 4.02 2004-06-10 -------------------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. Version 4.01 2004-02-15 -------------------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } Version 4.00 2004-02-13 -------------------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2004: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/lzma/lzma.txt ================================================ LZMA SDK 4.32 ------------- LZMA SDK 4.32 Copyright (C) 1999-2005 Igor Pavlov LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is available under any of the following licenses: 1) GNU Lesser General Public License (GNU LGPL) 2) Common Public License (CPL) 3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 4) Proprietary license It means that you can select one of these four options and follow rules of that license. 1,2) GNU LGPL and CPL licenses are pretty similar and both these licenses are classified as - "Free software licenses" at http://www.gnu.org/ - "OSI-approved" at http://www.opensource.org/ 3) 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 files from LZMA SDK without subjecting your linked code to the terms of the CPL or GNU LGPL. Any modifications or additions to files from LZMA SDK, however, are subject to the GNU LGPL or CPL terms. SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, while you keep LZMA SDK code unmodified. SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits you to use this code under the same terms and conditions contained in the License Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov. SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version of LZMA SDK as update for previous versions. SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits you to use code of examples (LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, LzmaAlone.cs, LzmaAlone.java) as public domain code. 4) Proprietary license LZMA SDK also can be available under a proprietary license which can include: 1) Right to modify code without subjecting modified code to the terms of the CPL or GNU LGPL 2) Technical support for code To request such proprietary license or any additional consultations, send email message from that page: http://www.7-zip.org/support.html You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You should have received a copy of the Common Public License along with this library. LZMA SDK Contents ----------------- LZMA SDK includes: - C++ source code of LZMA compressing and decompressing - ANSI-C compatible source code for LZMA decompressing - C# source code for LZMA compressing and decompressing - Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system ANSI-C LZMA decompression code was ported from original C++ sources to C. Also it was simplified and optimized for code size. But it is fully compatible with LZMA from 7-Zip. UNIX/Linux version ------------------ To compile C++ version of file->file LZMA, go to directory C/7zip/Compress/LZMA_Alone and type "make" or "make clean all" to recompile all. In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, change string in makefile LIB = -lm to string LIB = -lm -static Files --------------------- C - C / CPP source code CS - C# source code Java - Java source code lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description (this file) methods.txt - Compression method IDs for .7z LGPL.txt - GNU Lesser General Public License CPL.html - Common Public License lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C - C / CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm BinTree - Binary Tree Match Finder for LZ algorithm HashChain - Hash Chain Match Finder for LZ algorithm Patricia - Patricia Match Finder for LZ algorithm RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression LZMA_C - ANSI-C compatible LZMA decompressor LzmaDecode.h - interface for LZMA decoding on ANSI-C LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version) LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version) LzmaTest.c - test application that decodes LZMA encoded file LzmaStateDecode.h - interface for LZMA decoding (State version) LzmaStateDecode.c - LZMA decoding on ANSI-C (State version) LzmaStateTest.c - test application (State version) Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving 7z_C - 7z ANSI-C Decoder CS - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. You can find ANSI-C LZMA decompressing code at folder C/7zip/Compress/LZMA_C 7-Zip doesn't use that ANSI-C LZMA code and that code was developed specially for this SDK. And files from LZMA_C do not need files from other directories of SDK for compiling. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA Decompression features --------------------------- - Variable dictionary size (up to 256 MB) - Estimated compressing speed: about 500 KB/s on 1 GHz CPU - Estimated decompressing speed: - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (8-32 KB + DictionarySize) - Small code size for decompressing: 2-8 KB (depending from speed optimizations) LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect to speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations Speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA inputFile outputFile [...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with AMD Athlon XP CPU results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you can change number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. -a{N}: set compression mode 0 = fast, 1 = normal, 2 = max default: 2 (max) d{N}: Sets Dictionary size - [0, 28], default: 23 (8MB) The maximum value for dictionary size is 256 MB = 2^28 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Compression ratio for all bt* and pat* almost the same. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Methods from bt* group require less memory than methods from pat* group. Usually bt4 works faster than any pat*, but for some types of files pat* can work faster. Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d*9.5 + 1MB Binary Tree with 2 bytes hashing. bt3 d*9.5 + 65MB Binary Tree with 2-3(full) bytes hashing. bt4 d*9.5 + 6MB Binary Tree with 2-3-4 bytes hashing. bt4b d*9.5 + 34MB Binary Tree with 2-3-4(big) bytes hashing. pat2r d*26 + 1MB Patricia Tree with 2-bits nodes, removing. pat2 d*38 + 1MB Patricia Tree with 2-bits nodes. pat2h d*38 + 77MB Patricia Tree with 2-bits nodes, 2-3 bytes hashing. pat3h d*62 + 85MB Patricia Tree with 3-bits nodes, 2-3 bytes hashing. pat4h d*110 +101MB Patricia Tree with 4-bits nodes, 2-3 bytes hashing. hc3 d*5.5 + 1MB Hash Chain with 2-3 bytes hashing. hc4 d*5.5 + 6MB Hash Chain with 2-3-4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Using Filters ------------- You can increase compression ratio for some data types, using special filters before compressing. For example, it's possible to increase compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C/C++ source code of such filters in folder "7zip/Compress/Branch" You can check compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=bc_arm -m1=lzma With filter for big-endian ARM code (using additional Swap4 filter): 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. Source code of these CALL filters is pretty simple (about 20 lines of C++), so you can convert it from C++ version yourself. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties for compressed data 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ To compile ANSI-C LZMA Decoder you can use one of the following files sets: 1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version) 2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version) 3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface) Memory requirements for LZMA decoding ------------------------------------- LZMA decoder doesn't allocate memory itself, so you must allocate memory and send it to LZMA. Stack usage of LZMA decoding function for local variables is not larger than 200 bytes. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 5 interfaces: 1) Single-call Decompressing 2) Single-call Decompressing with input stream callback 3) Multi-call Decompressing with output buffer 4) Multi-call Decompressing with input callback and output buffer 5) Multi-call State Decompressing (zlib-like interface) Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions. Decompressing steps ------------------- 1) read LZMA properties (5 bytes): unsigned char properties[LZMA_PROPERTIES_SIZE]; 2) read uncompressed size (8 bytes, little-endian) 3) Decode properties: CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); 4) Allocate memory block for internal Structures: state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); LZMA decoder uses array of CProb variables as internal structure. By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make it unsigned_int. It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case. 5) Main Decompressing You must use one of the following interfaces: 5.1 Single-call Decompressing ----------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: int res = LzmaDecode(&state, inStream, compressedSize, &inProcessed, outStream, outSize, &outProcessed); 5.2 Single-call Decompressing with input stream callback -------------------------------------------------------- When to use: File->RAM or Flash->RAM decompressing. Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) { CBuffer *bo = (CBuffer *)object; *buffer = bo->Buffer; *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize); return LZMA_RESULT_OK; } CBuffer g_InBuffer; g_InBuffer.File = inFile; g_InBuffer.InCallback.Read = LzmaReadCompressed; int res = LzmaDecode(&state, &g_InBuffer.InCallback, outStream, outSize, &outProcessed); 5.3 Multi-call decompressing with output buffer ----------------------------------------------- When to use: RAM->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_OUT_READ Memory Requirements: - Input buffer: compressed size - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaTest.c for more details. 5.4 Multi-call decompressing with input callback and output buffer ------------------------------------------------------------------ When to use: File->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, &bo.InCallback, g_OutBuffer, outAvail, &outProcessed); } while you need more bytes see LzmaTest.c for more details: 5.5 Multi-call State Decompressing (zlib-like interface) ------------------------------------------------------------------ When to use: file->file decompressing Compile files: LzmaStateDecode.h, LzmaStateDecode.c Compile defines: Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaStateTest.c for more details: 6) Free all allocated blocks Note ---- LzmaDecodeSize.c is size-optimized version of LzmaDecode.c. But compiled code of LzmaDecodeSize.c can be larger than compiled code of LzmaDecode.c. So it's better to use LzmaDecode.c in most cases. EXIT codes ----------- LZMA decoder can return one of the following codes: #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 If you use callback function for input data and you return some error code, LZMA Decoder also returns that code. LZMA Defines ------------ _LZMA_IN_CB - Use callback for input data _LZMA_OUT_READ - Use read function for output data _LZMA_LOC_OPT - Enable local speed optimizations inside code. _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version). _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version) and LzmaStateDecode.c _LZMA_PROB32 - It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t. You can use it to enable 64-bit sizes supporting C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. By default, LZMA Encoder contains all Match Finders. But for compressing it's enough to have just one of them. So for reducing size of compressing code you can define: #define COMPRESS_MF_BT #define COMPRESS_MF_BT4 and it will use only bt4 match finder. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/motorola-bin.c ================================================ /* * motorola-bin.c * * Copyright (C) 2005-2006 Mike Baker, * Imre Kaloz * OpenWrt.org * * $Id: motorola-bin.c 3155 2006-02-05 23:59:37Z kaloz $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* * February 1, 2006 * * Add support for for creating WA840G and WE800G images */ #include #include #include #include #include #include #include unsigned long *crc32; void init_crc32() { unsigned long crc; unsigned long poly = ntohl(0x2083b8ed); int n, bit; if ((crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long))) == (void *)-1) { perror("malloc"); exit(1); } for (n = 0; n < 256; n++) { crc = (unsigned long) n; for (bit = 0; bit < 8; bit++) crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1); crc32[n] = crc; } } unsigned int crc32buf(char *buf, size_t len) { unsigned int crc = 0xFFFFFFFF; for (; len; len--, buf++) crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8); return crc; } struct motorola { unsigned int crc; // crc32 of the remainder unsigned int flags; // unknown, 105770* char *trx; // standard trx }; void usage(void) __attribute__ (( __noreturn__ )); void usage(void) { printf("Usage: motorola-bin [-device] [trxfile] [binfile]\n\n"); printf("Known devices: 1 - WR850G | 2 - WA840G | 3 - WE800G\n"); exit(1); } int main(int argc, char **argv) { unsigned int len; int fd; int c; void *trx; struct motorola *firmware; // verify parameters if (argc!=4) { usage(); } // mmap trx file if (((fd = open(argv[2], O_RDONLY)) < 0) || ((len = lseek(fd, 0, SEEK_END)) < 0) || ((trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)) || (close(fd) < 0)) { perror("open/malloc"); exit(1); } // create a firmware image in memory // and copy the trx to it firmware = malloc(len+8); memcpy(&firmware->trx,trx,len); munmap(trx,len); // setup the motorola headers init_crc32(); // setup the firmware magic while ((c = getopt(argc, argv, "123")) !=-1) { switch (c) { case '1': firmware->flags = ntohl(0x10577050); // Motorola WR850G break; case '2': firmware->flags = ntohl(0x10577040); // Motorola WA840G break; case '3': firmware->flags = ntohl(0x10577000); // Motorola WE800G break; default: usage(); } } firmware->crc = htonl(crc32buf((char *)&firmware->flags,len+4)); // write the firmware if (((fd = open(argv[3], O_CREAT|O_WRONLY,0644)) < 0) || (write(fd,firmware,len+8) != len+8) || (close(fd) < 0)) { perror("write"); exit(-1); } free(firmware); return 0; } ================================================ FILE: src/others/Makefile ================================================ all: make -C ./squashfs-3.0-e2100 make -C ./squashfs-3.2-r2 make -C ./squashfs-3.2-r2-lzma make -C ./squashfs-3.2-r2-hg612-lzma make -C ./squashfs-3.2-r2-wnr1000 make -C ./squashfs-3.2-r2-rtn12 make -C ./squashfs-3.3 make -C ./squashfs-3.3-lzma make -C ./squashfs-3.3-grml-lzma make -C ./squashfs-3.4-cisco make -C ./squashfs-3.4-nb4 make -C ./squashfs-4.0-lzma make -C ./squashfs-4.0-realtek make -C ./squashfs-2.0-nb4 make -C ./squashfs-4.2 make -C ./squashfs-4.2-official clean: make -C ./squashfs-3.0-e2100 clean make -C ./squashfs-3.2-r2 clean make -C ./squashfs-3.2-r2-lzma clean make -C ./squashfs-3.2-r2-hg612-lzma clean make -C ./squashfs-3.2-r2-wnr1000 clean make -C ./squashfs-3.2-r2-rtn12 clean make -C ./squashfs-3.3 clean make -C ./squashfs-3.3-lzma clean make -C ./squashfs-3.3-grml-lzma clean make -C ./squashfs-3.4-cisco clean make -C ./squashfs-3.4-nb4 clean make -C ./squashfs-4.0-lzma clean make -C ./squashfs-4.0-realtek clean make -C ./squashfs-2.0-nb4 clean make -C ./squashfs-4.2 clean make -C ./squashfs-4.2-official clean ================================================ FILE: src/others/squashfs-2.0-nb4/Makefile ================================================ all: make -C nb4-mksquashfs make -C nb4-unsquashfs cp nb4-mksquashfs/mksquashfs . cp nb4-unsquashfs/unsquashfs . clean: make -C nb4-mksquashfs clean make -C nb4-unsquashfs clean rm -rf mksquashfs unsquashfs ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/Makefile ================================================ LZMADIR = ./lzma/compress INCLUDEDIR = -I. -I$(LZMADIR) LZMAOBJS = \ 7zapi.o \ 7zlzma.o \ AriBitCoder.o \ IInOutStreams.o \ LenCoder.o \ LiteralCoder.o \ LZMA.o \ LZMAEncoder.o \ OutByte.o \ WindowIn.o CC = gcc STRIP = strip #CFLAGS = $(DEFS) $(WARNINGS) -O2 -D__MACOSX__ -DGNU $(INCLUDEDIR) CFLAGS = $(DEFS) $(WARNINGS) -O2 -DGNU $(INCLUDEDIR) vpath %.cpp $(LZMADIR) mksquashfs: squashfs/*.c squashfs/*.h $(LZMAOBJS) @if [ ! -e /usr/include/zlib.h ]; then \ echo *****You need to install zlib-devel package to build mksquashfs! ; \ echo *****You may find it in your Linux distribution CDs. ; \ exit ;\ fi gcc $(CFLAGS) -Isquashfs -c squashfs/*.c gcc $(CFLAGS) -c getline.c gcc $(CFLAGS) -c getdelim.c g++ -o mksquashfs mksquashfs.o read_fs.o sort.o getline.o getdelim.o $(LZMAOBJS) -lz # ln mksquashfs nb4-mksquashfs $(LZMAOBJS): %.o: %.cpp g++ -c $(CFLAGS) $^ -o $@ clean: rm -f mksquashfs nb4-mksquashfs rm -fr *.o core rm -fr $(LZMADIR)/*.o ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/getdelim.c ================================================ /* getdelim.c --- Implementation of replacement getdelim function. Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Ported from glibc by Simon Josefsson. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "getdelim.h" #if !HAVE_FLOCKFILE # undef flockfile # define flockfile(x) ((void) 0) #endif #if !HAVE_FUNLOCKFILE # undef funlockfile # define funlockfile(x) ((void) 0) #endif /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and NUL-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *N characters of space. It is realloc'ed as necessary. Returns the number of characters read (not including the null terminator), or -1 on error or EOF. */ ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) { int result = 0; ssize_t cur_len = 0; ssize_t len; if (lineptr == NULL || n == NULL || fp == NULL) { errno = EINVAL; return -1; } flockfile (fp); if (*lineptr == NULL || *n == 0) { *n = 120; *lineptr = (char *) malloc (*n); if (*lineptr == NULL) { result = -1; goto unlock_return; } } for (;;) { char *t; int i; i = getc (fp); if (i == EOF) { result = -1; break; } /* Make enough space for len+1 (for final NUL) bytes. */ if (cur_len + 1 >= *n) { size_t needed = 2 * (cur_len + 1) + 1; /* Be generous. */ char *new_lineptr; if (needed < cur_len) { result = -1; goto unlock_return; } new_lineptr = (char *) realloc (*lineptr, needed); if (new_lineptr == NULL) { result = -1; goto unlock_return; } *lineptr = new_lineptr; *n = needed; } (*lineptr)[cur_len] = i; cur_len++; if (i == delimiter) break; } (*lineptr)[cur_len] = '\0'; result = cur_len ? cur_len : result; unlock_return: funlockfile (fp); return result; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/getdelim.h ================================================ /* getdelim.h --- Prototype for replacement getdelim function. Copyright (C) 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Simon Josefsson. */ /* Get size_t, FILE, ssize_t. And getdelim, if available. */ # include # include # include #if !HAVE_DECL_GETDELIM ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream); #endif /* !HAVE_GETDELIM */ ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/getline.c ================================================ /* getline.c --- Implementation of replacement getline function. Copyright (C) 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Simon Josefsson. */ #ifdef HAVE_CONFIG_H # include #endif #include "getdelim.h" #include "getline.h" ssize_t getline (char **lineptr, size_t *n, FILE *stream) { return getdelim (lineptr, n, '\n', stream); } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/getline.h ================================================ /* getline.h --- Prototype for replacement getline function. Copyright (C) 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Simon Josefsson. */ /* Get size_t, FILE, ssize_t. And getline, if available. */ # include # include # include #if !HAVE_DECL_GETLINE ssize_t getline (char **lineptr, size_t *n, FILE *stream); #endif /* !HAVE_GETLINE */ ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/7z.h ================================================ #ifndef __7Z_H #define __7Z_H bool compress_deflate_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned& out_size, unsigned num_passes, unsigned num_fast_bytes) throw (); bool decompress_deflate_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw (); bool compress_rfc1950_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned& out_size, unsigned num_passes, unsigned num_fast_bytes) throw (); bool compress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned& out_size, unsigned algo, unsigned dictionary_size, unsigned num_fast_bytes) throw (); bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw (); #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/7zapi.cpp ================================================ #include "7z.h" /********************** APIs Definitions ************************************/ extern "C" { int compress_lzma_7zapi(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned *out_size, unsigned algo, unsigned dictionary_size, unsigned num_fast_bytes); } int compress_lzma_7zapi(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned *out_size, unsigned algo, unsigned dictionary_size, unsigned num_fast_bytes) { bool ret; //unsigned outsize = *out_size; ret = compress_lzma_7z(in_data, in_size, out_data, *out_size, algo, dictionary_size, num_fast_bytes); return (int)ret; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/7zapi.h ================================================ #ifndef __7ZAPI_H__ #define __7ZAPI_H__ #if defined(__cplusplus) extern "C" { #endif extern int compress_lzma_7zapi(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned *out_size, unsigned algo, unsigned dictionary_size, unsigned num_fast_bytes); #if defined(__cplusplus) } #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/7zlzma.cpp ================================================ #include "7z.h" #include "LZMAEncoder.h" #include "LZMADecoder.h" bool compress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned& out_size, unsigned algo, unsigned dictionary_size, unsigned num_fast_bytes) throw () { try { NCompress::NLZMA::CEncoder cc; // reduce the dictionary size if the file is small while (dictionary_size > 8 && dictionary_size / 2 >= out_size) dictionary_size /= 2; if (cc.SetDictionarySize(dictionary_size) != S_OK) return false; if (cc.SetEncoderNumFastBytes(num_fast_bytes) != S_OK) return false; if (cc.SetEncoderAlgorithm(algo) != S_OK) return false; ISequentialInStream in(reinterpret_cast(in_data), in_size); ISequentialOutStream out(reinterpret_cast(out_data), out_size); UINT64 in_size_l = in_size; if (cc.WriteCoderProperties(&out) != S_OK) return false; if (cc.Code(&in, &out, &in_size_l) != S_OK) return false; out_size = out.size_get(); if (out.overflow_get()) return false; return true; } catch (...) { return false; } } #if 0 bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw () { try { NCompress::NLZMA::CDecoder cc; ISequentialInStream in(reinterpret_cast(in_data), in_size); ISequentialOutStream out(reinterpret_cast(out_data), out_size); UINT64 in_size_l = in_size; UINT64 out_size_l = out_size; if (cc.ReadCoderProperties(&in) != S_OK) return false; if (cc.Code(&in, &out, &in_size_l, &out_size_l) != S_OK) return false; if (out.size_get() != out_size || out.overflow_get()) return false; return true; } catch (...) { return false; } } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/AriBitCoder.cpp ================================================ #include "AriBitCoder.h" #include "AriPrice.h" #include namespace NCompression { namespace NArithmetic { static const double kDummyMultMid = (1.0 / kBitPrice) / 2; CPriceTables::CPriceTables() { double aLn2 = log(2); double aLnAll = log(kBitModelTotal >> kNumMoveReducingBits); for(UINT32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) m_StatePrices[i] = UINT32((fabs(aLnAll - log(i)) / aLn2 + kDummyMultMid) * kBitPrice); } CPriceTables g_PriceTables; }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/AriBitCoder.h ================================================ #ifndef __COMPRESSION_BITCODER_H #define __COMPRESSION_BITCODER_H #include "RangeCoder.h" namespace NCompression { namespace NArithmetic { const int kNumBitModelTotalBits = 11; const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; class CPriceTables { public: UINT32 m_StatePrices[kBitModelTotal >> kNumMoveReducingBits]; CPriceTables(); }; extern CPriceTables g_PriceTables; ///////////////////////////// // CBitModel template class CBitModel { public: UINT32 m_Probability; void UpdateModel(UINT32 aSymbol) { /* m_Probability -= (m_Probability + ((aSymbol - 1) & ((1 << aNumMoveBits) - 1))) >> aNumMoveBits; m_Probability += (1 - aSymbol) << (kNumBitModelTotalBits - aNumMoveBits); */ if (aSymbol == 0) m_Probability += (kBitModelTotal - m_Probability) >> aNumMoveBits; else m_Probability -= (m_Probability) >> aNumMoveBits; } public: void Init() { m_Probability = kBitModelTotal / 2; } }; template class CBitEncoder: public CBitModel { public: void Encode(CRangeEncoder *aRangeEncoder, UINT32 aSymbol) { aRangeEncoder->EncodeBit(this->m_Probability, kNumBitModelTotalBits, aSymbol); this->UpdateModel(aSymbol); } UINT32 GetPrice(UINT32 aSymbol) const { return g_PriceTables.m_StatePrices[ (((this->m_Probability - aSymbol) ^ ((-(int)aSymbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template class CBitDecoder: public CBitModel { public: UINT32 Decode(CRangeDecoder *aRangeDecoder) { UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * this->m_Probability; if (aRangeDecoder->m_Code < aNewBound) { aRangeDecoder->m_Range = aNewBound; this->m_Probability += (kBitModelTotal - this->m_Probability) >> aNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); aRangeDecoder->m_Range <<= 8; } return 0; } else { aRangeDecoder->m_Range -= aNewBound; aRangeDecoder->m_Code -= aNewBound; this->m_Probability -= (this->m_Probability) >> aNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); aRangeDecoder->m_Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/AriConst.h ================================================ #ifndef __ARICONST_H #define __ARICONST_H #include "AriBitCoder.h" typedef NCompression::NArithmetic::CRangeEncoder CMyRangeEncoder; typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder; template class CMyBitEncoder: public NCompression::NArithmetic::CBitEncoder {}; template class CMyBitDecoder: public NCompression::NArithmetic::CBitDecoder {}; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/AriPrice.h ================================================ #ifndef __COMPRESSION_ARIPRICE_H #define __COMPRESSION_ARIPRICE_H namespace NCompression { namespace NArithmetic { const UINT32 kNumBitPriceShiftBits = 6; const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree.h ================================================ #include "Portable.h" #include "WindowIn.h" namespace BT_NAMESPACE { typedef UINT32 CIndex; const UINT32 kMaxValForNormalize = (UINT32(1) << 31) - 1; struct CPair { CIndex Left; CIndex Right; }; class CInTree: public NStream::NWindow::CIn { UINT32 m_HistorySize; UINT32 m_MatchMaxLen; CIndex *m_Hash; #ifdef HASH_ARRAY_2 CIndex *m_Hash2; #ifdef HASH_ARRAY_3 CIndex *m_Hash3; #endif #endif CPair *m_Son; CPair *m_Base; UINT32 m_CutValue; void NormalizeLinks(CIndex *anArray, UINT32 aNumItems, UINT32 aSubValue); void Normalize(); void FreeMemory(); protected: virtual void AfterMoveBlock(); public: CInTree(); ~CInTree(); HRESULT Create(UINT32 aSizeHistory, UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen, UINT32 aKeepAddBufferAfter, UINT32 _dwSizeReserv = (1<<17)); HRESULT Init(ISequentialInStream *aStream); void SetCutValue(UINT32 aCutValue) { m_CutValue = aCutValue; } UINT32 GetLongestMatch(UINT32 *aDistances); void DummyLongestMatch(); HRESULT MovePos() { RETURN_IF_NOT_S_OK(CIn::MovePos()); if (m_Pos == kMaxValForNormalize) Normalize(); return S_OK; } void ReduceOffsets(UINT32 aSubValue) { CIn::ReduceOffsets(aSubValue); m_Son += aSubValue; } }; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree2.h ================================================ #ifndef __BINTREE2__H #define __BINTREE2__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT2 #undef BT_NAMESPACE #define BT_NAMESPACE NBT2 #include "BinTreeMF.h" #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree2Main.h ================================================ #ifndef __BINTREE2MAIN__H #define __BINTREE2MAIN__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT2 #undef BT_NAMESPACE #define BT_NAMESPACE NBT2 #include "BinTreeMFMain.h" #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree3.h ================================================ #ifndef __BINTREE3__H #define __BINTREE3__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT3 #undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTreeMF.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree3Main.h ================================================ #ifndef __BINTREE3MAIN__H #define __BINTREE3MAIN__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT3 #undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTreeMFMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree3Z.h ================================================ #ifndef __BINTREE3Z__H #define __BINTREE3Z__H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTree.h" #undef HASH_ZIP #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree3ZMain.h ================================================ #ifndef __BINTREE3ZMAIN__H #define __BINTREE3ZMAIN__H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTreeMain.h" #undef HASH_ZIP #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree4.h ================================================ #ifndef __BINTREE4__H #define __BINTREE4__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT4 #undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTreeMF.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree4Main.h ================================================ #ifndef __BINTREEMAIN4__H #define __BINTREEMAIN4__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT4 #undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTreeMFMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree4b.h ================================================ #ifndef __BINTREE4B__H #define __BINTREE4B__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT4b #undef BT_NAMESPACE #define BT_NAMESPACE NBT4b #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "BinTreeMF.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTree4bMain.h ================================================ #ifndef __BINTREE4BMAIN__H #define __BINTREE4BMAIN__H #undef BT_CLSID #define BT_CLSID CLSID_CMatchFinderBT4b #undef BT_NAMESPACE #define BT_NAMESPACE NBT4b #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "BinTreeMFMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTreeMF.h ================================================ // #ifndef __BINTREEMF_H // #define __BINTREEMF_H #include "BinTree.h" namespace BT_NAMESPACE { class CMatchFinderBinTree : public CInTree { public: HRESULT Create(UINT32 aSizeHistory, UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen, UINT32 aKeepAddBufferAfter); }; } // #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTreeMFMain.h ================================================ #include "BinTreeMain.h" namespace BT_NAMESPACE { HRESULT CMatchFinderBinTree::Create(UINT32 aSizeHistory, UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen, UINT32 aKeepAddBufferAfter) { const UINT32 kAlignMask = (1 << 16) - 1; UINT32 aWindowReservSize = aSizeHistory / 2; aWindowReservSize += kAlignMask; aWindowReservSize &= ~(kAlignMask); const int kMinDictSize = (1 << 19); if (aWindowReservSize < kMinDictSize) aWindowReservSize = kMinDictSize; aWindowReservSize += 256; try { return CInTree::Create(aSizeHistory, aKeepAddBufferBefore, aMatchMaxLen, aKeepAddBufferAfter, aWindowReservSize); } catch(...) { return E_OUTOFMEMORY; } } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BinTreeMain.h ================================================ #include "CRC.h" namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UINT32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UINT32 kNumHashDirectBytes = 0; static const UINT32 kNumHashBytes = 4; static const UINT32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UINT32 kHashSize = 1 << 23; #else static const UINT32 kHashSize = 1 << 20; #endif #else static const UINT32 kNumHashDirectBytes = 3; static const UINT32 kNumHashBytes = 3; static const UINT32 kHashSize = 1 << (8 * kNumHashBytes); #endif #else #ifdef HASH_ZIP static const UINT32 kNumHashDirectBytes = 0; static const UINT32 kNumHashBytes = 3; static const UINT32 kHashSize = 1 << 16; #else static const UINT32 kNumHashDirectBytes = 2; static const UINT32 kNumHashBytes = 2; static const UINT32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif CInTree::CInTree(): #ifdef HASH_ARRAY_2 m_Hash2(0), #ifdef HASH_ARRAY_3 m_Hash3(0), #endif #endif m_Hash(0), m_Base(0), m_CutValue(0xFF) { } void CInTree::FreeMemory() { if (m_Base != 0) delete [] m_Base; if (m_Hash != 0) delete [] m_Hash; m_Base = 0; m_Hash = 0; CIn::Free(); } CInTree::~CInTree() { FreeMemory(); } HRESULT CInTree::Create(UINT32 aSizeHistory, UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen, UINT32 aKeepAddBufferAfter, UINT32 aSizeReserv) { FreeMemory(); CIn::Create(aSizeHistory + aKeepAddBufferBefore, aMatchMaxLen + aKeepAddBufferAfter, aSizeReserv); if (m_BlockSize + 256 > kMaxValForNormalize) return E_INVALIDARG; m_HistorySize = aSizeHistory; m_MatchMaxLen = aMatchMaxLen; UINT32 aSize = kHashSize; #ifdef HASH_ARRAY_2 aSize += kHash2Size; #ifdef HASH_ARRAY_3 aSize += kHash3Size; #endif #endif m_Base = new CPair[m_BlockSize + 1]; if (m_Base == 0) return E_OUTOFMEMORY; m_Hash = new CIndex[aSize + 1]; if (m_Hash == 0) return E_OUTOFMEMORY; #ifdef HASH_ARRAY_2 m_Hash2 = &m_Hash[kHashSize]; #ifdef HASH_ARRAY_3 m_Hash3 = &m_Hash2[kHash2Size]; #endif #endif return S_OK; } static const UINT32 kEmptyHashValue = 0; HRESULT CInTree::Init(ISequentialInStream *aStream) { RETURN_IF_NOT_S_OK(CIn::Init(aStream)); unsigned i; for(i = 0; i < kHashSize; i++) m_Hash[i] = kEmptyHashValue; #ifdef HASH_ARRAY_2 for(i = 0; i < kHash2Size; i++) m_Hash2[i] = kEmptyHashValue; #ifdef HASH_ARRAY_3 for(i = 0; i < kHash3Size; i++) m_Hash3[i] = kEmptyHashValue; #endif #endif m_Son = m_Base; ReduceOffsets(0 - 1); return S_OK; } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UINT32 Hash(const BYTE *aPointer, UINT32 &aHash2Value, UINT32 &aHash3Value) { UINT32 aTemp = CCRC::m_Table[aPointer[0]] ^ aPointer[1]; aHash2Value = aTemp & (kHash2Size - 1); aHash3Value = (aTemp ^ (UINT32(aPointer[2]) << 8)) & (kHash3Size - 1); return (aTemp ^ (UINT32(aPointer[2]) << 8) ^ (CCRC::m_Table[aPointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UINT32 Hash(const BYTE *aPointer, UINT32 &aHash2Value) { aHash2Value = (CCRC::m_Table[aPointer[0]] ^ aPointer[1]) & (kHash2Size - 1); return (*((const UINT32 *)aPointer)) & 0xFFFFFF; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UINT32 Hash(const BYTE *aPointer) { return ((UINT32(aPointer[0]) << 8) ^ CCRC::m_Table[aPointer[1]] ^ aPointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UINT32 Hash(const BYTE *aPointer) { return aPointer[0] ^ (UINT32(aPointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 UINT32 CInTree::GetLongestMatch(UINT32 *aDistances) { UINT32 aCurrentLimit; if (m_Pos + m_MatchMaxLen <= m_StreamPos) aCurrentLimit = m_MatchMaxLen; else { aCurrentLimit = m_StreamPos - m_Pos; if(aCurrentLimit < kNumHashBytes) return 0; } UINT32 aMatchMinPos = (m_Pos > m_HistorySize) ? (m_Pos - m_HistorySize) : 1; BYTE *aCur = m_Buffer + m_Pos; UINT32 aMatchHashLenMax = 0; #ifdef HASH_ARRAY_2 UINT32 aHash2Value; #ifdef HASH_ARRAY_3 UINT32 aHash3Value; UINT32 aHashValue = Hash(aCur, aHash2Value, aHash3Value); #else UINT32 aHashValue = Hash(aCur, aHash2Value); #endif #else UINT32 aHashValue = Hash(aCur); #endif UINT32 aCurMatch = m_Hash[aHashValue]; #ifdef HASH_ARRAY_2 UINT32 aCurMatch2 = m_Hash2[aHash2Value]; #ifdef HASH_ARRAY_3 UINT32 aCurMatch3 = m_Hash3[aHash3Value]; #endif m_Hash2[aHash2Value] = m_Pos; bool aMatchLen2Exist = false; UINT32 aLen2Distance = 0; if(aCurMatch2 >= aMatchMinPos) { if (m_Buffer[aCurMatch2] == aCur[0]) { aLen2Distance = m_Pos - aCurMatch2 - 1; aMatchHashLenMax = 2; aMatchLen2Exist = true; } } #ifdef HASH_ARRAY_3 m_Hash3[aHash3Value] = m_Pos; UINT32 aMatchLen3Exist = false; UINT32 aLen3Distance = 0; if(aCurMatch3 >= aMatchMinPos) { if (m_Buffer[aCurMatch3] == aCur[0]) { aLen3Distance = m_Pos - aCurMatch3 - 1; aMatchHashLenMax = 3; aMatchLen3Exist = true; if (aMatchLen2Exist) { if (aLen3Distance < aLen2Distance) aLen2Distance = aLen3Distance; } else { aLen2Distance = aLen3Distance; aMatchLen2Exist = true; } } } #endif #endif m_Hash[aHashValue] = m_Pos; if(aCurMatch < aMatchMinPos) { m_Son[m_Pos].Left = kEmptyHashValue; m_Son[m_Pos].Right = kEmptyHashValue; #ifdef HASH_ARRAY_2 aDistances[2] = aLen2Distance; #ifdef HASH_ARRAY_3 aDistances[3] = aLen3Distance; #endif #endif return aMatchHashLenMax; } CIndex *aPtrLeft = &m_Son[m_Pos].Right; CIndex *aPtrRight = &m_Son[m_Pos].Left; UINT32 aMax, aMinSameLeft, aMinSameRight, aMinSame; aMax = aMinSameLeft = aMinSameRight = aMinSame = kNumHashDirectBytes; #ifdef HASH_ARRAY_2 #ifndef HASH_ARRAY_3 if (aMatchLen2Exist) aDistances[2] = aLen2Distance; else if (kNumHashDirectBytes >= 2) aDistances[2] = m_Pos - aCurMatch - 1; #endif #endif aDistances[aMax] = m_Pos - aCurMatch - 1; for(UINT32 aCount = m_CutValue; aCount > 0; aCount--) { BYTE *pby1 = m_Buffer + aCurMatch; // CIndex aLeft = m_Son[aCurMatch].Left; // it's prefetch UINT32 aCurrentLen; for(aCurrentLen = aMinSame; aCurrentLen < aCurrentLimit; aCurrentLen++/*, dwComps++*/) if (pby1[aCurrentLen] != aCur[aCurrentLen]) break; while (aCurrentLen > aMax) aDistances[++aMax] = m_Pos - aCurMatch - 1; if (aCurrentLen != aCurrentLimit) { if (pby1[aCurrentLen] < aCur[aCurrentLen]) { *aPtrRight = aCurMatch; aPtrRight = &m_Son[aCurMatch].Right; aCurMatch = m_Son[aCurMatch].Right; if(aCurrentLen > aMinSameLeft) { aMinSameLeft = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } else { *aPtrLeft = aCurMatch; aPtrLeft = &m_Son[aCurMatch].Left; // aCurMatch = aLeft; aCurMatch = m_Son[aCurMatch].Left; if(aCurrentLen > aMinSameRight) { aMinSameRight = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } } else { if(aCurrentLen < m_MatchMaxLen) { *aPtrLeft = aCurMatch; aPtrLeft = &m_Son[aCurMatch].Left; aCurMatch = m_Son[aCurMatch].Left; if(aCurrentLen > aMinSameRight) { aMinSameRight = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } else { *aPtrLeft = m_Son[aCurMatch].Right; *aPtrRight = m_Son[aCurMatch].Left; #ifdef HASH_ARRAY_2 if (aMatchLen2Exist && aLen2Distance < aDistances[2]) aDistances[2] = aLen2Distance; #ifdef HASH_ARRAY_3 if (aMatchLen3Exist && aLen3Distance < aDistances[3]) aDistances[3] = aLen3Distance; #endif #endif return aMax; } } if(aCurMatch < aMatchMinPos) break; } *aPtrLeft = kEmptyHashValue; *aPtrRight = kEmptyHashValue; #ifdef HASH_ARRAY_2 if (aMatchLen2Exist) { if (aMax < 2) { aDistances[2] = aLen2Distance; aMax = 2; } else if (aLen2Distance < aDistances[2]) aDistances[2] = aLen2Distance; } #ifdef HASH_ARRAY_3 if (aMatchLen3Exist) { if (aMax < 3) { aDistances[3] = aLen3Distance; aMax = 3; } else if (aLen3Distance < aDistances[3]) aDistances[3] = aLen3Distance; } #endif #endif return aMax; } void CInTree::DummyLongestMatch() { UINT32 aCurrentLimit; if (m_Pos + m_MatchMaxLen <= m_StreamPos) aCurrentLimit = m_MatchMaxLen; else { aCurrentLimit = m_StreamPos - m_Pos; if(aCurrentLimit < kNumHashBytes) return; } UINT32 aMatchMinPos = (m_Pos > m_HistorySize) ? (m_Pos - m_HistorySize) : 1; BYTE *aCur = m_Buffer + m_Pos; #ifdef HASH_ARRAY_2 UINT32 aHash2Value; #ifdef HASH_ARRAY_3 UINT32 aHash3Value; UINT32 aHashValue = Hash(aCur, aHash2Value, aHash3Value); m_Hash3[aHash3Value] = m_Pos; #else UINT32 aHashValue = Hash(aCur, aHash2Value); #endif m_Hash2[aHash2Value] = m_Pos; #else UINT32 aHashValue = Hash(aCur); #endif UINT32 aCurMatch = m_Hash[aHashValue]; m_Hash[aHashValue] = m_Pos; if(aCurMatch < aMatchMinPos) { m_Son[m_Pos].Left = kEmptyHashValue; m_Son[m_Pos].Right = kEmptyHashValue; return; } CIndex *aPtrLeft = &m_Son[m_Pos].Right; CIndex *aPtrRight = &m_Son[m_Pos].Left; UINT32 aMax, aMinSameLeft, aMinSameRight, aMinSame; aMax = aMinSameLeft = aMinSameRight = aMinSame = kNumHashDirectBytes; for(UINT32 aCount = m_CutValue; aCount > 0; aCount--) { BYTE *pby1 = m_Buffer + aCurMatch; // CIndex aLeft = m_Son[aCurMatch].Left; // it's prefetch UINT32 aCurrentLen; for(aCurrentLen = aMinSame; aCurrentLen < aCurrentLimit; aCurrentLen++/*, dwComps++*/) if (pby1[aCurrentLen] != aCur[aCurrentLen]) break; if (aCurrentLen != aCurrentLimit) { if (pby1[aCurrentLen] < aCur[aCurrentLen]) { *aPtrRight = aCurMatch; aPtrRight = &m_Son[aCurMatch].Right; aCurMatch = m_Son[aCurMatch].Right; if(aCurrentLen > aMinSameLeft) { aMinSameLeft = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } else { *aPtrLeft = aCurMatch; aPtrLeft = &m_Son[aCurMatch].Left; aCurMatch = m_Son[aCurMatch].Left; // aCurMatch = aLeft; if(aCurrentLen > aMinSameRight) { aMinSameRight = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } } else { if(aCurrentLen < m_MatchMaxLen) { *aPtrLeft = aCurMatch; aPtrLeft = &m_Son[aCurMatch].Left; aCurMatch = m_Son[aCurMatch].Left; if(aCurrentLen > aMinSameRight) { aMinSameRight = aCurrentLen; aMinSame = MyMin(aMinSameLeft, aMinSameRight); } } else { *aPtrLeft = m_Son[aCurMatch].Right; *aPtrRight = m_Son[aCurMatch].Left; return; } } if(aCurMatch < aMatchMinPos) break; } *aPtrLeft = kEmptyHashValue; *aPtrRight = kEmptyHashValue; } void CInTree::AfterMoveBlock() { UINT32 aNumBytesToMove = m_HistorySize * sizeof(CPair); UINT32 aSpecOffset = ((m_Son + m_Pos) - m_Base) - m_HistorySize; memmove(m_Base, m_Base + aSpecOffset, aNumBytesToMove); m_Son -= aSpecOffset; } void CInTree::NormalizeLinks(CIndex *anArray, UINT32 aNumItems, UINT32 aSubValue) { for (UINT32 i = 0; i < aNumItems; i++) { UINT32 aValue = anArray[i]; if (aValue <= aSubValue) aValue = kEmptyHashValue; else aValue -= aSubValue; anArray[i] = aValue; } } void CInTree::Normalize() { UINT32 aStartItem = m_Pos - m_HistorySize; UINT32 aSubValue = aStartItem - 1; NormalizeLinks((CIndex *)(m_Son + aStartItem), m_HistorySize * 2, aSubValue); NormalizeLinks(m_Hash, kHashSize, aSubValue); #ifdef HASH_ARRAY_2 NormalizeLinks(m_Hash2, kHash2Size, aSubValue); #ifdef HASH_ARRAY_3 NormalizeLinks(m_Hash3, kHash3Size, aSubValue); #endif #endif ReduceOffsets(aSubValue); } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/BitTreeCoder.h ================================================ #ifndef __BITTREECODER_H #define __BITTREECODER_H #include "AriBitCoder.h" #include "RCDefs.h" ////////////////////////// // CBitTreeEncoder template class CBitTreeEncoder { CMyBitEncoder m_Models[1 << m_NumBitLevels]; public: void Init() { for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) m_Models[i].Init(); } void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) { UINT32 aModelIndex = 1; for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) { aBitIndex--; UINT32 aBit = (aSymbol >> aBitIndex ) & 1; m_Models[aModelIndex].Encode(aRangeEncoder, aBit); aModelIndex = (aModelIndex << 1) | aBit; } }; UINT32 GetPrice(UINT32 aSymbol) const { UINT32 aPrice = 0; UINT32 aModelIndex = 1; for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) { aBitIndex--; UINT32 aBit = (aSymbol >> aBitIndex ) & 1; aPrice += m_Models[aModelIndex].GetPrice(aBit); aModelIndex = (aModelIndex << 1) + aBit; } return aPrice; } }; ////////////////////////// // CBitTreeDecoder template class CBitTreeDecoder { CMyBitDecoder m_Models[1 << m_NumBitLevels]; public: void Init() { for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) m_Models[i].Init(); } UINT32 Decode(CMyRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; RC_INIT_VAR for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--) { // aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder); RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex) } RC_FLUSH_VAR return aModelIndex - (1 << m_NumBitLevels); }; }; //////////////////////////////// // CReverseBitTreeEncoder template class CReverseBitTreeEncoder2 { CMyBitEncoder *m_Models; UINT32 m_NumBitLevels; public: CReverseBitTreeEncoder2(): m_Models(0) { } ~CReverseBitTreeEncoder2() { delete []m_Models; } bool Create(UINT32 aNumBitLevels) { m_NumBitLevels = aNumBitLevels; m_Models = new CMyBitEncoder[1 << aNumBitLevels]; return (m_Models != 0); } void Init() { UINT32 aNumModels = 1 << m_NumBitLevels; for(UINT32 i = 1; i < aNumModels; i++) m_Models[i].Init(); } void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) { UINT32 aModelIndex = 1; for (UINT32 i = 0; i < m_NumBitLevels; i++) { UINT32 aBit = aSymbol & 1; m_Models[aModelIndex].Encode(aRangeEncoder, aBit); aModelIndex = (aModelIndex << 1) | aBit; aSymbol >>= 1; } } UINT32 GetPrice(UINT32 aSymbol) const { UINT32 aPrice = 0; UINT32 aModelIndex = 1; for (UINT32 i = m_NumBitLevels; i > 0; i--) { UINT32 aBit = aSymbol & 1; aSymbol >>= 1; aPrice += m_Models[aModelIndex].GetPrice(aBit); aModelIndex = (aModelIndex << 1) | aBit; } return aPrice; } }; /* template class CReverseBitTreeEncoder: public CReverseBitTreeEncoder2 { public: CReverseBitTreeEncoder() { Create(aNumBitLevels); } }; */ //////////////////////////////// // CReverseBitTreeDecoder template class CReverseBitTreeDecoder2 { CMyBitDecoder *m_Models; UINT32 m_NumBitLevels; public: CReverseBitTreeDecoder2(): m_Models(0) { } ~CReverseBitTreeDecoder2() { delete []m_Models; } bool Create(UINT32 aNumBitLevels) { m_NumBitLevels = aNumBitLevels; m_Models = new CMyBitDecoder[1 << aNumBitLevels]; return (m_Models != 0); } void Init() { UINT32 aNumModels = 1 << m_NumBitLevels; for(UINT32 i = 1; i < aNumModels; i++) m_Models[i].Init(); } UINT32 Decode(CMyRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; RC_INIT_VAR for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) { // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); // aModelIndex <<= 1; // aModelIndex += aBit; // aSymbol |= (aBit << aBitIndex); RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } RC_FLUSH_VAR return aSymbol; }; }; //////////////////////////// // CReverseBitTreeDecoder2 template class CReverseBitTreeDecoder { CMyBitDecoder m_Models[1 << m_NumBitLevels]; public: void Init() { for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) m_Models[i].Init(); } UINT32 Decode(CMyRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; RC_INIT_VAR for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) { // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); // aModelIndex <<= 1; // aModelIndex += aBit; // aSymbol |= (aBit << aBitIndex); RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } RC_FLUSH_VAR return aSymbol; } }; /* ////////////////////////// // CBitTreeEncoder2 template class CBitTreeEncoder2 { NCompression::NArithmetic::CBitEncoder *m_Models; UINT32 m_NumBitLevels; public: bool Create(UINT32 aNumBitLevels) { m_NumBitLevels = aNumBitLevels; m_Models = new NCompression::NArithmetic::CBitEncoder[1 << aNumBitLevels]; return (m_Models != 0); } void Init() { UINT32 aNumModels = 1 << m_NumBitLevels; for(UINT32 i = 1; i < aNumModels; i++) m_Models[i].Init(); } void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) { UINT32 aModelIndex = 1; for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) { aBitIndex--; UINT32 aBit = (aSymbol >> aBitIndex ) & 1; m_Models[aModelIndex].Encode(aRangeEncoder, aBit); aModelIndex = (aModelIndex << 1) | aBit; } } UINT32 GetPrice(UINT32 aSymbol) const { UINT32 aPrice = 0; UINT32 aModelIndex = 1; for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) { aBitIndex--; UINT32 aBit = (aSymbol >> aBitIndex ) & 1; aPrice += m_Models[aModelIndex].GetPrice(aBit); aModelIndex = (aModelIndex << 1) + aBit; } return aPrice; } }; ////////////////////////// // CBitTreeDecoder2 template class CBitTreeDecoder2 { NCompression::NArithmetic::CBitDecoder *m_Models; UINT32 m_NumBitLevels; public: bool Create(UINT32 aNumBitLevels) { m_NumBitLevels = aNumBitLevels; m_Models = new NCompression::NArithmetic::CBitDecoder[1 << aNumBitLevels]; return (m_Models != 0); } void Init() { UINT32 aNumModels = 1 << m_NumBitLevels; for(UINT32 i = 1; i < aNumModels; i++) m_Models[i].Init(); } UINT32 Decode(CMyRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; RC_INIT_VAR for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--) { // aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder); RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex) } RC_FLUSH_VAR return aModelIndex - (1 << m_NumBitLevels); } }; */ #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/CRC.h ================================================ #ifndef __COMMON_CRC_H #define __COMMON_CRC_H #include "Portable.h" class CCRC { UINT32 m_Value; public: static UINT32 m_Table[256]; CCRC(): m_Value(0xFFFFFFFF){}; void Init() { m_Value = 0xFFFFFFFF; } void Update(const void *aData, UINT32 aSize); UINT32 GetDigest() const { return m_Value ^ 0xFFFFFFFF; } static UINT32 CalculateDigest(const void *aData, UINT32 aSize) { CCRC aCRC; aCRC.Update(aData, aSize); return aCRC.GetDigest(); } static bool VerifyDigest(UINT32 aDigest, const void *aData, UINT32 aSize) { return (CalculateDigest(aData, aSize) == aDigest); } }; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/Const.h ================================================ #ifndef __DEFLATE_CONST_H #define __DEFLATE_CONST_H namespace NDeflate { const UINT32 kDistTableSize = 30; const UINT32 kHistorySize = 0x8000; const UINT32 kNumLenCombinations = 256; const UINT32 kNumHuffmanBits = 15; const UINT32 kLenTableSize = 29; const UINT32 kStaticDistTableSize = 32; const UINT32 kStaticLenTableSize = 31; const UINT32 kReadTableNumber = 0x100; const UINT32 kMatchNumber = kReadTableNumber + 1; const UINT32 kMainTableSize = kMatchNumber + kLenTableSize; //298; const UINT32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298; const UINT32 kDistTableStart = kMainTableSize; const UINT32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize; const UINT32 kLevelTableSize = 19; const UINT32 kMaxTableSize = kHeapTablesSizesSum; // test it const UINT32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize; const UINT32 kTableDirectLevels = 16; const UINT32 kTableLevelRepNumber = kTableDirectLevels; const UINT32 kTableLevel0Number = kTableLevelRepNumber + 1; const UINT32 kTableLevel0Number2 = kTableLevel0Number + 1; const UINT32 kLevelMask = 0xF; const BYTE kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255}; const BYTE kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; const UINT32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576}; const BYTE kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; const BYTE kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; const BYTE kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; const UINT32 kMatchMinLen = 3; const UINT32 kMatchMaxLen = kNumLenCombinations + kMatchMinLen - 1; // 255 + 2; test it const int kFinalBlockFieldSize = 1; namespace NFinalBlockField { enum { kNotFinalBlock = 0, kFinalBlock = 1 }; } const int kBlockTypeFieldSize = 2; namespace NBlockType { enum { kStored = 0, kFixedHuffman = 1, kDynamicHuffman = 2, kReserved = 3 }; } const UINT32 kDeflateNumberOfLengthCodesFieldSize = 5; const UINT32 kDeflateNumberOfDistanceCodesFieldSize = 5; const UINT32 kDeflateNumberOfLevelCodesFieldSize = 4; const UINT32 kDeflateNumberOfLitLenCodesMin = 257; const UINT32 kDeflateNumberOfDistanceCodesMin = 1; const UINT32 kDeflateNumberOfLevelCodesMin = 4; const UINT32 kDeflateLevelCodeFieldSize = 3; const UINT32 kDeflateStoredBlockLengthFieldSizeSize = 16; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/IInOutStreams.cpp ================================================ #include "Portable.h" #include "IInOutStreams.h" HRESULT ISequentialInStream::Read(void *aData, UINT32 aSize, UINT32* aProcessedSize) { if (aSize > size) aSize = size; *aProcessedSize = aSize; memcpy(aData, data, aSize); size -= aSize; data += aSize; return S_OK; } HRESULT ISequentialOutStream::Write(const void *aData, UINT32 aSize, UINT32* aProcessedSize) { if (aSize > size) { overflow = true; aSize = size; } *aProcessedSize = aSize; memcpy(data, aData, aSize); size -= aSize; data += aSize; total += aSize; return S_OK; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/IInOutStreams.h ================================================ #ifndef __IINOUTSTREAMS_H #define __IINOUTSTREAMS_H #include "Portable.h" class ISequentialInStream { const char* data; unsigned size; public: ISequentialInStream(const char* Adata, unsigned Asize) : data(Adata), size(Asize) { } HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); }; class ISequentialOutStream { char* data; unsigned size; bool overflow; unsigned total; public: ISequentialOutStream(char* Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { } bool overflow_get() const { return overflow; } unsigned size_get() const { return total; } HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); }; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/InByte.cpp ================================================ #include "InByte.h" namespace NStream{ CInByte::CInByte(UINT32 aBufferSize): m_BufferSize(aBufferSize), m_BufferBase(0) { m_BufferBase = new BYTE[m_BufferSize]; } CInByte::~CInByte() { delete []m_BufferBase; } void CInByte::Init(ISequentialInStream *aStream) { m_Stream = aStream; m_ProcessedSize = 0; m_Buffer = m_BufferBase; m_BufferLimit = m_Buffer; m_StreamWasExhausted = false; } bool CInByte::ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += (m_Buffer - m_BufferBase); UINT32 aNumProcessedBytes; HRESULT aResult = m_Stream->Read(m_BufferBase, m_BufferSize, &aNumProcessedBytes); if (aResult != S_OK) throw aResult; m_Buffer = m_BufferBase; m_BufferLimit = m_Buffer + aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/InByte.h ================================================ #ifndef __STREAM_INBYTE_H #define __STREAM_INBYTE_H #include "IInOutStreams.h" namespace NStream { class CInByte { UINT64 m_ProcessedSize; BYTE *m_BufferBase; UINT32 m_BufferSize; BYTE *m_Buffer; BYTE *m_BufferLimit; ISequentialInStream* m_Stream; bool m_StreamWasExhausted; bool ReadBlock(); public: CInByte(UINT32 aBufferSize = 0x100000); ~CInByte(); void Init(ISequentialInStream *aStream); bool ReadByte(BYTE &aByte) { if(m_Buffer >= m_BufferLimit) if(!ReadBlock()) return false; aByte = *m_Buffer++; return true; } BYTE ReadByte() { if(m_Buffer >= m_BufferLimit) if(!ReadBlock()) return 0x0; return *m_Buffer++; } void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize) { for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++) if (!ReadByte(((BYTE *)aData)[aProcessedSize])) return; } bool ReadBytes(void *aData, UINT32 aSize) { UINT32 aProcessedSize; ReadBytes(aData, aSize, aProcessedSize); return (aProcessedSize == aSize); } UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); } }; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMA.cpp ================================================ #include "LZMA.h" namespace NCompress { namespace NLZMA { UINT32 kDistStart[kDistTableSizeMax]; static class CConstInit { public: CConstInit() { UINT32 aStartValue = 0; int i; for (i = 0; i < kDistTableSizeMax; i++) { kDistStart[i] = aStartValue; aStartValue += (1 << kDistDirectBits[i]); } } } g_ConstInit; }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMA.h ================================================ #include "LenCoder.h" #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UINT32 kNumRepDistances = 4; const BYTE kNumStates = 12; const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: BYTE m_Index; void Init() { m_Index = 0; } void UpdateChar() { m_Index = kLiteralNextStates[m_Index]; } void UpdateMatch() { m_Index = kMatchNextStates[m_Index]; } void UpdateRep() { m_Index = kRepNextStates[m_Index]; } void UpdateShortRep() { m_Index = kShortRepNextStates[m_Index]; } }; class CBaseCoder { protected: CState m_State; BYTE m_PreviousByte; bool m_PeviousIsMatch; UINT32 m_RepDistances[kNumRepDistances]; void Init() { m_State.Init(); m_PreviousByte = 0; m_PeviousIsMatch = false; for(int i = 0 ; i < kNumRepDistances; i++) m_RepDistances[i] = 0; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMax = 28; const int kDistTableSizeMax = kDicLogSizeMax * 2; extern UINT32 kDistStart[kDistTableSizeMax]; const BYTE kDistDirectBits[kDistTableSizeMax] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 }; const UINT32 kNumLenToPosStates = 4; inline UINT32 GetLenToPosState(UINT32 aLen) { aLen -= 2; if (aLen < kNumLenToPosStates) return aLen; return kNumLenToPosStates - 1; } const int kMatchMinLen = 2; const int kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const int kAlignTableSize = 1 << kNumAlignBits; const UINT32 kAlignMask = (kAlignTableSize - 1); const int kStartPosModelIndex = 4; const int kEndPosModelIndex = 14; const int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const int kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kMainChoiceLiteralIndex = 0; const int kMainChoiceMatchIndex = 1; const int kMatchChoiceDistanceIndex= 0; const int kMatchChoiceRepetitionIndex = 1; const int kNumMoveBitsForMainChoice = 5; const int kNumMoveBitsForPosCoders = 5; const int kNumMoveBitsForAlignCoders = 5; const int kNumMoveBitsForPosSlotCoder = 5; const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMADecoder.cpp ================================================ #include "Portable.h" #include "LZMADecoder.h" #define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } namespace NCompress { namespace NLZMA { HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize) { if (aDictionarySize > (1 << kDicLogSizeMax)) return E_INVALIDARG; UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); if (m_DictionarySize != aDictionarySize) { m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize); m_DictionarySize = aDictionarySize; } return S_OK; } HRESULT CDecoder::SetLiteralProperties( UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) { if (aLiteralPosStateBits > 8) return E_INVALIDARG; if (aLiteralContextBits > 8) return E_INVALIDARG; m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits); return S_OK; } HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits) { if (aNumPosStateBits > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; UINT32 aNumPosStates = 1 << aNumPosStateBits; m_LenDecoder.Create(aNumPosStates); m_RepMatchLenDecoder.Create(aNumPosStates); m_PosStateMask = aNumPosStates - 1; return S_OK; } CDecoder::CDecoder(): m_DictionarySize((UINT32)-1) { Create(); } HRESULT CDecoder::Create() { for(int i = 0; i < kNumPosModels; i++) { RETURN_E_OUTOFMEMORY_IF_FALSE( m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i])); } return S_OK; } HRESULT CDecoder::Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream) { m_RangeDecoder.Init(anInStream); m_OutWindowStream.Init(anOutStream); int i; for(i = 0; i < kNumStates; i++) { for (UINT32 j = 0; j <= m_PosStateMask; j++) { m_MainChoiceDecoders[i][j].Init(); m_MatchRepShortChoiceDecoders[i][j].Init(); } m_MatchChoiceDecoders[i].Init(); m_MatchRepChoiceDecoders[i].Init(); m_MatchRep1ChoiceDecoders[i].Init(); m_MatchRep2ChoiceDecoders[i].Init(); } m_LiteralDecoder.Init(); // m_RepMatchLenDecoder.Init(); for (i = 0; i < kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); for(i = 0; i < kNumPosModels; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepMatchLenDecoder.Init(); m_PosAlignDecoder.Init(); return S_OK; } HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize) { if (anOutSize == NULL) return E_INVALIDARG; Init(anInStream, anOutStream); CState aState; aState.Init(); bool aPeviousIsMatch = false; BYTE aPreviousByte = 0; UINT32 aRepDistances[kNumRepDistances]; for(int i = 0 ; i < kNumRepDistances; i++) aRepDistances[i] = 0; UINT64 aNowPos64 = 0; UINT64 aSize = *anOutSize; while(aNowPos64 < aSize) { UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); while(aNowPos64 < aNext) { UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == kMainChoiceLiteralIndex) { // aCounts[0]++; aState.UpdateChar(); if(aPeviousIsMatch) { BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, UINT32(aNowPos64), aPreviousByte, aMatchByte); aPeviousIsMatch = false; } else aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, UINT32(aNowPos64), aPreviousByte); m_OutWindowStream.PutOneByte(aPreviousByte); aNowPos64++; } else { aPeviousIsMatch = true; UINT32 aDistance, aLen; if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == kMatchChoiceRepetitionIndex) { if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0) { aState.UpdateShortRep(); aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); m_OutWindowStream.PutOneByte(aPreviousByte); aNowPos64++; // aCounts[3 + 4]++; continue; } // aCounts[3 + 0]++; aDistance = aRepDistances[0]; } else { if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { aDistance = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; // aCounts[3 + 1]++; } else { if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) { // aCounts[3 + 2]++; aDistance = aRepDistances[2]; } else { // aCounts[3 + 3]++; aDistance = aRepDistances[3]; aRepDistances[3] = aRepDistances[2]; } aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } aRepDistances[0] = aDistance; } aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen; // aCounts[aLen]++; aState.UpdateRep(); } else { aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState); aState.UpdateMatch(); UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder); // aCounts[aPosSlot]++; if (aPosSlot >= kStartPosModelIndex) { aDistance = kDistStart[aPosSlot]; if (aPosSlot < kEndPosModelIndex) aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder); else { aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits); aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder); } } else aDistance = aPosSlot; aRepDistances[3] = aRepDistances[2]; aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; aRepDistances[0] = aDistance; // UpdateStat(aLen, aPosSlot); } if (aDistance >= aNowPos64) throw E_INVALIDDATA; m_OutWindowStream.CopyBackBlock(aDistance, aLen); aNowPos64 += aLen; aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1); } } } return Flush(); } HRESULT CDecoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize) { try { return CodeReal(anInStream, anOutStream, anInSize, anOutSize); } catch (HRESULT& e) { return e; } catch (...) { return E_FAIL; } } HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream) { UINT32 aNumPosStateBits; UINT32 aLiteralPosStateBits; UINT32 aLiteralContextBits; UINT32 aDictionarySize; UINT32 aProcessesedSize; BYTE aByte; RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize)); if (aProcessesedSize != sizeof(aByte)) return E_INVALIDARG; aLiteralContextBits = aByte % 9; BYTE aRemainder = aByte / 9; aLiteralPosStateBits = aRemainder % 5; aNumPosStateBits = aRemainder / 5; RETURN_IF_NOT_S_OK(anInStream->Read(&aDictionarySize, sizeof(aDictionarySize), &aProcessesedSize)); if (aProcessesedSize != sizeof(aDictionarySize)) return E_INVALIDARG; RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize)); RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits)); RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits)); return S_OK; } }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMADecoder.h ================================================ #ifndef __LZARITHMETIC_DECODER_H #define __LZARITHMETIC_DECODER_H #include "WindowOut.h" #include "LZMA.h" #include "LenCoder.h" #include "LiteralCoder.h" namespace NCompress { namespace NLZMA { typedef CMyBitDecoder CMyBitDecoder2; class CDecoder { NStream::NWindow::COut m_OutWindowStream; CMyRangeDecoder m_RangeDecoder; CMyBitDecoder2 m_MainChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder2 m_MatchChoiceDecoders[kNumStates]; CMyBitDecoder2 m_MatchRepChoiceDecoders[kNumStates]; CMyBitDecoder2 m_MatchRep1ChoiceDecoders[kNumStates]; CMyBitDecoder2 m_MatchRep2ChoiceDecoders[kNumStates]; CMyBitDecoder2 m_MatchRepShortChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; CReverseBitTreeDecoder m_PosAlignDecoder; // CBitTreeDecoder2 m_PosDecoders[kNumPosModels]; // CBitTreeDecoder m_PosAlignDecoder; NLength::CDecoder m_LenDecoder; NLength::CDecoder m_RepMatchLenDecoder; NLiteral::CDecoder m_LiteralDecoder; UINT32 m_DictionarySize; UINT32 m_PosStateMask; HRESULT Create(); HRESULT Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream); HRESULT Flush() { return m_OutWindowStream.Flush(); } HRESULT CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); public: CDecoder(); HRESULT Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); HRESULT ReadCoderProperties(ISequentialInStream *anInStream); HRESULT SetDictionarySize(UINT32 aDictionarySize); HRESULT SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); HRESULT SetPosBitsProperties(UINT32 aNumPosStateBits); }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMAEncoder.cpp ================================================ #include "Portable.h" #include "LZMAEncoder.h" #include "BinTree2Main.h" using namespace NCompression; using namespace NArithmetic; #define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } namespace NCompress { namespace NLZMA { BYTE g_FastPos[1024]; class CFastPosInit { public: CFastPosInit() { int c = 0; const int kFastSlots = 20; c = 0; for (BYTE aSlotFast = 0; aSlotFast < kFastSlots; aSlotFast++) { UINT32 k = (1 << kDistDirectBits[aSlotFast]); for (UINT32 j = 0; j < k; j++, c++) g_FastPos[c] = aSlotFast; } } } g_FastPosInit; const int kDefaultDictionaryLogSize = 20; const int kNumFastBytesDefault = 0x20; CEncoder::CEncoder(): m_DictionarySize(1 << kDefaultDictionaryLogSize), m_DictionarySizePrev(UINT32(-1)), m_NumFastBytes(kNumFastBytesDefault), m_NumFastBytesPrev(UINT32(-1)), m_DistTableSize(kDefaultDictionaryLogSize * 2), m_PosStateBits(2), m_PosStateMask(4 - 1), m_LiteralPosStateBits(0), m_LiteralContextBits(3) { m_MaxMode = false; m_FastMode = false; m_PosAlignEncoder.Create(kNumAlignBits); for(int i = 0; i < kNumPosModels; i++) m_PosEncoders[i].Create(kDistDirectBits[kStartPosModelIndex + i]); } HRESULT CEncoder::Create() { if (m_DictionarySize == m_DictionarySizePrev && m_NumFastBytesPrev == m_NumFastBytes) return S_OK; RETURN_IF_NOT_S_OK(m_MatchFinder.Create(m_DictionarySize, kNumOpts, m_NumFastBytes, kMatchMaxLen - m_NumFastBytes)); m_DictionarySizePrev = m_DictionarySize; m_NumFastBytesPrev = m_NumFastBytes; m_LiteralEncoder.Create(m_LiteralPosStateBits, m_LiteralContextBits); m_LenEncoder.Create(1 << m_PosStateBits); m_RepMatchLenEncoder.Create(1 << m_PosStateBits); return S_OK; } HRESULT CEncoder::SetEncoderAlgorithm(UINT32 A) { UINT32 aMaximize = A; if (aMaximize > 2) return E_INVALIDARG; m_FastMode = (aMaximize == 0); m_MaxMode = (aMaximize >= 2); return S_OK; } HRESULT CEncoder::SetEncoderNumFastBytes(UINT32 A) { UINT32 aNumFastBytes = A; if(aNumFastBytes < 2 || aNumFastBytes > kMatchMaxLen) return E_INVALIDARG; m_NumFastBytes = aNumFastBytes; return S_OK; } HRESULT CEncoder::SetDictionarySize(UINT32 aDictionarySize) { if (aDictionarySize > UINT32(1 << kDicLogSizeMax)) return E_INVALIDARG; m_DictionarySize = aDictionarySize; UINT32 aDicLogSize; for(aDicLogSize = 0; aDicLogSize < kDicLogSizeMax; aDicLogSize++) if (aDictionarySize <= (UINT32(1) << aDicLogSize)) break; m_DistTableSize = aDicLogSize * 2; return S_OK; } HRESULT CEncoder::SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) { if (aLiteralPosStateBits > kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; if (aLiteralContextBits > kNumLitContextBitsMax) return E_INVALIDARG; m_LiteralPosStateBits = aLiteralPosStateBits; m_LiteralContextBits = aLiteralContextBits; return S_OK; } HRESULT CEncoder::SetPosBitsProperties(UINT32 aNumPosStateBits) { if (aNumPosStateBits > NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; m_PosStateBits = aNumPosStateBits; m_PosStateMask = (1 << m_PosStateBits) - 1; return S_OK; } HRESULT CEncoder::WriteCoderProperties(ISequentialOutStream *anOutStream) { BYTE aByte = (m_PosStateBits * 5 + m_LiteralPosStateBits) * 9 + m_LiteralContextBits; UINT32 aProcessedSize; HRESULT aResult = anOutStream->Write(&aByte, sizeof(aByte), &aProcessedSize); if (aResult != S_OK) return aResult; if (aProcessedSize != sizeof(aByte)) return E_FAIL; aResult = anOutStream->Write(&m_DictionarySize, sizeof(m_DictionarySize), &aProcessedSize); if (aResult != S_OK) return aResult; if (aProcessedSize != sizeof(m_DictionarySize)) return E_FAIL; return S_OK; } HRESULT CEncoder::Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream) { CBaseCoder::Init(); RETURN_IF_NOT_S_OK(m_MatchFinder.Init(anInStream)); m_RangeEncoder.Init(anOutStream); int i; for(i = 0; i < kNumStates; i++) { for (UINT32 j = 0; j <= m_PosStateMask; j++) { m_MainChoiceEncoders[i][j].Init(); m_MatchRepShortChoiceEncoders[i][j].Init(); } m_MatchChoiceEncoders[i].Init(); m_MatchRepChoiceEncoders[i].Init(); m_MatchRep1ChoiceEncoders[i].Init(); m_MatchRep2ChoiceEncoders[i].Init(); } m_LiteralEncoder.Init(); // m_RepMatchLenEncoder.Init(); for(i = 0; i < kNumLenToPosStates; i++) m_PosSlotEncoder[i].Init(); for(i = 0; i < kNumPosModels; i++) m_PosEncoders[i].Init(); m_LenEncoder.Init(); m_RepMatchLenEncoder.Init(); m_PosAlignEncoder.Init(); m_LongestMatchWasFound = false; m_OptimumEndIndex = 0; m_OptimumCurrentIndex = 0; m_AdditionalOffset = 0; return S_OK; } void CEncoder::MovePos(UINT32 aNum) { for (;aNum > 0; aNum--) { m_MatchFinder.DummyLongestMatch(); HRESULT aResult = m_MatchFinder.MovePos(); if (aResult != S_OK) throw aResult; m_AdditionalOffset++; } } UINT32 CEncoder::Backward(UINT32 &aBackRes, UINT32 aCur) { m_OptimumEndIndex = aCur; UINT32 aPosMem = m_Optimum[aCur].PosPrev; UINT32 aBackMem = m_Optimum[aCur].BackPrev; do { if (m_Optimum[aCur].Prev1IsChar) { m_Optimum[aPosMem].MakeAsChar(); m_Optimum[aPosMem].PosPrev = aPosMem - 1; if (m_Optimum[aCur].Prev2) { m_Optimum[aPosMem - 1].Prev1IsChar = false; m_Optimum[aPosMem - 1].PosPrev = m_Optimum[aCur].PosPrev2; m_Optimum[aPosMem - 1].BackPrev = m_Optimum[aCur].BackPrev2; } } UINT32 aPosPrev = aPosMem; UINT32 aBackCur = aBackMem; aBackMem = m_Optimum[aPosPrev].BackPrev; aPosMem = m_Optimum[aPosPrev].PosPrev; m_Optimum[aPosPrev].BackPrev = aBackCur; m_Optimum[aPosPrev].PosPrev = aCur; aCur = aPosPrev; } while(aCur > 0); aBackRes = m_Optimum[0].BackPrev; m_OptimumCurrentIndex = m_Optimum[0].PosPrev; return m_OptimumCurrentIndex; } /* inline UINT32 GetMatchLen(const BYTE *aData, UINT32 aBack, UINT32 aLimit) { aBack++; for(UINT32 i = 0; i < aLimit && aData[i] == aData[i - aBack]; i++); return i; } */ UINT32 CEncoder::GetOptimum(UINT32 &aBackRes, UINT32 aPosition) { if(m_OptimumEndIndex != m_OptimumCurrentIndex) { UINT32 aLen = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex; aBackRes = m_Optimum[m_OptimumCurrentIndex].BackPrev; m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev; return aLen; } m_OptimumCurrentIndex = 0; m_OptimumEndIndex = 0; // test it; UINT32 aLenMain; if (!m_LongestMatchWasFound) aLenMain = ReadMatchDistances(); else { aLenMain = m_LongestMatchLength; m_LongestMatchWasFound = false; } UINT32 aReps[kNumRepDistances]; UINT32 aRepLens[kNumRepDistances]; UINT32 RepMaxIndex = 0; int i; for(i = 0; i < kNumRepDistances; i++) { aReps[i] = m_RepDistances[i]; aRepLens[i] = m_MatchFinder.GetMatchLen(0 - 1, aReps[i], kMatchMaxLen); if (i == 0 || aRepLens[i] > aRepLens[RepMaxIndex]) RepMaxIndex = i; } if(aRepLens[RepMaxIndex] > m_NumFastBytes) { aBackRes = RepMaxIndex; MovePos(aRepLens[RepMaxIndex] - 1); return aRepLens[RepMaxIndex]; } if(aLenMain > m_NumFastBytes) { UINT32 aBackMain = (aLenMain < m_NumFastBytes) ? m_MatchDistances[aLenMain] : m_MatchDistances[m_NumFastBytes]; aBackRes = aBackMain + kNumRepDistances; MovePos(aLenMain - 1); return aLenMain; } BYTE aCurrentByte = m_MatchFinder.GetIndexByte(0 - 1); m_Optimum[0].State = m_State; BYTE aMatchByte; aMatchByte = m_MatchFinder.GetIndexByte(0 - m_RepDistances[0] - 1 - 1); UINT32 aPosState = (aPosition & m_PosStateMask); m_Optimum[1].Price = m_MainChoiceEncoders[m_State.m_Index][aPosState].GetPrice(kMainChoiceLiteralIndex) + m_LiteralEncoder.GetPrice(aPosition, m_PreviousByte, m_PeviousIsMatch, aMatchByte, aCurrentByte); m_Optimum[1].MakeAsChar(); m_Optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) m_Optimum[0].Backs[i] = aReps[i]; UINT32 aMatchPrice = m_MainChoiceEncoders[m_State.m_Index][aPosState].GetPrice(kMainChoiceMatchIndex); UINT32 aRepMatchPrice = aMatchPrice + m_MatchChoiceEncoders[m_State.m_Index].GetPrice(kMatchChoiceRepetitionIndex); if(aMatchByte == aCurrentByte) { UINT32 aShortRepPrice = aRepMatchPrice + GetRepLen1Price(m_State, aPosState); if(aShortRepPrice < m_Optimum[1].Price) { m_Optimum[1].Price = aShortRepPrice; m_Optimum[1].MakeAsShortRep(); } } if(aLenMain < 2) { aBackRes = m_Optimum[1].BackPrev; return 1; } UINT32 aNormalMatchPrice = aMatchPrice + m_MatchChoiceEncoders[m_State.m_Index].GetPrice(kMatchChoiceDistanceIndex); if (aLenMain <= aRepLens[RepMaxIndex]) aLenMain = 0; UINT32 aLen; for(aLen = 2; aLen <= aLenMain; aLen++) { m_Optimum[aLen].PosPrev = 0; m_Optimum[aLen].BackPrev = m_MatchDistances[aLen] + kNumRepDistances; m_Optimum[aLen].Price = aNormalMatchPrice + GetPosLenPrice(m_MatchDistances[aLen], aLen, aPosState); m_Optimum[aLen].Prev1IsChar = false; } if (aLenMain < aRepLens[RepMaxIndex]) aLenMain = aRepLens[RepMaxIndex]; for (; aLen <= aLenMain; aLen++) m_Optimum[aLen].Price = kIfinityPrice; for(i = 0; i < kNumRepDistances; i++) { unsigned aRepLen = aRepLens[i]; for(UINT32 aLenTest = 2; aLenTest <= aRepLen; aLenTest++) { UINT32 aCurAndLenPrice = aRepMatchPrice + GetRepPrice(i, aLenTest, m_State, aPosState); COptimal &anOptimum = m_Optimum[aLenTest]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = 0; anOptimum.BackPrev = i; anOptimum.Prev1IsChar = false; } } } UINT32 aCur = 0; UINT32 aLenEnd = aLenMain; while(true) { aCur++; if(aCur == aLenEnd) return Backward(aBackRes, aCur); aPosition++; UINT32 aPosPrev = m_Optimum[aCur].PosPrev; CState aState; if (m_Optimum[aCur].Prev1IsChar) { aPosPrev--; if (m_Optimum[aCur].Prev2) { aState = m_Optimum[m_Optimum[aCur].PosPrev2].State; if (m_Optimum[aCur].BackPrev2 < kNumRepDistances) aState.UpdateRep(); else aState.UpdateMatch(); } else aState = m_Optimum[aPosPrev].State; aState.UpdateChar(); } else aState = m_Optimum[aPosPrev].State; bool aPrevWasMatch; if (aPosPrev == aCur - 1) { if (m_Optimum[aCur].IsShortRep()) { aPrevWasMatch = true; aState.UpdateShortRep(); } else { aPrevWasMatch = false; aState.UpdateChar(); } /* if (m_Optimum[aCur].Prev1IsChar) for(int i = 0; i < kNumRepDistances; i++) aReps[i] = m_Optimum[aPosPrev].Backs[i]; */ } else { aPrevWasMatch = true; UINT32 aPos; if (m_Optimum[aCur].Prev1IsChar && m_Optimum[aCur].Prev2) { aPosPrev = m_Optimum[aCur].PosPrev2; aPos = m_Optimum[aCur].BackPrev2; aState.UpdateRep(); } else { aPos = m_Optimum[aCur].BackPrev; if (aPos < kNumRepDistances) aState.UpdateRep(); else aState.UpdateMatch(); } if (aPos < kNumRepDistances) { aReps[0] = m_Optimum[aPosPrev].Backs[aPos]; UINT32 i; for(i = 1; i <= aPos; i++) aReps[i] = m_Optimum[aPosPrev].Backs[i - 1]; for(; i < kNumRepDistances; i++) aReps[i] = m_Optimum[aPosPrev].Backs[i]; } else { aReps[0] = (aPos - kNumRepDistances); for(UINT32 i = 1; i < kNumRepDistances; i++) aReps[i] = m_Optimum[aPosPrev].Backs[i - 1]; } } m_Optimum[aCur].State = aState; for(UINT32 i = 0; i < kNumRepDistances; i++) m_Optimum[aCur].Backs[i] = aReps[i]; UINT32 aNewLen = ReadMatchDistances(); if(aNewLen > m_NumFastBytes) { m_LongestMatchLength = aNewLen; m_LongestMatchWasFound = true; return Backward(aBackRes, aCur); } UINT32 aCurPrice = m_Optimum[aCur].Price; // BYTE aCurrentByte = m_MatchFinder.GetIndexByte(0 - 1); // BYTE aMatchByte = m_MatchFinder.GetIndexByte(0 - aReps[0] - 1 - 1); const BYTE *aData = m_MatchFinder.GetPointerToCurrentPos() - 1; BYTE aCurrentByte = *aData; BYTE aMatchByte = aData[0 - aReps[0] - 1]; UINT32 aPosState = (aPosition & m_PosStateMask); UINT32 aCurAnd1Price = aCurPrice + m_MainChoiceEncoders[aState.m_Index][aPosState].GetPrice(kMainChoiceLiteralIndex) + m_LiteralEncoder.GetPrice(aPosition, aData[-1], aPrevWasMatch, aMatchByte, aCurrentByte); COptimal &aNextOptimum = m_Optimum[aCur + 1]; bool aNextIsChar = false; if (aCurAnd1Price < aNextOptimum.Price) { aNextOptimum.Price = aCurAnd1Price; aNextOptimum.PosPrev = aCur; aNextOptimum.MakeAsChar(); aNextIsChar = true; } UINT32 aMatchPrice = aCurPrice + m_MainChoiceEncoders[aState.m_Index][aPosState].GetPrice(kMainChoiceMatchIndex); UINT32 aRepMatchPrice = aMatchPrice + m_MatchChoiceEncoders[aState.m_Index].GetPrice(kMatchChoiceRepetitionIndex); if(aMatchByte == aCurrentByte && !(aNextOptimum.PosPrev < aCur && aNextOptimum.BackPrev == 0)) { UINT32 aShortRepPrice = aRepMatchPrice + GetRepLen1Price(aState, aPosState); if(aShortRepPrice <= aNextOptimum.Price) { aNextOptimum.Price = aShortRepPrice; aNextOptimum.PosPrev = aCur; aNextOptimum.MakeAsShortRep(); // aNextIsChar = false; } } /* if(aNewLen == 2 && m_MatchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UINT32 aNumAvailableBytes = m_MatchFinder.GetNumAvailableBytes() + 1; aNumAvailableBytes = MyMin(kNumOpts - 1 - aCur, aNumAvailableBytes); if (aNumAvailableBytes < 2) continue; if (aNumAvailableBytes > m_NumFastBytes) aNumAvailableBytes = m_NumFastBytes; if (aNumAvailableBytes >= 3 && !aNextIsChar) { UINT32 aBackOffset = aReps[0] + 1; UINT32 aTemp; for (aTemp = 1; aTemp < aNumAvailableBytes; aTemp++) if (aData[aTemp] != aData[aTemp - aBackOffset]) break; UINT32 aLenTest2 = aTemp - 1; if (aLenTest2 >= 2) { CState aState2 = aState; aState2.UpdateChar(); UINT32 aPosStateNext = (aPosition + 1) & m_PosStateMask; UINT32 aNextRepMatchPrice = aCurAnd1Price + m_MainChoiceEncoders[aState2.m_Index][aPosStateNext].GetPrice(kMainChoiceMatchIndex) + m_MatchChoiceEncoders[aState2.m_Index].GetPrice(kMatchChoiceRepetitionIndex); // for (; aLenTest2 >= 2; aLenTest2--) { while(aLenEnd < aCur + 1 + aLenTest2) m_Optimum[++aLenEnd].Price = kIfinityPrice; UINT32 aCurAndLenPrice = aNextRepMatchPrice + GetRepPrice( 0, aLenTest2, aState2, aPosStateNext); COptimal &anOptimum = m_Optimum[aCur + 1 + aLenTest2]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = aCur + 1; anOptimum.BackPrev = 0; anOptimum.Prev1IsChar = true; anOptimum.Prev2 = false; } } } } for(UINT32 aRepIndex = 0; aRepIndex < kNumRepDistances; aRepIndex++) { // UINT32 aRepLen = m_MatchFinder.GetMatchLen(0 - 1, aReps[aRepIndex], aNewLen); // test it; UINT32 aBackOffset = aReps[aRepIndex] + 1; UINT32 aLenTest; for (aLenTest = 0; aLenTest < aNumAvailableBytes; aLenTest++) if (aData[aLenTest] != aData[aLenTest - aBackOffset]) break; for(; aLenTest >= 2; aLenTest--) { while(aLenEnd < aCur + aLenTest) m_Optimum[++aLenEnd].Price = kIfinityPrice; UINT32 aCurAndLenPrice = aRepMatchPrice + GetRepPrice(aRepIndex, aLenTest, aState, aPosState); COptimal &anOptimum = m_Optimum[aCur + aLenTest]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = aCur; anOptimum.BackPrev = aRepIndex; anOptimum.Prev1IsChar = false; } /* if (m_MaxMode) { UINT32 aTemp; for (aTemp = aLenTest + 1; aTemp < aNumAvailableBytes; aTemp++) if (aData[aTemp] != aData[aTemp - aBackOffset]) break; UINT32 aLenTest2 = aTemp - (aLenTest + 1); if (aLenTest2 >= 2) { CState aState2 = aState; aState2.UpdateRep(); UINT32 aPosStateNext = (aPosition + aLenTest) & m_PosStateMask; UINT32 aCurAndLenCharPrice = aCurAndLenPrice + m_MainChoiceEncoders[aState2.m_Index][aPosStateNext].GetPrice(kMainChoiceLiteralIndex) + m_LiteralEncoder.GetPrice(aPosition + aLenTest, aData[aLenTest - 1], true, aData[aLenTest - aBackOffset], aData[aLenTest]); aState2.UpdateChar(); aPosStateNext = (aPosition + aLenTest + 1) & m_PosStateMask; UINT32 aNextMatchPrice = aCurAndLenCharPrice + m_MainChoiceEncoders[aState2.m_Index][aPosStateNext].GetPrice(kMainChoiceMatchIndex); UINT32 aNextRepMatchPrice = aNextMatchPrice + m_MatchChoiceEncoders[aState2.m_Index].GetPrice(kMatchChoiceRepetitionIndex); // for(; aLenTest2 >= 2; aLenTest2--) { UINT32 anOffset = aLenTest + 1 + aLenTest2; while(aLenEnd < aCur + anOffset) m_Optimum[++aLenEnd].Price = kIfinityPrice; UINT32 aCurAndLenPrice = aNextRepMatchPrice + GetRepPrice( 0, aLenTest2, aState2, aPosStateNext); COptimal &anOptimum = m_Optimum[aCur + anOffset]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = aCur + aLenTest + 1; anOptimum.BackPrev = 0; anOptimum.Prev1IsChar = true; anOptimum.Prev2 = true; anOptimum.PosPrev2 = aCur; anOptimum.BackPrev2 = aRepIndex; } } } } */ } } // for(UINT32 aLenTest = 2; aLenTest <= aNewLen; aLenTest++) if (aNewLen > aNumAvailableBytes) aNewLen = aNumAvailableBytes; if (aNewLen >= 2) { if (aNewLen == 2 && m_MatchDistances[2] >= 0x80) continue; UINT32 aNormalMatchPrice = aMatchPrice + m_MatchChoiceEncoders[aState.m_Index].GetPrice(kMatchChoiceDistanceIndex); while(aLenEnd < aCur + aNewLen) m_Optimum[++aLenEnd].Price = kIfinityPrice; for(UINT32 aLenTest = aNewLen; aLenTest >= 2; aLenTest--) { UINT32 aCurBack = m_MatchDistances[aLenTest]; UINT32 aCurAndLenPrice = aNormalMatchPrice + GetPosLenPrice(aCurBack, aLenTest, aPosState); COptimal &anOptimum = m_Optimum[aCur + aLenTest]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = aCur; anOptimum.BackPrev = aCurBack + kNumRepDistances; anOptimum.Prev1IsChar = false; } if (m_MaxMode) { UINT32 aBackOffset = aCurBack + 1; UINT32 aTemp; for (aTemp = aLenTest + 1; aTemp < aNumAvailableBytes; aTemp++) if (aData[aTemp] != aData[aTemp - aBackOffset]) break; UINT32 aLenTest2 = aTemp - (aLenTest + 1); if (aLenTest2 >= 2) { CState aState2 = aState; aState2.UpdateMatch(); UINT32 aPosStateNext = (aPosition + aLenTest) & m_PosStateMask; UINT32 aCurAndLenCharPrice = aCurAndLenPrice + m_MainChoiceEncoders[aState2.m_Index][aPosStateNext].GetPrice(kMainChoiceLiteralIndex) + m_LiteralEncoder.GetPrice(aPosition + aLenTest, aData[aLenTest - 1], true, aData[aLenTest - aBackOffset], aData[aLenTest]); aState2.UpdateChar(); aPosStateNext = (aPosition + aLenTest + 1) & m_PosStateMask; UINT32 aNextMatchPrice = aCurAndLenCharPrice + m_MainChoiceEncoders[aState2.m_Index][aPosStateNext].GetPrice(kMainChoiceMatchIndex); UINT32 aNextRepMatchPrice = aNextMatchPrice + m_MatchChoiceEncoders[aState2.m_Index].GetPrice(kMatchChoiceRepetitionIndex); // for(; aLenTest2 >= 2; aLenTest2--) { UINT32 anOffset = aLenTest + 1 + aLenTest2; while(aLenEnd < aCur + anOffset) m_Optimum[++aLenEnd].Price = kIfinityPrice; UINT32 aCurAndLenPrice = aNextRepMatchPrice + GetRepPrice( 0, aLenTest2, aState2, aPosStateNext); COptimal &anOptimum = m_Optimum[aCur + anOffset]; if (aCurAndLenPrice < anOptimum.Price) { anOptimum.Price = aCurAndLenPrice; anOptimum.PosPrev = aCur + aLenTest + 1; anOptimum.BackPrev = 0; anOptimum.Prev1IsChar = true; anOptimum.Prev2 = true; anOptimum.PosPrev2 = aCur; anOptimum.BackPrev2 = aCurBack + kNumRepDistances; } } } } } } } } static bool inline ChangePair(UINT32 aSmall, UINT32 aBig) { const int kDif = 7; return (aSmall < (UINT32(1) << (32-kDif)) && aBig >= (aSmall << kDif)); } UINT32 CEncoder::GetOptimumFast(UINT32 &aBackRes, UINT32 aPosition) { UINT32 aLenMain; if (!m_LongestMatchWasFound) aLenMain = ReadMatchDistances(); else { aLenMain = m_LongestMatchLength; m_LongestMatchWasFound = false; } UINT32 aRepLens[kNumRepDistances]; UINT32 RepMaxIndex = 0; for(int i = 0; i < kNumRepDistances; i++) { aRepLens[i] = m_MatchFinder.GetMatchLen(0 - 1, m_RepDistances[i], kMatchMaxLen); if (i == 0 || aRepLens[i] > aRepLens[RepMaxIndex]) RepMaxIndex = i; } if(aRepLens[RepMaxIndex] >= m_NumFastBytes) { aBackRes = RepMaxIndex; MovePos(aRepLens[RepMaxIndex] - 1); return aRepLens[RepMaxIndex]; } if(aLenMain >= m_NumFastBytes) { aBackRes = m_MatchDistances[m_NumFastBytes] + kNumRepDistances; MovePos(aLenMain - 1); return aLenMain; } while (aLenMain > 2) { if (!ChangePair(m_MatchDistances[aLenMain - 1], m_MatchDistances[aLenMain])) break; aLenMain--; } if (aLenMain == 2 && m_MatchDistances[2] >= 0x80) aLenMain = 1; UINT32 aBackMain = m_MatchDistances[aLenMain]; if (aRepLens[RepMaxIndex] >= 2) { if (aRepLens[RepMaxIndex] + 1 >= aLenMain || aRepLens[RepMaxIndex] + 2 >= aLenMain && (aBackMain > (1<<12))) { aBackRes = RepMaxIndex; MovePos(aRepLens[RepMaxIndex] - 1); return aRepLens[RepMaxIndex]; } } if (aLenMain >= 2) { m_LongestMatchLength = ReadMatchDistances(); if (m_LongestMatchLength >= 2 && ( (m_LongestMatchLength >= aLenMain && m_MatchDistances[aLenMain] < aBackMain) || m_LongestMatchLength == aLenMain + 1 && !ChangePair(aBackMain, m_MatchDistances[m_LongestMatchLength]) || m_LongestMatchLength > aLenMain + 1 || m_LongestMatchLength + 1 >= aLenMain && ChangePair(m_MatchDistances[aLenMain - 1], aBackMain) ) ) { m_LongestMatchWasFound = true; aBackRes = UINT32(-1); return 1; } for(int i = 0; i < kNumRepDistances; i++) { UINT32 aRepLen = m_MatchFinder.GetMatchLen(0 - 1, m_RepDistances[i], kMatchMaxLen); if (aRepLen >= 2 && aRepLen + 1 >= aLenMain) { m_LongestMatchWasFound = true; aBackRes = UINT32(-1); return 1; } } aBackRes = aBackMain + kNumRepDistances; MovePos(aLenMain - 2); return aLenMain; } aBackRes = UINT32(-1); return 1; } HRESULT CEncoder::Flush() { m_RangeEncoder.FlushData(); return m_RangeEncoder.FlushStream(); } HRESULT CEncoder::CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize) { RETURN_IF_NOT_S_OK(Create()); Init(anInStream, anOutStream); if (m_MatchFinder.GetNumAvailableBytes() == 0) return Flush(); if (!m_FastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } m_LenEncoder.SetTableSize(m_NumFastBytes); m_LenEncoder.UpdateTables(); m_RepMatchLenEncoder.SetTableSize(m_NumFastBytes); m_RepMatchLenEncoder.UpdateTables(); UINT64 aLastPosSlotFillingPos = 0; UINT64 aNowPos64 = 0; ReadMatchDistances(); UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; m_MainChoiceEncoders[m_State.m_Index][aPosState].Encode(&m_RangeEncoder, kMainChoiceLiteralIndex); m_State.UpdateChar(); BYTE aByte = m_MatchFinder.GetIndexByte(0 - m_AdditionalOffset); m_LiteralEncoder.Encode(&m_RangeEncoder, UINT32(aNowPos64), m_PreviousByte, false, 0, aByte); m_PreviousByte = aByte; m_AdditionalOffset--; aNowPos64++; if (m_MatchFinder.GetNumAvailableBytes() == 0) return Flush(); while(true) { UINT32 aPos; UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; UINT32 aLen; if (m_FastMode) aLen = GetOptimumFast(aPos, UINT32(aNowPos64)); else aLen = GetOptimum(aPos, UINT32(aNowPos64)); if(aLen == 1 && aPos == (-1)) { m_MainChoiceEncoders[m_State.m_Index][aPosState].Encode(&m_RangeEncoder, kMainChoiceLiteralIndex); m_State.UpdateChar(); BYTE aMatchByte; if(m_PeviousIsMatch) aMatchByte = m_MatchFinder.GetIndexByte(0 - m_RepDistances[0] - 1 - m_AdditionalOffset); BYTE aByte = m_MatchFinder.GetIndexByte(0 - m_AdditionalOffset); m_LiteralEncoder.Encode(&m_RangeEncoder, UINT32(aNowPos64), m_PreviousByte, m_PeviousIsMatch, aMatchByte, aByte); m_PreviousByte = aByte; m_PeviousIsMatch = false; } else { m_PeviousIsMatch = true; m_MainChoiceEncoders[m_State.m_Index][aPosState].Encode(&m_RangeEncoder, kMainChoiceMatchIndex); if(aPos < kNumRepDistances) { m_MatchChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, kMatchChoiceRepetitionIndex); if(aPos == 0) { m_MatchRepChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, 0); if(aLen == 1) m_MatchRepShortChoiceEncoders[m_State.m_Index][aPosState].Encode(&m_RangeEncoder, 0); else m_MatchRepShortChoiceEncoders[m_State.m_Index][aPosState].Encode(&m_RangeEncoder, 1); } else { m_MatchRepChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, 1); if (aPos == 1) m_MatchRep1ChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, 0); else { m_MatchRep1ChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, 1); m_MatchRep2ChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, aPos - 2); } } if (aLen == 1) m_State.UpdateShortRep(); else { m_RepMatchLenEncoder.Encode(&m_RangeEncoder, aLen - kMatchMinLen, aPosState); m_State.UpdateRep(); } UINT32 aDistance = m_RepDistances[aPos]; if (aPos != 0) { for(UINT32 i = aPos; i >= 1; i--) m_RepDistances[i] = m_RepDistances[i - 1]; m_RepDistances[0] = aDistance; } } else { m_MatchChoiceEncoders[m_State.m_Index].Encode(&m_RangeEncoder, kMatchChoiceDistanceIndex); m_State.UpdateMatch(); m_LenEncoder.Encode(&m_RangeEncoder, aLen - kMatchMinLen, aPosState); aPos -= kNumRepDistances; UINT32 aPosSlot = GetPosSlot(aPos); UINT32 aLenToPosState = GetLenToPosState(aLen); m_PosSlotEncoder[aLenToPosState].Encode(&m_RangeEncoder, aPosSlot); UINT32 aFooterBits = kDistDirectBits[aPosSlot]; UINT32 aPosReduced = aPos - kDistStart[aPosSlot]; if (aPosSlot >= kStartPosModelIndex) { if (aPosSlot < kEndPosModelIndex) m_PosEncoders[aPosSlot - kStartPosModelIndex].Encode(&m_RangeEncoder, aPosReduced); else { m_RangeEncoder.EncodeDirectBits(aPosReduced >> kNumAlignBits, aFooterBits - kNumAlignBits); m_PosAlignEncoder.Encode(&m_RangeEncoder, aPosReduced & kAlignMask); if (!m_FastMode) if (--m_AlignPriceCount == 0) FillAlignPrices(); } } UINT32 aDistance = aPos; for(UINT32 i = kNumRepDistances - 1; i >= 1; i--) m_RepDistances[i] = m_RepDistances[i - 1]; m_RepDistances[0] = aDistance; } m_PreviousByte = m_MatchFinder.GetIndexByte(aLen - 1 - m_AdditionalOffset); } m_AdditionalOffset -= aLen; aNowPos64 += aLen; if (!m_FastMode) if (aNowPos64 - aLastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); aLastPosSlotFillingPos = aNowPos64; } if (m_AdditionalOffset == 0 && m_MatchFinder.GetNumAvailableBytes() == 0) return Flush(); } } HRESULT CEncoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize) { try { return CodeReal(anInStream, anOutStream, anInSize); } catch (HRESULT& e) { return e; } catch (...) { return E_FAIL; } } void CEncoder::FillPosSlotPrices() { for (int aLenToPosState = 0; aLenToPosState < kNumLenToPosStates; aLenToPosState++) { UINT32 aPosSlot; for (aPosSlot = 0; aPosSlot < kEndPosModelIndex && aPosSlot < m_DistTableSize; aPosSlot++) m_PosSlotPrices[aLenToPosState][aPosSlot] = m_PosSlotEncoder[aLenToPosState].GetPrice(aPosSlot); for (; aPosSlot < m_DistTableSize; aPosSlot++) m_PosSlotPrices[aLenToPosState][aPosSlot] = m_PosSlotEncoder[aLenToPosState].GetPrice(aPosSlot) + ((kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumBitPriceShiftBits); } } void CEncoder::FillDistancesPrices() { for (int aLenToPosState = 0; aLenToPosState < kNumLenToPosStates; aLenToPosState++) { UINT32 i; for (i = 0; i < kStartPosModelIndex; i++) m_DistancesPrices[aLenToPosState][i] = m_PosSlotPrices[aLenToPosState][i]; for (; i < kNumFullDistances; i++) { UINT32 aPosSlot = GetPosSlot(i); m_DistancesPrices[aLenToPosState][i] = m_PosSlotPrices[aLenToPosState][aPosSlot] + m_PosEncoders[aPosSlot - kStartPosModelIndex].GetPrice(i - kDistStart[aPosSlot]); } } } void CEncoder::FillAlignPrices() { for (int i = 0; i < kAlignTableSize; i++) m_AlignPrices[i] = m_PosAlignEncoder.GetPrice(i); m_AlignPriceCount = kAlignTableSize; } }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LZMAEncoder.h ================================================ #ifndef __LZARITHMETIC_ENCODER_H #define __LZARITHMETIC_ENCODER_H #include "Portable.h" #include "AriPrice.h" #include "LZMA.h" #include "LenCoder.h" #include "LiteralCoder.h" #include "AriConst.h" // NOTE Here is choosen the MatchFinder #include "BinTree2.h" #define MATCH_FINDER NBT2::CMatchFinderBinTree namespace NCompress { namespace NLZMA { struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UINT32 PosPrev2; UINT32 BackPrev2; UINT32 Price; UINT32 PosPrev; // posNext; UINT32 BackPrev; UINT32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UINT32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; extern BYTE g_FastPos[1024]; inline UINT32 GetPosSlot(UINT32 aPos) { if (aPos < (1 << 10)) return g_FastPos[aPos]; if (aPos < (1 << 19)) return g_FastPos[aPos >> 9] + 18; return g_FastPos[aPos >> 18] + 36; } inline UINT32 GetPosSlot2(UINT32 aPos) { if (aPos < (1 << 16)) return g_FastPos[aPos >> 6] + 12; if (aPos < (1 << 25)) return g_FastPos[aPos >> 15] + 30; return g_FastPos[aPos >> 24] + 48; } const int kIfinityPrice = 0xFFFFFFF; typedef CMyBitEncoder CMyBitEncoder2; const int kNumOpts = 1 << 12; class CEncoder : public CBaseCoder { COptimal m_Optimum[kNumOpts]; public: MATCH_FINDER m_MatchFinder; CMyRangeEncoder m_RangeEncoder; private: CMyBitEncoder2 m_MainChoiceEncoders[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder2 m_MatchChoiceEncoders[kNumStates]; CMyBitEncoder2 m_MatchRepChoiceEncoders[kNumStates]; CMyBitEncoder2 m_MatchRep1ChoiceEncoders[kNumStates]; CMyBitEncoder2 m_MatchRep2ChoiceEncoders[kNumStates]; CMyBitEncoder2 m_MatchRepShortChoiceEncoders[kNumStates][NLength::kNumPosStatesEncodingMax]; CBitTreeEncoder m_PosSlotEncoder[kNumLenToPosStates]; CReverseBitTreeEncoder2 m_PosEncoders[kNumPosModels]; CReverseBitTreeEncoder2 m_PosAlignEncoder; // CBitTreeEncoder2 m_PosEncoders[kNumPosModels]; // CBitTreeEncoder2 m_PosAlignEncoder; NLength::CPriceTableEncoder m_LenEncoder; NLength::CPriceTableEncoder m_RepMatchLenEncoder; NLiteral::CEncoder m_LiteralEncoder; UINT32 m_MatchDistances[kMatchMaxLen + 1]; bool m_FastMode; bool m_MaxMode; UINT32 m_NumFastBytes; UINT32 m_LongestMatchLength; UINT32 m_AdditionalOffset; UINT32 m_OptimumEndIndex; UINT32 m_OptimumCurrentIndex; bool m_LongestMatchWasFound; UINT32 m_PosSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UINT32 m_DistancesPrices[kNumLenToPosStates][kNumFullDistances]; UINT32 m_AlignPrices[kAlignTableSize]; UINT32 m_AlignPriceCount; UINT32 m_DistTableSize; UINT32 m_PosStateBits; UINT32 m_PosStateMask; UINT32 m_LiteralPosStateBits; UINT32 m_LiteralContextBits; UINT32 m_DictionarySize; UINT32 m_DictionarySizePrev; UINT32 m_NumFastBytesPrev; UINT32 ReadMatchDistances() { UINT32 aLen = m_MatchFinder.GetLongestMatch(m_MatchDistances); if (aLen == m_NumFastBytes) aLen += m_MatchFinder.GetMatchLen(aLen, m_MatchDistances[aLen], kMatchMaxLen - aLen); m_AdditionalOffset++; HRESULT aResult = m_MatchFinder.MovePos(); if (aResult != S_OK) throw aResult; return aLen; } void MovePos(UINT32 aNum); UINT32 GetRepLen1Price(CState aState, UINT32 aPosState) const { return m_MatchRepChoiceEncoders[aState.m_Index].GetPrice(0) + m_MatchRepShortChoiceEncoders[aState.m_Index][aPosState].GetPrice(0); } UINT32 GetRepPrice(UINT32 aRepIndex, UINT32 aLen, CState aState, UINT32 aPosState) const { UINT32 aPrice = m_RepMatchLenEncoder.GetPrice(aLen - kMatchMinLen, aPosState); if(aRepIndex == 0) { aPrice += m_MatchRepChoiceEncoders[aState.m_Index].GetPrice(0); aPrice += m_MatchRepShortChoiceEncoders[aState.m_Index][aPosState].GetPrice(1); } else { aPrice += m_MatchRepChoiceEncoders[aState.m_Index].GetPrice(1); if (aRepIndex == 1) aPrice += m_MatchRep1ChoiceEncoders[aState.m_Index].GetPrice(0); else { aPrice += m_MatchRep1ChoiceEncoders[aState.m_Index].GetPrice(1); aPrice += m_MatchRep2ChoiceEncoders[aState.m_Index].GetPrice(aRepIndex - 2); } } return aPrice; } /* UINT32 GetPosLen2Price(UINT32 aPos, UINT32 aPosState) const { if (aPos >= kNumFullDistances) return kIfinityPrice; return m_DistancesPrices[0][aPos] + m_LenEncoder.GetPrice(0, aPosState); } UINT32 GetPosLen3Price(UINT32 aPos, UINT32 aLen, UINT32 aPosState) const { UINT32 aPrice; UINT32 aLenToPosState = GetLenToPosState(aLen); if (aPos < kNumFullDistances) aPrice = m_DistancesPrices[aLenToPosState][aPos]; else aPrice = m_PosSlotPrices[aLenToPosState][GetPosSlot2(aPos)] + m_AlignPrices[aPos & kAlignMask]; return aPrice + m_LenEncoder.GetPrice(aLen - kMatchMinLen, aPosState); } */ UINT32 GetPosLenPrice(UINT32 aPos, UINT32 aLen, UINT32 aPosState) const { if (aLen == 2 && aPos >= 0x80) return kIfinityPrice; UINT32 aPrice; UINT32 aLenToPosState = GetLenToPosState(aLen); if (aPos < kNumFullDistances) aPrice = m_DistancesPrices[aLenToPosState][aPos]; else aPrice = m_PosSlotPrices[aLenToPosState][GetPosSlot2(aPos)] + m_AlignPrices[aPos & kAlignMask]; return aPrice + m_LenEncoder.GetPrice(aLen - kMatchMinLen, aPosState); } UINT32 Backward(UINT32 &aBackRes, UINT32 aCur); UINT32 GetOptimum(UINT32 &aBackRes, UINT32 aPosition); UINT32 GetOptimumFast(UINT32 &aBackRes, UINT32 aPosition); void FillPosSlotPrices(); void FillDistancesPrices(); void FillAlignPrices(); HRESULT Flush(); HRESULT Create(); HRESULT CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize); HRESULT Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream); public: CEncoder(); HRESULT SetEncoderAlgorithm(UINT32 A); HRESULT SetEncoderNumFastBytes(UINT32 A); HRESULT SetDictionarySize(UINT32 aDictionarySize); HRESULT SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); HRESULT SetPosBitsProperties(UINT32 aNumPosStateBits); HRESULT Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize); HRESULT WriteCoderProperties(ISequentialOutStream *anOutStream); }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LenCoder.cpp ================================================ #include "LenCoder.h" using namespace NCompression; using namespace NArithmetic; namespace NLength { void CEncoder::Init() { m_Choice.Init(); for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++) { m_LowCoder[aPosState].Init(); m_MidCoder[aPosState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } void CEncoder::Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol, UINT32 aPosState) { if(aSymbol < kNumLowSymbols) { m_Choice.Encode(aRangeEncoder, 0); m_LowCoder[aPosState].Encode(aRangeEncoder, aSymbol); } else { aSymbol -= kNumLowSymbols; m_Choice.Encode(aRangeEncoder, 1); if(aSymbol < kNumMidSymbols) { m_Choice2.Encode(aRangeEncoder, 0); m_MidCoder[aPosState].Encode(aRangeEncoder, aSymbol); } else { aSymbol -= kNumMidSymbols; m_Choice2.Encode(aRangeEncoder, 1); m_HighCoder.Encode(aRangeEncoder, aSymbol); } } } UINT32 CEncoder::GetPrice(UINT32 aSymbol, UINT32 aPosState) const { UINT32 aPrice = 0; if(aSymbol < kNumLowSymbols) { aPrice += m_Choice.GetPrice(0); aPrice += m_LowCoder[aPosState].GetPrice(aSymbol); } else { aSymbol -= kNumLowSymbols; aPrice += m_Choice.GetPrice(1); if(aSymbol < kNumMidSymbols) { aPrice += m_Choice2.GetPrice(0); aPrice += m_MidCoder[aPosState].GetPrice(aSymbol); } else { aSymbol -= kNumMidSymbols; aPrice += m_Choice2.GetPrice(1); aPrice += m_HighCoder.GetPrice(aSymbol); } } return aPrice; } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LenCoder.h ================================================ #ifndef __LENCODER_H #define __LENCODER_H #include "BitTreeCoder.h" namespace NLength { const int kNumPosStatesBitsMax = 4; const int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumMoveBits = 5; const int kNumLenBits = 3; const int kNumLowSymbols = 1 << kNumLenBits; const int kNumMidBits = 3; const int kNumMidSymbols = 1 << kNumMidBits; const int kNumHighBits = 8; const int kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); class CEncoder { CMyBitEncoder m_Choice; CBitTreeEncoder m_LowCoder[kNumPosStatesEncodingMax]; CMyBitEncoder m_Choice2; CBitTreeEncoder m_MidCoder[kNumPosStatesEncodingMax]; CBitTreeEncoder m_HighCoder; protected: UINT32 m_NumPosStates; public: void Create(UINT32 aNumPosStates) { m_NumPosStates = aNumPosStates; } void Init(); void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol, UINT32 aPosState); UINT32 GetPrice(UINT32 aSymbol, UINT32 aPosState) const; }; const int kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UINT32 m_Prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; UINT32 m_TableSize; UINT32 m_Counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UINT32 aTableSize) { m_TableSize = aTableSize; } UINT32 GetPrice(UINT32 aSymbol, UINT32 aPosState) const { return m_Prices[aSymbol][aPosState]; } void UpdateTable(UINT32 aPosState) { for (UINT32 aLen = 0; aLen < m_TableSize; aLen++) m_Prices[aLen][aPosState] = CEncoder::GetPrice(aLen , aPosState); m_Counters[aPosState] = m_TableSize; } void UpdateTables() { for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++) UpdateTable(aPosState); } void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol, UINT32 aPosState) { CEncoder::Encode(aRangeEncoder, aSymbol, aPosState); if (--m_Counters[aPosState] == 0) UpdateTable(aPosState); } }; class CDecoder { CMyBitDecoder m_Choice; CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; CMyBitDecoder m_Choice2; CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; CBitTreeDecoder m_HighCoder; UINT32 m_NumPosStates; public: void Create(UINT32 aNumPosStates) { m_NumPosStates = aNumPosStates; } void Init() { m_Choice.Init(); for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++) { m_LowCoder[aPosState].Init(); m_MidCoder[aPosState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } UINT32 Decode(CMyRangeDecoder *aRangeDecoder, UINT32 aPosState) { if(m_Choice.Decode(aRangeDecoder) == 0) return m_LowCoder[aPosState].Decode(aRangeDecoder); else { UINT32 aSymbol = kNumLowSymbols; if(m_Choice2.Decode(aRangeDecoder) == 0) aSymbol += m_MidCoder[aPosState].Decode(aRangeDecoder); else { aSymbol += kNumMidSymbols; aSymbol += m_HighCoder.Decode(aRangeDecoder); } return aSymbol; } } }; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LiteralCoder.cpp ================================================ #include "LiteralCoder.h" using namespace NCompression; using namespace NArithmetic; namespace NLiteral { void CEncoder2::Init() { for (int i = 0; i < 3; i++) for (int j = 1; j < (1 << 8); j++) m_Encoders[i][j].Init(); } void CEncoder2::Encode(CMyRangeEncoder *aRangeEncoder, bool aMatchMode, BYTE aMatchByte, BYTE aSymbol) { UINT32 aContext = 1; bool aSame = true; for (int i = 7; i >= 0; i--) { UINT32 aBit = (aSymbol >> i) & 1; unsigned aState; if (aMatchMode && aSame) { UINT32 aMatchBit = (aMatchByte >> i) & 1; aState = 1 + aMatchBit; aSame = (aMatchBit == aBit); } else aState = 0; m_Encoders[aState][aContext].Encode(aRangeEncoder, aBit); aContext = (aContext << 1) | aBit; } } UINT32 CEncoder2::GetPrice(bool aMatchMode, BYTE aMatchByte, BYTE aSymbol) const { UINT32 aPrice = 0; UINT32 aContext = 1; int i = 7; if (aMatchMode) { for (; i >= 0; i--) { UINT32 aMatchBit = (aMatchByte >> i) & 1; UINT32 aBit = (aSymbol >> i) & 1; aPrice += m_Encoders[1 + aMatchBit][aContext].GetPrice(aBit); aContext = (aContext << 1) | aBit; if (aMatchBit != aBit) { i--; break; } } } for (; i >= 0; i--) { UINT32 aBit = (aSymbol >> i) & 1; aPrice += m_Encoders[0][aContext].GetPrice(aBit); aContext = (aContext << 1) | aBit; } return aPrice; }; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/LiteralCoder.h ================================================ #ifndef __LITERALCODER_H #define __LITERALCODER_H #include "AriBitCoder.h" #include "RCDefs.h" namespace NLiteral { const int kNumMoveBits = 5; class CEncoder2 { CMyBitEncoder m_Encoders[3][1 << 8]; public: void Init(); void Encode(CMyRangeEncoder *aRangeEncoder, bool aMatchMode, BYTE aMatchByte, BYTE aSymbol); UINT32 GetPrice(bool aMatchMode, BYTE aMatchByte, BYTE aSymbol) const; }; class CDecoder2 { CMyBitDecoder m_Decoders[3][1 << 8]; public: void Init() { for (int i = 0; i < 3; i++) for (int j = 1; j < (1 << 8); j++) m_Decoders[i][j].Init(); } BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder) { UINT32 aSymbol = 1; RC_INIT_VAR do { // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) } while (aSymbol < 0x100); RC_FLUSH_VAR return aSymbol; } BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, BYTE aMatchByte) { UINT32 aSymbol = 1; RC_INIT_VAR do { UINT32 aMatchBit = (aMatchByte >> 7) & 1; aMatchByte <<= 1; // UINT32 aBit = m_Decoders[1 + aMatchBit][aSymbol].Decode(aRangeDecoder); // aSymbol = (aSymbol << 1) | aBit; UINT32 aBit; RC_GETBIT2(kNumMoveBits, m_Decoders[1 + aMatchBit][aSymbol].m_Probability, aSymbol, aBit = 0, aBit = 1) if (aMatchBit != aBit) { while (aSymbol < 0x100) { // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) } break; } } while (aSymbol < 0x100); RC_FLUSH_VAR return aSymbol; } }; /* const UINT32 kNumPrevByteBits = 1; const UINT32 kNumPrevByteStates = (1 << kNumPrevByteBits); inline UINT32 GetLiteralState(BYTE aPrevByte) { return (aPrevByte >> (8 - kNumPrevByteBits)); } */ class CEncoder { CEncoder2 *m_Coders; UINT32 m_NumPrevBits; UINT32 m_NumPosBits; UINT32 m_PosMask; public: CEncoder(): m_Coders(0) {} ~CEncoder() { Free(); } void Free() { delete []m_Coders; m_Coders = 0; } void Create(UINT32 aNumPosBits, UINT32 aNumPrevBits) { Free(); m_NumPosBits = aNumPosBits; m_PosMask = (1 << aNumPosBits) - 1; m_NumPrevBits = aNumPrevBits; UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new CEncoder2[aNumStates]; } void Init() { UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); for (UINT32 i = 0; i < aNumStates; i++) m_Coders[i].Init(); } UINT32 GetState(UINT32 aPos, BYTE aPrevByte) const { return ((aPos & m_PosMask) << m_NumPrevBits) + (aPrevByte >> (8 - m_NumPrevBits)); } void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aPos, BYTE aPrevByte, bool aMatchMode, BYTE aMatchByte, BYTE aSymbol) { m_Coders[GetState(aPos, aPrevByte)].Encode(aRangeEncoder, aMatchMode, aMatchByte, aSymbol); } UINT32 GetPrice(UINT32 aPos, BYTE aPrevByte, bool aMatchMode, BYTE aMatchByte, BYTE aSymbol) const { return m_Coders[GetState(aPos, aPrevByte)].GetPrice(aMatchMode, aMatchByte, aSymbol); } }; class CDecoder { CDecoder2 *m_Coders; UINT32 m_NumPrevBits; UINT32 m_NumPosBits; UINT32 m_PosMask; public: CDecoder(): m_Coders(0) {} ~CDecoder() { Free(); } void Free() { delete []m_Coders; m_Coders = 0; } void Create(UINT32 aNumPosBits, UINT32 aNumPrevBits) { Free(); m_NumPosBits = aNumPosBits; m_PosMask = (1 << aNumPosBits) - 1; m_NumPrevBits = aNumPrevBits; UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new CDecoder2[aNumStates]; } void Init() { UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); for (UINT32 i = 0; i < aNumStates; i++) m_Coders[i].Init(); } UINT32 GetState(UINT32 aPos, BYTE aPrevByte) const { return ((aPos & m_PosMask) << m_NumPrevBits) + (aPrevByte >> (8 - m_NumPrevBits)); } BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) { return m_Coders[GetState(aPos, aPrevByte)].DecodeNormal(aRangeDecoder); } BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) { return m_Coders[GetState(aPos, aPrevByte)].DecodeWithMatchByte(aRangeDecoder, aMatchByte); } }; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/OutByte.cpp ================================================ #include "OutByte.h" namespace NStream { COutByte::COutByte(UINT32 aBufferSize): m_BufferSize(aBufferSize) { m_Buffer = new BYTE[m_BufferSize]; } COutByte::~COutByte() { delete []m_Buffer; } void COutByte::Init(ISequentialOutStream *aStream) { m_Stream = aStream; m_ProcessedSize = 0; m_Pos = 0; } HRESULT COutByte::Flush() { if (m_Pos == 0) return S_OK; UINT32 aProcessedSize; HRESULT aResult = m_Stream->Write(m_Buffer, m_Pos, &aProcessedSize); if (aResult != S_OK) return aResult; if (m_Pos != aProcessedSize) return E_FAIL; m_ProcessedSize += aProcessedSize; m_Pos = 0; return S_OK; } void COutByte::WriteBlock() { HRESULT aResult = Flush(); if (aResult != S_OK) throw aResult; } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/OutByte.h ================================================ #ifndef __STREAM_OUTBYTE_H #define __STREAM_OUTBYTE_H #include "Portable.h" #include "IInOutStreams.h" namespace NStream { class COutByte { BYTE *m_Buffer; UINT32 m_Pos; UINT32 m_BufferSize; ISequentialOutStream* m_Stream; UINT64 m_ProcessedSize; void WriteBlock(); public: COutByte(UINT32 aBufferSize = (1 << 20)); ~COutByte(); void Init(ISequentialOutStream *aStream); HRESULT Flush(); void WriteByte(BYTE aByte) { m_Buffer[m_Pos++] = aByte; if(m_Pos >= m_BufferSize) WriteBlock(); } void WriteBytes(const void *aBytes, UINT32 aSize) { for (UINT32 i = 0; i < aSize; i++) WriteByte(((const BYTE *)aBytes)[i]); } UINT64 GetProcessedSize() const { return m_ProcessedSize + m_Pos; } }; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/Portable.h ================================================ #ifndef __PORTABLE_H #define __PORTABLE_H #include typedef signed char INT8; typedef unsigned char UINT8; typedef short INT16; typedef unsigned short UINT16; typedef long INT32; typedef unsigned long UINT32; #if GNU typedef long long INT64; typedef unsigned long long UINT64; #else typedef __int64 INT64; typedef unsigned __int64 UINT64; #endif typedef UINT8 BYTE; typedef UINT16 WORD; typedef UINT32 DWORD; typedef unsigned UINT_PTR; typedef int BOOL; #define FALSE 0 #define TRUE 1 #define HRESULT int #define S_OK 0 #define E_INVALIDARG -1 #define E_OUTOFMEMORY -2 #define E_FAIL -3 #define E_INTERNAL_ERROR -4 #define E_INVALIDDATA -5 template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } #define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/RCDefs.h ================================================ #ifndef __RCDEFS_H #define __RCDEFS_H #include "AriBitCoder.h" #include "AriConst.h" #define RC_INIT_VAR \ UINT32 aRange = aRangeDecoder->m_Range; \ UINT32 aCode = aRangeDecoder->m_Code; #define RC_FLUSH_VAR \ aRangeDecoder->m_Range = aRange; \ aRangeDecoder->m_Code = aCode; #define RC_NORMALIZE \ if (aRange < NCompression::NArithmetic::kTopValue) \ { \ aCode = (aCode << 8) | aRangeDecoder->m_Stream.ReadByte(); \ aRange <<= 8; } #define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ {UINT32 aNewBound = (aRange >> NCompression::NArithmetic::kNumBitModelTotalBits) * aProb; \ if (aCode < aNewBound) \ { \ Action0; \ aRange = aNewBound; \ aProb += (NCompression::NArithmetic::kBitModelTotal - aProb) >> aNumMoveBits; \ aModelIndex <<= 1; \ } \ else \ { \ Action1; \ aRange -= aNewBound; \ aCode -= aNewBound; \ aProb -= (aProb) >> aNumMoveBits; \ aModelIndex = (aModelIndex << 1) + 1; \ }} \ RC_NORMALIZE #define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/RangeCoder.h ================================================ #ifndef __COMPRESSION_RANGECODER_H #define __COMPRESSION_RANGECODER_H #include "InByte.h" #include "OutByte.h" namespace NCompression { namespace NArithmetic { const UINT32 kNumTopBits = 24; const UINT32 kTopValue = (1 << kNumTopBits); class CRangeEncoder { NStream::COutByte m_Stream; UINT64 m_Low; UINT32 m_Range; UINT32 m_FFNum; BYTE m_Cache; public: void Init(ISequentialOutStream *aStream) { m_Stream.Init(aStream); m_Low = 0; m_Range = UINT32(-1); m_FFNum = 0; m_Cache = 0; } void FlushData() { // m_Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return m_Stream.Flush(); } void Encode(UINT32 aStart, UINT32 aSize, UINT32 aTotal) { m_Low += aStart * (m_Range /= aTotal); m_Range *= aSize; while (m_Range < kTopValue) { m_Range <<= 8; ShiftLow(); } } /* void EncodeDirectBitsDiv(UINT32 aValue, UINT32 aNumTotalBits) { m_Low += aValue * (m_Range >>= aNumTotalBits); Normalize(); } void EncodeDirectBitsDiv2(UINT32 aValue, UINT32 aNumTotalBits) { if (aNumTotalBits <= kNumBottomBits) EncodeDirectBitsDiv(aValue, aNumTotalBits); else { EncodeDirectBitsDiv(aValue >> kNumBottomBits, (aNumTotalBits - kNumBottomBits)); EncodeDirectBitsDiv(aValue & ((1 << kBottomValueBits) - 1), kNumBottomBits); } } */ void ShiftLow() { if (m_Low < (UINT32)0xFF000000 || UINT32(m_Low >> 32) == 1) { m_Stream.WriteByte(m_Cache + BYTE(m_Low >> 32)); for (;m_FFNum != 0; m_FFNum--) m_Stream.WriteByte(0xFF + BYTE(m_Low >> 32)); m_Cache = BYTE(UINT32(m_Low) >> 24); } else m_FFNum++; m_Low = UINT32(m_Low) << 8; } void EncodeDirectBits(UINT32 aValue, UINT32 aNumTotalBits) { for (int i = aNumTotalBits - 1; i >= 0; i--) { m_Range >>= 1; if (((aValue >> i) & 1) == 1) m_Low += m_Range; if (m_Range < kTopValue) { m_Range <<= 8; ShiftLow(); } } } void EncodeBit(UINT32 aSize0, UINT32 aNumTotalBits, UINT32 aSymbol) { UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0; if (aSymbol == 0) m_Range = aNewBound; else { m_Low += aNewBound; m_Range -= aNewBound; } while (m_Range < kTopValue) { m_Range <<= 8; ShiftLow(); } } UINT64 GetProcessedSize() { return m_Stream.GetProcessedSize() + m_FFNum; } }; class CRangeDecoder { public: NStream::CInByte m_Stream; UINT32 m_Range; UINT32 m_Code; UINT32 m_Word; void Normalize() { while (m_Range < kTopValue) { m_Code = (m_Code << 8) | m_Stream.ReadByte(); m_Range <<= 8; } } void Init(ISequentialInStream *aStream) { m_Stream.Init(aStream); m_Code = 0; m_Range = UINT32(-1); for(int i = 0; i < 5; i++) m_Code = (m_Code << 8) | m_Stream.ReadByte(); } UINT32 GetThreshold(UINT32 aTotal) { return (m_Code) / ( m_Range /= aTotal); } void Decode(UINT32 aStart, UINT32 aSize, UINT32 aTotal) { m_Code -= aStart * m_Range; m_Range *= aSize; Normalize(); } /* UINT32 DecodeDirectBitsDiv(UINT32 aNumTotalBits) { m_Range >>= aNumTotalBits; UINT32 aThreshold = m_Code / m_Range; m_Code -= aThreshold * m_Range; Normalize(); return aThreshold; } UINT32 DecodeDirectBitsDiv2(UINT32 aNumTotalBits) { if (aNumTotalBits <= kNumBottomBits) return DecodeDirectBitsDiv(aNumTotalBits); UINT32 aResult = DecodeDirectBitsDiv(aNumTotalBits - kNumBottomBits) << kNumBottomBits; return (aResult | DecodeDirectBitsDiv(kNumBottomBits)); } */ UINT32 DecodeDirectBits(UINT32 aNumTotalBits) { UINT32 aRange = m_Range; UINT32 aCode = m_Code; UINT32 aResult = 0; for (UINT32 i = aNumTotalBits; i > 0; i--) { aRange >>= 1; /* aResult <<= 1; if (aCode >= aRange) { aCode -= aRange; aResult |= 1; } */ UINT32 t = (aCode - aRange) >> 31; aCode -= aRange & (t - 1); // aRange = aRangeTmp + ((aRange & 1) & (1 - t)); aResult = (aResult << 1) | (1 - t); if (aRange < kTopValue) { aCode = (aCode << 8) | m_Stream.ReadByte(); aRange <<= 8; } } m_Range = aRange; m_Code = aCode; return aResult; } UINT32 DecodeBit(UINT32 aSize0, UINT32 aNumTotalBits) { UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0; UINT32 aSymbol; if (m_Code < aNewBound) { aSymbol = 0; m_Range = aNewBound; } else { aSymbol = 1; m_Code -= aNewBound; m_Range -= aNewBound; } Normalize(); return aSymbol; } UINT64 GetProcessedSize() {return m_Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/StdAfx.cpp ================================================ // stdafx.cpp : source file that includes just the standard includes // ProgramStore.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "StdAfx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/StdAfx.h ================================================ // stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__FF26AFB2_1227_11D4_A62F_00C04F69DA2B__INCLUDED_) #define AFX_STDAFX_H__FF26AFB2_1227_11D4_A62F_00C04F69DA2B__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__FF26AFB2_1227_11D4_A62F_00C04F69DA2B__INCLUDED_) ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/WindowIn.cpp ================================================ #include "Portable.h" #include "WindowIn.h" namespace NStream { namespace NWindow { CIn::CIn(): m_BufferBase(0) {} void CIn::Free() { delete []m_BufferBase; m_BufferBase = 0; } void CIn::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv) { m_KeepSizeBefore = aKeepSizeBefore; m_KeepSizeAfter = aKeepSizeAfter; m_KeepSizeReserv = aKeepSizeReserv; m_BlockSize = aKeepSizeBefore + aKeepSizeAfter + aKeepSizeReserv; Free(); m_BufferBase = new BYTE[m_BlockSize]; m_PointerToLastSafePosition = m_BufferBase + m_BlockSize - aKeepSizeAfter; } CIn::~CIn() { Free(); } HRESULT CIn::Init(ISequentialInStream *aStream) { m_Stream = aStream; m_Buffer = m_BufferBase; m_Pos = 0; m_StreamPos = 0; m_StreamEndWasReached = false; return ReadBlock(); } /////////////////////////////////////////// // ReadBlock // In State: // (m_Buffer + m_StreamPos) <= (m_BufferBase + m_BlockSize) // Out State: // m_PosLimit <= m_BlockSize - m_KeepSizeAfter; // if(m_StreamEndWasReached == false): // m_StreamPos >= m_Pos + m_KeepSizeAfter // m_PosLimit = m_StreamPos - m_KeepSizeAfter; // else // HRESULT CIn::ReadBlock() { if(m_StreamEndWasReached) return S_OK; while(true) { UINT32 aSize = (m_BufferBase + m_BlockSize) - (m_Buffer + m_StreamPos); if(aSize == 0) return S_OK; UINT32 aNumReadBytes; RETURN_IF_NOT_S_OK(m_Stream->Read(m_Buffer + m_StreamPos, aSize, &aNumReadBytes)); if(aNumReadBytes == 0) { m_PosLimit = m_StreamPos; const BYTE *aPointerToPostion = m_Buffer + m_PosLimit; if(aPointerToPostion > m_PointerToLastSafePosition) m_PosLimit = m_PointerToLastSafePosition - m_Buffer; m_StreamEndWasReached = true; return S_OK; } m_StreamPos += aNumReadBytes; if(m_StreamPos >= m_Pos + m_KeepSizeAfter) { m_PosLimit = m_StreamPos - m_KeepSizeAfter; return S_OK; } } } void CIn::MoveBlock() { BeforeMoveBlock(); UINT32 anOffset = (m_Buffer + m_Pos - m_KeepSizeBefore) - m_BufferBase; UINT32 aNumBytes = (m_Buffer + m_StreamPos) - (m_BufferBase + anOffset); memmove(m_BufferBase, m_BufferBase + anOffset, aNumBytes); m_Buffer -= anOffset; AfterMoveBlock(); } }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/WindowIn.h ================================================ #ifndef __STREAM_WINDOWIN_H #define __STREAM_WINDOWIN_H #include "IInOutStreams.h" namespace NStream { namespace NWindow { class CIn { BYTE *m_BufferBase; // pointer to buffer with data ISequentialInStream* m_Stream; UINT32 m_PosLimit; // offset (from m_Buffer) of first byte when new block reading must be done bool m_StreamEndWasReached; // if (true) then m_StreamPos shows real end of stream const BYTE *m_PointerToLastSafePosition; protected: BYTE *m_Buffer; // Pointer to virtual Buffer begin UINT32 m_BlockSize; // Size of Allocated memory block UINT32 m_Pos; // offset (from m_Buffer) of curent byte UINT32 m_KeepSizeBefore; // how many BYTEs must be kept in buffer before m_Pos UINT32 m_KeepSizeAfter; // how many BYTEs must be kept buffer after m_Pos UINT32 m_KeepSizeReserv; // how many BYTEs must be kept as reserv UINT32 m_StreamPos; // offset (from m_Buffer) of first not read byte from Stream virtual void BeforeMoveBlock() {}; virtual void AfterMoveBlock() {}; void MoveBlock(); virtual HRESULT ReadBlock(); void Free(); public: CIn(); void Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17)); virtual ~CIn(); HRESULT Init(ISequentialInStream *aStream); BYTE *GetBuffer() const { return m_Buffer; } const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos; } HRESULT MovePos() { m_Pos++; if (m_Pos > m_PosLimit) { const BYTE *aPointerToPostion = m_Buffer + m_Pos; if(aPointerToPostion > m_PointerToLastSafePosition) MoveBlock(); return ReadBlock(); } else return S_OK; } // BYTE GetCurrentByte()const; BYTE GetIndexByte(UINT32 anIndex)const { return m_Buffer[m_Pos + anIndex]; } // UINT32 GetCurPos()const { return m_Pos;}; // BYTE *GetBufferBeg()const { return m_Buffer;}; // aIndex + aLimit have not to exceed m_KeepSizeAfter; UINT32 GetMatchLen(UINT32 aIndex, UINT32 aBack, UINT32 aLimit) const { if(m_StreamEndWasReached) if ((m_Pos + aIndex) + aLimit > m_StreamPos) aLimit = m_StreamPos - (m_Pos + aIndex); aBack++; BYTE *pby = m_Buffer + m_Pos + aIndex; UINT32 i; for(i = 0; i < aLimit && pby[i] == pby[i - aBack]; i++); return i; } UINT32 GetNumAvailableBytes() const { return m_StreamPos - m_Pos; } void ReduceOffsets(UINT32 aSubValue) { m_Buffer += aSubValue; m_PosLimit -= aSubValue; m_Pos -= aSubValue; m_StreamPos -= aSubValue; } }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/WindowOut.cpp ================================================ #include "WindowOut.h" namespace NStream { namespace NWindow { void COut::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv) { m_Pos = 0; m_PosLimit = aKeepSizeReserv + aKeepSizeBefore; m_KeepSizeBefore = aKeepSizeBefore; m_KeepSizeAfter = aKeepSizeAfter; m_KeepSizeReserv = aKeepSizeReserv; m_StreamPos = 0; m_MoveFrom = m_KeepSizeReserv; m_WindowSize = aKeepSizeBefore; UINT32 aBlockSize = m_KeepSizeBefore + m_KeepSizeAfter + m_KeepSizeReserv; delete []m_Buffer; m_Buffer = new BYTE[aBlockSize]; } COut::~COut() { delete []m_Buffer; } void COut::SetWindowSize(UINT32 aWindowSize) { m_WindowSize = aWindowSize; m_MoveFrom = m_KeepSizeReserv + m_KeepSizeBefore - aWindowSize; } void COut::Init(ISequentialOutStream *aStream, bool aSolid) { m_Stream = aStream; if(aSolid) m_StreamPos = m_Pos; else { m_Pos = 0; m_PosLimit = m_KeepSizeReserv + m_KeepSizeBefore; m_StreamPos = 0; } } HRESULT COut::Flush() { UINT32 aSize = m_Pos - m_StreamPos; if(aSize == 0) return S_OK; UINT32 aProcessedSize; HRESULT aResult = m_Stream->Write(m_Buffer + m_StreamPos, aSize, &aProcessedSize); if (aResult != S_OK) return aResult; if (aSize != aProcessedSize) return E_FAIL; m_StreamPos = m_Pos; return S_OK; } void COut::MoveBlockBackward() { HRESULT aResult = Flush(); if (aResult != S_OK) throw aResult; memmove(m_Buffer, m_Buffer + m_MoveFrom, m_WindowSize + m_KeepSizeAfter); m_Pos -= m_MoveFrom; m_StreamPos -= m_MoveFrom; } }} ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/WindowOut.h ================================================ #ifndef __STREAM_WINDOWOUT_H #define __STREAM_WINDOWOUT_H #include "IInOutStreams.h" namespace NStream { namespace NWindow { // m_KeepSizeBefore: how mach BYTEs must be in buffer before m_Pos; // m_KeepSizeAfter: how mach BYTEs must be in buffer after m_Pos; // m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv; // must be >= aKeepSizeAfter; // test it class COut { BYTE *m_Buffer; UINT32 m_Pos; UINT32 m_PosLimit; UINT32 m_KeepSizeBefore; UINT32 m_KeepSizeAfter; UINT32 m_KeepSizeReserv; UINT32 m_StreamPos; UINT32 m_WindowSize; UINT32 m_MoveFrom; ISequentialOutStream *m_Stream; virtual void MoveBlockBackward(); public: COut(): m_Buffer(0), m_Stream(0) {} virtual ~COut(); void Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17)); void SetWindowSize(UINT32 aWindowSize); void Init(ISequentialOutStream *aStream, bool aSolid = false); HRESULT Flush(); UINT32 GetCurPos() const { return m_Pos; } const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos;}; void CopyBackBlock(UINT32 aDistance, UINT32 aLen) { if (m_Pos >= m_PosLimit) MoveBlockBackward(); BYTE *p = m_Buffer + m_Pos; aDistance++; for(UINT32 i = 0; i < aLen; i++) p[i] = p[i - aDistance]; m_Pos += aLen; } void PutOneByte(BYTE aByte) { if (m_Pos >= m_PosLimit) MoveBlockBackward(); m_Buffer[m_Pos++] = aByte; } BYTE GetOneByte(UINT32 anIndex) const { return m_Buffer[m_Pos + anIndex]; } BYTE *GetBuffer() const { return m_Buffer; } }; }} #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/compress/lzDecomp.cpp ================================================ #include "stdio.h" #include "LZMADecoder.h" //static LzmaDecoder cc; ISequentialInStream in_stream; ISequentialOutStream out_stream; int decompress_lzma_7z( unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) { // LzmaDecoder cc; int RC; UINT64 in_size_l = in_size; UINT64 out_size_l = out_size; InStreamInit(in_data, in_size); OutStreamInit((char *)out_data, out_size); LzmaDecoderConstructor(&cc); if ((RC = LzmaDecoderReadCoderProperties(&cc)) != S_OK) { return RC; } if (LzmaDecoderCode(&cc, &in_size_l, &out_size_l) != S_OK) { return -2; } if (out_stream.size != out_size) { return -3; } if ( out_stream.overflow ) { return -4; } printf( "\nDecompressed size: %d\n", out_stream.total ); return 0; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/7z.h ================================================ #ifndef __7Z_H #define __7Z_H #if defined __cplusplus extern "C" { #endif int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size); #if defined __cplusplus } #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/7zlzma.c ================================================ #include "7z.h" #ifdef _HOST_TOOL #include "stdio.h" #endif #include "LZMADecoder.h" static LzmaDecoder cc; ISequentialInStream in_stream; ISequentialOutStream out_stream; int decompress_lzma_7z( unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) { // LzmaDecoder cc; int RC; UINT64 in_size_l = in_size; UINT64 out_size_l = out_size; InStreamInit(in_data, in_size); OutStreamInit((char *)out_data, out_size); LzmaDecoderConstructor(&cc); if ((RC = LzmaDecoderReadCoderProperties(&cc)) != S_OK) { return RC; } if (LzmaDecoderCode(&cc, &in_size_l, &out_size_l) != S_OK) { return -2; } if (out_stream.size != out_size) { return -3; } if ( out_stream.overflow ) { return -4; } return 0; } //BRCM modification #ifdef __KERNEL__ EXPORT_SYMBOL(decompress_lzma_7z); #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/AriBitCoder.h ================================================ #ifndef __COMPRESSION_BITCODER_H #define __COMPRESSION_BITCODER_H #include "RangeCoder.h" #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveReducingBits 2 typedef UINT32 CBitDecoder; INLINE void BitDecoderInit(CBitDecoder *bitDecoder) { *bitDecoder = kBitModelTotal / 2; } #if 0 UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder); #else INLINE UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * (*bitDecoder); if (aRangeDecoder->m_Code < aNewBound) { aRangeDecoder->m_Range = aNewBound; *bitDecoder += (kBitModelTotal - *bitDecoder) >> kNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); aRangeDecoder->m_Range <<= 8; } return 0; } else { aRangeDecoder->m_Range -= aNewBound; aRangeDecoder->m_Code -= aNewBound; *bitDecoder -= (*bitDecoder) >> kNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); aRangeDecoder->m_Range <<= 8; } return 1; } } #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/BitTreeCoder.h ================================================ #ifndef __BITTREECODER_H #define __BITTREECODER_H #include "AriBitCoder.h" #include "RCDefs.h" //BRCM modification start // Duplication of malloc/free redirection macros from the two header files // namely, BitTreeCoder.h and LiteralCoder.h, were moved to a single // implementation in RCDefs.h that is included by both the above header files. //BRCM modification end ////////////////////////// // CBitTreeDecoder typedef struct CBitTreeDecoder { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CBitTreeDecoder; // ~CBitTreeDecoder() { free(m_Models); } INLINE void BitTreeDecoderInit(CBitTreeDecoder *bitTreeDecoder, UINT32 aNumBitLevels) { int i; bitTreeDecoder->m_NumBitLevels = aNumBitLevels; bitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); //BRCM modification //printf("malloc in BitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); if (!bitTreeDecoder->m_Models) { printf("Error in allocating memory for bitTreeDecoder!\n"); return; } for(i = 1; i < (1 << aNumBitLevels); i++) BitDecoderInit(&bitTreeDecoder->m_Models[i]); } INLINE UINT32 BitTreeDecode(ISequentialInStream *in_stream, CBitTreeDecoder *bitTreeDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = bitTreeDecoder->m_NumBitLevels; aBitIndex > 0; aBitIndex--) { RC_GETBIT(kNumMoveBits, bitTreeDecoder->m_Models[aModelIndex], aModelIndex) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aModelIndex - (1 << bitTreeDecoder->m_NumBitLevels); } //////////////////////////////// // CReverseBitTreeDecoder2 typedef struct CReverseBitTreeDecoder2 { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CReverseBitTreeDecoder2; // CReverseBitTreeDecoder2(): m_Models(0) { } // ~CReverseBitTreeDecoder2() { free(m_Models); } INLINE BOOL ReverseBitTreeDecoder2Create(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, UINT32 aNumBitLevels) { reverseBitTreeDecoder2->m_NumBitLevels = aNumBitLevels; reverseBitTreeDecoder2->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); //printf("malloc in ReverseBitTreeDecoder2Create=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); if (!reverseBitTreeDecoder2->m_Models) { printf("Error in allocating memory for reverseBitTreeDecoder2!\n"); return 0; } return (reverseBitTreeDecoder2->m_Models != 0); } INLINE void ReverseBitTreeDecoder2Init(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2) { UINT32 aNumModels = 1 << reverseBitTreeDecoder2->m_NumBitLevels; UINT32 i; for(i = 1; i < aNumModels; i++) BitDecoderInit(&reverseBitTreeDecoder2->m_Models[i]); } INLINE UINT32 ReverseBitTreeDecoder2Decode(ISequentialInStream *in_stream, CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder2->m_NumBitLevels; aBitIndex++) { RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder2->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } //////////////////////////// // CReverseBitTreeDecoder typedef struct CReverseBitTreeDecoder { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CReverseBitTreeDecoder; // CReverseBitTreeDecoder(): m_Models(0) { } // ~CReverseBitTreeDecoder() { free(m_Models); } INLINE void ReverseBitTreeDecoderInit(CReverseBitTreeDecoder *reverseBitTreeDecoder, UINT32 aNumBitLevels) { int i; reverseBitTreeDecoder->m_NumBitLevels = aNumBitLevels; reverseBitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); //printf("malloc in ReverseBitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); if (!reverseBitTreeDecoder->m_Models) { printf("Error in allocating memory for reverseBitTreeDecoder!\n"); return; } for(i = 1; i < (1 << reverseBitTreeDecoder->m_NumBitLevels); i++) BitDecoderInit(&reverseBitTreeDecoder->m_Models[i]); } INLINE UINT32 ReverseBitTreeDecoderDecode(ISequentialInStream *in_stream, CReverseBitTreeDecoder *reverseBitTreeDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder->m_NumBitLevels; aBitIndex++) { RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/IInOutStreams.c ================================================ #include "IInOutStreams.h" // BRCM modification static void *lib_memcpy(void *dest,const void *src,size_t cnt); static void *lib_memcpy(void *dest,const void *src,size_t cnt) { unsigned char *d; const unsigned char *s; d = (unsigned char *) dest; s = (const unsigned char *) src; while (cnt) { *d++ = *s++; cnt--; } return dest; } HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize) { if (aSize > in_stream.remainingBytes) aSize = in_stream.remainingBytes; *aProcessedSize = aSize; lib_memcpy(aData, in_stream.data, aSize); // brcm modification in_stream.remainingBytes -= aSize; in_stream.data += aSize; return S_OK; } #if 0 BYTE InStreamReadByte() { if (in_stream.remainingBytes == 0) return 0x0; in_stream.remainingBytes--; return (BYTE) *in_stream.data++; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/IInOutStreams.h ================================================ #ifndef __IINOUTSTREAMS_H #define __IINOUTSTREAMS_H #include "Portable.h" typedef struct ISequentialInStream { unsigned char* data; unsigned remainingBytes; } ISequentialInStream; extern ISequentialInStream in_stream; INLINE void InStreamInit(unsigned char * Adata, unsigned Asize) { in_stream.data = Adata; in_stream.remainingBytes = Asize; } HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize); #if 0 BYTE InStreamReadByte(); #else INLINE BYTE InStreamReadByte(ISequentialInStream *in_stream) { if (in_stream->remainingBytes == 0) return 0x0; in_stream->remainingBytes--; return (BYTE) *in_stream->data++; } #endif typedef struct ISequentialOutStream { char* data; unsigned size; BOOL overflow; unsigned total; } ISequentialOutStream; extern ISequentialOutStream out_stream; #define OutStreamInit(Adata, Asize) \ { \ out_stream.data = Adata; \ out_stream.size = Asize; \ out_stream.overflow = FALSE; \ out_stream.total = 0; \ } #define OutStreamSizeSet(newsize) \ { \ out_stream.total = newsize; \ if (out_stream.total > out_stream.size) \ out_stream.overflow = TRUE; \ } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/LZMA.h ================================================ #include "LenCoder.h" #ifndef __LZMA_H #define __LZMA_H #define kNumRepDistances 4 #define kNumStates 12 static const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; typedef BYTE CState; INLINE void CStateInit(CState *m_Index) { *m_Index = 0; } INLINE void CStateUpdateChar(CState *m_Index) { *m_Index = kLiteralNextStates[*m_Index]; } INLINE void CStateUpdateMatch(CState *m_Index) { *m_Index = kMatchNextStates[*m_Index]; } INLINE void CStateUpdateRep(CState *m_Index) { *m_Index = kRepNextStates[*m_Index]; } INLINE void CStateUpdateShortRep(CState *m_Index) { *m_Index = kShortRepNextStates[*m_Index]; } #define kNumPosSlotBits 6 #define kDicLogSizeMax 28 #define kDistTableSizeMax 56 //extern UINT32 kDistStart[kDistTableSizeMax]; static const BYTE kDistDirectBits[kDistTableSizeMax] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 }; #define kNumLenToPosStates 4 INLINE UINT32 GetLenToPosState(UINT32 aLen) { aLen -= 2; if (aLen < kNumLenToPosStates) return aLen; return kNumLenToPosStates - 1; } #define kMatchMinLen 2 #define kMatchMaxLen (kMatchMinLen + kNumSymbolsTotal - 1) #define kNumAlignBits 4 #define kAlignTableSize 16 #define kAlignMask 15 #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels 10 #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #define kMainChoiceLiteralIndex 0 #define kMainChoiceMatchIndex 1 #define kMatchChoiceDistanceIndex0 #define kMatchChoiceRepetitionIndex 1 #define kNumMoveBitsForMainChoice 5 #define kNumMoveBitsForPosCoders 5 #define kNumMoveBitsForAlignCoders 5 #define kNumMoveBitsForPosSlotCoder 5 #define kNumLitPosStatesBitsEncodingMax 4 #define kNumLitContextBitsMax 8 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/LZMADecoder.c ================================================ #include "Portable.h" #ifdef _HOST_TOOL #include "stdio.h" #endif #include "LZMADecoder.h" //#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } static UINT32 kDistStart[kDistTableSizeMax]; struct WindowOut out_window; /* * BRCM modification: free all the allocated buffer by malloc * */ static void LzmaDecoderFreeBuffer(LzmaDecoder *lzmaDecoder) { int i,aPosState; //printf("free lzmaDecoder->m_LiteralDecoder\n"); free((&lzmaDecoder->m_LiteralDecoder)->m_Coders); for (i = 0; i < kNumLenToPosStates; i++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free((&lzmaDecoder->m_PosSlotDecoder[i])->m_Models); } // from LenDecoderInit(&lzmaDecoder->m_LenDecoder; for (aPosState = 0; aPosState < (&lzmaDecoder->m_LenDecoder)->m_NumPosStates; aPosState++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_LowCoder[aPosState])->m_Models ); //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_MidCoder[aPosState])->m_Models ); } //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_HighCoder)->m_Models ); // from LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); for (aPosState = 0; aPosState < (&lzmaDecoder->m_RepMatchLenDecoder)->m_NumPosStates; aPosState++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_LowCoder[aPosState])->m_Models ); //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_MidCoder[aPosState])->m_Models ); } //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_HighCoder)->m_Models ); //printf("free lzmaDecoder->m_PosAlignDecoder\n"); free((&lzmaDecoder->m_PosAlignDecoder)->m_Models); for(i = 0; i < kNumPosModels; i++) { //printf("free lzmaDecoder->m_PosDecoders\n"); free((&lzmaDecoder->m_PosDecoders[i])->m_Models); } } HRESULT LzmaDecoderSetDictionarySize( LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize) { if (aDictionarySize > (1 << kDicLogSizeMax)) return E_INVALIDARG; // UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); if (lzmaDecoder->m_DictionarySize != aDictionarySize) { lzmaDecoder->m_DictionarySize = aDictionarySize; } return S_OK; } HRESULT LzmaDecoderSetLiteralProperties( LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) { if (aLiteralPosStateBits > 8) return E_INVALIDARG; if (aLiteralContextBits > 8) return E_INVALIDARG; LitDecoderCreate(&lzmaDecoder->m_LiteralDecoder, aLiteralPosStateBits, aLiteralContextBits); return S_OK; } HRESULT LzmaDecoderSetPosBitsProperties( LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits) { UINT32 aNumPosStates; if (aNumPosStateBits > (UINT32) kNumPosStatesBitsMax) return E_INVALIDARG; aNumPosStates = 1 << aNumPosStateBits; LenDecoderCreate(&lzmaDecoder->m_LenDecoder, aNumPosStates); LenDecoderCreate(&lzmaDecoder->m_RepMatchLenDecoder, aNumPosStates); lzmaDecoder->m_PosStateMask = aNumPosStates - 1; return S_OK; } void LzmaDecoderConstructor(LzmaDecoder *lzmaDecoder) { lzmaDecoder->m_DictionarySize = ((UINT32)-1); LzmaDecoderCreate(lzmaDecoder); } HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder) { int i; for(i = 0; i < kNumPosModels; i++) { if (!(ReverseBitTreeDecoder2Create(&lzmaDecoder->m_PosDecoders[i],kDistDirectBits[kStartPosModelIndex + i]))) return E_OUTOFMEMORY;; } return S_OK; } HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder) { int i; UINT32 j; RangeDecoderInit(&in_stream, &lzmaDecoder->m_RangeDecoder); OutWindowInit(); for(i = 0; i < kNumStates; i++) { for (j = 0; j <= lzmaDecoder->m_PosStateMask; j++) { BitDecoderInit(&lzmaDecoder->m_MainChoiceDecoders[i][j]); BitDecoderInit(&lzmaDecoder->m_MatchRepShortChoiceDecoders[i][j]); } BitDecoderInit(&lzmaDecoder->m_MatchChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRepChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRep1ChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRep2ChoiceDecoders[i]); } LitDecoderInit(&lzmaDecoder->m_LiteralDecoder); for (i = 0; i < (int) kNumLenToPosStates; i++) BitTreeDecoderInit(&lzmaDecoder->m_PosSlotDecoder[i],kNumPosSlotBits); for(i = 0; i < kNumPosModels; i++) ReverseBitTreeDecoder2Init(&lzmaDecoder->m_PosDecoders[i]); LenDecoderInit(&lzmaDecoder->m_LenDecoder); LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); ReverseBitTreeDecoderInit(&lzmaDecoder->m_PosAlignDecoder, kNumAlignBits); return S_OK; } HRESULT LzmaDecoderCodeReal( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize) { BOOL aPeviousIsMatch = FALSE; BYTE aPreviousByte = 0; UINT32 aRepDistances[kNumRepDistances]; int i; UINT64 aNowPos64 = 0; UINT64 aSize = *anOutSize; ISequentialInStream my_in_stream; // WindowOut out_window; CState aState; CStateInit(&aState); if (anOutSize == NULL) { printf("CodeReal: invalid argument %x\n", (UINT32) anOutSize ); return E_INVALIDARG; } LzmaDecoderInit(lzmaDecoder); my_in_stream.data = in_stream.data; my_in_stream.remainingBytes = in_stream.remainingBytes; for(i = 0 ; i < (int) kNumRepDistances; i++) aRepDistances[i] = 0; //while(aNowPos64 < aSize) while(my_in_stream.remainingBytes > 0) { UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); while(aNowPos64 < aNext) { UINT32 aPosState = (UINT32)(aNowPos64) & lzmaDecoder->m_PosStateMask; if (BitDecode(&my_in_stream, &lzmaDecoder->m_MainChoiceDecoders[aState][aPosState], &lzmaDecoder->m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) { CStateUpdateChar(&aState); if(aPeviousIsMatch) { BYTE aMatchByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); aPreviousByte = LitDecodeWithMatchByte(&my_in_stream, &lzmaDecoder->m_LiteralDecoder, &lzmaDecoder->m_RangeDecoder, (UINT32)(aNowPos64), aPreviousByte, aMatchByte); aPeviousIsMatch = FALSE; } else aPreviousByte = LitDecodeNormal(&my_in_stream, &lzmaDecoder->m_LiteralDecoder, &lzmaDecoder->m_RangeDecoder, (UINT32)(aNowPos64), aPreviousByte); OutWindowPutOneByte(aPreviousByte); aNowPos64++; } else { UINT32 aDistance, aLen; aPeviousIsMatch = TRUE; if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex) { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRepChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRepShortChoiceDecoders[aState][aPosState], &lzmaDecoder->m_RangeDecoder) == 0) { CStateUpdateShortRep(&aState); aPreviousByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); OutWindowPutOneByte(aPreviousByte); aNowPos64++; continue; } aDistance = aRepDistances[0]; } else { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRep1ChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { aDistance = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } else { if (BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRep2ChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { aDistance = aRepDistances[2]; } else { aDistance = aRepDistances[3]; aRepDistances[3] = aRepDistances[2]; } aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } aRepDistances[0] = aDistance; } aLen = LenDecode(&my_in_stream, &lzmaDecoder->m_RepMatchLenDecoder, &lzmaDecoder->m_RangeDecoder, aPosState) + kMatchMinLen; CStateUpdateRep(&aState); } else { UINT32 aPosSlot; aLen = kMatchMinLen + LenDecode(&my_in_stream, &lzmaDecoder->m_LenDecoder, &lzmaDecoder->m_RangeDecoder, aPosState); CStateUpdateMatch(&aState); aPosSlot = BitTreeDecode(&my_in_stream, &lzmaDecoder->m_PosSlotDecoder[GetLenToPosState(aLen)], &lzmaDecoder->m_RangeDecoder); if (aPosSlot >= (UINT32) kStartPosModelIndex) { aDistance = kDistStart[aPosSlot]; if (aPosSlot < (UINT32) kEndPosModelIndex) aDistance += ReverseBitTreeDecoder2Decode(&my_in_stream, &lzmaDecoder->m_PosDecoders[aPosSlot - kStartPosModelIndex], &lzmaDecoder->m_RangeDecoder); else { aDistance += (RangeDecodeDirectBits(&my_in_stream, &lzmaDecoder->m_RangeDecoder, kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits); aDistance += ReverseBitTreeDecoderDecode(&my_in_stream, &lzmaDecoder->m_PosAlignDecoder, &lzmaDecoder->m_RangeDecoder); } } else aDistance = aPosSlot; aRepDistances[3] = aRepDistances[2]; aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; aRepDistances[0] = aDistance; } if (aDistance >= aNowPos64) { printf("CodeReal: invalid data\n" ); return E_INVALIDDATA; } OutWindowCopyBackBlock(aDistance, aLen); aNowPos64 += aLen; aPreviousByte = OutWindowGetOneByte(0 - 1); } } } //BRCM modification LzmaDecoderFreeBuffer(lzmaDecoder); OutWindowFlush(); return S_OK; } HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize) { UINT32 aStartValue = 0; int i; for (i = 0; i < kDistTableSizeMax; i++) { kDistStart[i] = aStartValue; aStartValue += (1 << kDistDirectBits[i]); } return LzmaDecoderCodeReal( lzmaDecoder, anInSize, anOutSize); } HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder) { UINT32 aNumPosStateBits; UINT32 aLiteralPosStateBits; UINT32 aLiteralContextBits; UINT32 aDictionarySize; BYTE aRemainder; UINT32 aProcessesedSize; BYTE aByte; RETURN_IF_NOT_S_OK(InStreamRead(&aByte, sizeof(aByte), &aProcessesedSize)); if (aProcessesedSize != sizeof(aByte)) return E_INVALIDARG; aLiteralContextBits = aByte % 9; aRemainder = aByte / 9; aLiteralPosStateBits = aRemainder % 5; aNumPosStateBits = aRemainder / 5; RETURN_IF_NOT_S_OK(InStreamRead(&aDictionarySize, sizeof(aDictionarySize), &aProcessesedSize)); if (aProcessesedSize != sizeof(aDictionarySize)) return E_INVALIDARG; RETURN_IF_NOT_S_OK( LzmaDecoderSetDictionarySize(lzmaDecoder, aDictionarySize) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetLiteralProperties(lzmaDecoder, aLiteralPosStateBits, aLiteralContextBits) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetPosBitsProperties(lzmaDecoder, aNumPosStateBits) ); return S_OK; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/LZMADecoder.h ================================================ #ifndef __LZARITHMETIC_DECODER_H #define __LZARITHMETIC_DECODER_H #include "WindowOut.h" #include "LZMA.h" #include "LenCoder.h" #include "LiteralCoder.h" typedef struct LzmaDecoder { CRangeDecoder m_RangeDecoder; CBitDecoder m_MainChoiceDecoders[kNumStates][kNumPosStatesMax]; CBitDecoder m_MatchChoiceDecoders[kNumStates]; CBitDecoder m_MatchRepChoiceDecoders[kNumStates]; CBitDecoder m_MatchRep1ChoiceDecoders[kNumStates]; CBitDecoder m_MatchRep2ChoiceDecoders[kNumStates]; CBitDecoder m_MatchRepShortChoiceDecoders[kNumStates][kNumPosStatesMax]; CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; CReverseBitTreeDecoder m_PosAlignDecoder; LenDecoder m_LenDecoder; LenDecoder m_RepMatchLenDecoder; LitDecoder m_LiteralDecoder; UINT32 m_DictionarySize; UINT32 m_PosStateMask; } LzmaDecoder; HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder); HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder); //static inline HRESULT LzmaDecoderFlush() { return OutWindowFlush(); } HRESULT LzmaDecoderCodeReal( LzmaDecoder *lzmaDecoder, // ISequentialInStream *in_stream, UINT64 *anInSize, // WindowOut *out_window, UINT64 *anOutSize); void LzmaDecoderConstructor( LzmaDecoder *lzmaDecoder ); HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize); HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder ); HRESULT LzmaDecoderSetDictionarySize(LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize); HRESULT LzmaDecoderSetLiteralProperties(LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); HRESULT LzmaDecoderSetPosBitsProperties(LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits); #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/LenCoder.h ================================================ #ifndef __LENCODER_H #define __LENCODER_H #include "BitTreeCoder.h" #define kNumPosStatesBitsMax 4 #define kNumPosStatesMax 16 #define kNumPosStatesBitsEncodingMax 4 #define kNumPosStatesEncodingMax 16 //#define kNumMoveBits 5 #define kNumLenBits 3 #define kNumLowSymbols (1 << kNumLenBits) #define kNumMidBits 3 #define kNumMidSymbols (1 << kNumMidBits) #define kNumHighBits 8 #define kNumSymbolsTotal (kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits)) typedef struct LenDecoder { CBitDecoder m_Choice; CBitDecoder m_Choice2; CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; CBitTreeDecoder m_HighCoder; UINT32 m_NumPosStates; } LenDecoder; INLINE void LenDecoderCreate(LenDecoder *lenCoder, UINT32 aNumPosStates) { lenCoder->m_NumPosStates = aNumPosStates; } INLINE void LenDecoderInit(LenDecoder *lenCoder) { UINT32 aPosState; BitDecoderInit(&lenCoder->m_Choice); for (aPosState = 0; aPosState < lenCoder->m_NumPosStates; aPosState++) { BitTreeDecoderInit(&lenCoder->m_LowCoder[aPosState],kNumLenBits); BitTreeDecoderInit(&lenCoder->m_MidCoder[aPosState],kNumMidBits); } BitTreeDecoderInit(&lenCoder->m_HighCoder,kNumHighBits); BitDecoderInit(&lenCoder->m_Choice2); } INLINE UINT32 LenDecode(ISequentialInStream *in_stream, LenDecoder *lenCoder, CRangeDecoder *aRangeDecoder, UINT32 aPosState) { if(BitDecode(in_stream, &lenCoder->m_Choice, aRangeDecoder) == 0) return BitTreeDecode(in_stream, &lenCoder->m_LowCoder[aPosState],aRangeDecoder); else { UINT32 aSymbol = kNumLowSymbols; if(BitDecode(in_stream, &lenCoder->m_Choice2, aRangeDecoder) == 0) aSymbol += BitTreeDecode(in_stream, &lenCoder->m_MidCoder[aPosState],aRangeDecoder); else { aSymbol += kNumMidSymbols; aSymbol += BitTreeDecode(in_stream, &lenCoder->m_HighCoder,aRangeDecoder); } return aSymbol; } } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/LiteralCoder.h ================================================ #ifndef __LITERALCODER_H #define __LITERALCODER_H #include "AriBitCoder.h" #include "RCDefs.h" //BRCM modification start // Duplication of malloc/free redirection macros from the two header files // namely, BitTreeCoder.h and LiteralCoder.h, were moved to a single // implementation in RCDefs.h that is included by both the above header files. //BRCM modification end //#define kNumMoveBits 5 typedef struct LitDecoder2 { CBitDecoder m_Decoders[3][1 << 8]; } LitDecoder2; INLINE void LitDecoder2Init(LitDecoder2 *litDecoder2) { int i, j; for (i = 0; i < 3; i++) for (j = 1; j < (1 << 8); j++) BitDecoderInit(&litDecoder2->m_Decoders[i][j]); } INLINE BYTE LitDecoder2DecodeNormal(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder) { UINT32 aSymbol = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; do { RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) } while (aSymbol < 0x100); aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } INLINE BYTE LitDecoder2DecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder, BYTE aMatchByte) { UINT32 aSymbol = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; do { UINT32 aBit; UINT32 aMatchBit = (aMatchByte >> 7) & 1; aMatchByte <<= 1; RC_GETBIT2(kNumMoveBits, litDecoder2->m_Decoders[1 + aMatchBit][aSymbol], aSymbol, aBit = 0, aBit = 1) if (aMatchBit != aBit) { while (aSymbol < 0x100) { RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) } break; } } while (aSymbol < 0x100); aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } typedef struct LitDecoder { LitDecoder2 *m_Coders; UINT32 m_NumPrevBits; UINT32 m_NumPosBits; UINT32 m_PosMask; } LitDecoder; // LitDecoder(): m_Coders(0) {} // ~LitDecoder() { Free(); } /* INLINE void LitDecoderFree(LitDecoder *litDecoder) { free( (char *) litDecoder->m_Coders ); litDecoder->m_Coders = 0; } */ INLINE void LitDecoderCreate(LitDecoder *litDecoder, UINT32 aNumPosBits, UINT32 aNumPrevBits) { // LitDecoderFree(litDecoder); UINT32 aNumStates; litDecoder->m_NumPosBits = aNumPosBits; litDecoder->m_PosMask = (1 << aNumPosBits) - 1; litDecoder->m_NumPrevBits = aNumPrevBits; aNumStates = 1 << (aNumPrevBits + aNumPosBits); litDecoder->m_Coders = (LitDecoder2*) malloc( sizeof( LitDecoder2 ) * aNumStates ); //printf("malloc in LitDecoderCreate=%d\n",sizeof( LitDecoder2 ) * aNumStates); if (litDecoder->m_Coders == 0) printf( "Error allocating memory for LitDecoder m_Coders!\n" ); } INLINE void LitDecoderInit(LitDecoder *litDecoder) { UINT32 i; UINT32 aNumStates = 1 << (litDecoder->m_NumPrevBits + litDecoder->m_NumPosBits); for (i = 0; i < aNumStates; i++) LitDecoder2Init(&litDecoder->m_Coders[i]); } INLINE UINT32 LitDecoderGetState(LitDecoder *litDecoder, UINT32 aPos, BYTE aPrevByte) { return ((aPos & litDecoder->m_PosMask) << litDecoder->m_NumPrevBits) + (aPrevByte >> (8 - litDecoder->m_NumPrevBits)); } INLINE BYTE LitDecodeNormal(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) { return LitDecoder2DecodeNormal(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder); } INLINE BYTE LitDecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) { return LitDecoder2DecodeWithMatchByte(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder, aMatchByte); } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/Makefile ================================================ BSPOBJS += \ 7zlzma.o \ LZMADecoder.o \ IInOutStreams.o \ ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/Portable.h ================================================ #ifndef __PORTABLE_H #define __PORTABLE_H //BRCM modification #ifdef _HOST_TOOL #include #endif #ifdef _CFE_ #include #endif #ifdef __KERNEL__ #include #endif //bcm //#ifdef __GNUC__ //#include //#define INLINE static inline //#else typedef char INT8; typedef unsigned char UINT8; typedef short INT16; typedef unsigned short UINT16; typedef int INT32; typedef unsigned int UINT32; typedef int BOOL; #define INLINE static inline //#define INLINE static __inline__ //#endif typedef long long INT64; // %%%% Changed from "long long" typedef unsigned long long UINT64; // %%%% Changed from "long long" typedef UINT8 BYTE; typedef UINT16 WORD; typedef UINT32 DWORD; typedef unsigned UINT_PTR; #define FALSE 0 #define TRUE 1 #define HRESULT int #define S_OK 0 #define E_INVALIDARG -1 #define E_OUTOFMEMORY -2 #define E_FAIL -3 #define E_INTERNAL_ERROR -4 #define E_INVALIDDATA -5 #define MyMin( a, b ) ( a < b ? a : b ) #define MyMax( a, b ) ( a > b ? a : b ) #define kNumMoveBits 5 #define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/RCDefs.h ================================================ #ifndef __RCDEFS_H #define __RCDEFS_H #include "AriBitCoder.h" /* BRCM modification start */ #ifdef _HOST_TOOL #include "stdio.h" #include "stdlib.h" #include "malloc.h" #endif #ifdef _CFE_ #include "lib_malloc.h" #include "lib_printf.h" #define malloc(x) KMALLOC(x, 0) #define free(x) KFREE(x) #endif #ifdef __KERNEL__ #include #include #include #define printf printk /* * BRCM Note: * * Typically the LitDecoder2 object m_Coders is very large e.g. 24576 bytes, * and kmalloc can fail if there is no contiguous space. All other dynamic * memory allocations in lzma's usage are very small. If vmalloc is used * we would use up (2*4K + 32 + 32) bytes per invocation. When memory is * in short supply, e.g. during an upload we typically require over 158Kbytes * when 28K would have sufficed if kmalloc was used for smaller sizes. * */ INLINE void * lzma_malloc(unsigned long sz) { if ( sz > 1024 ) { // printf("lzma_malloc -> vmalloc( %lu )\n", sz ); return (void*) vmalloc(sz); } else { // printf("lzma_malloc -> kmalloc( %lu )\n", sz ); return kmalloc(sz, GFP_KERNEL); } } INLINE void lzma_free(void * blk_p) { /* if kseg0 kernel cached memory | kseg1 kernel uncached memory */ if ( ((unsigned int)blk_p < (unsigned int) 0xC0000000) && ((unsigned int)blk_p >= (unsigned int) 0x80000000)) { // printf("lzma_free -> kfree( 0x%08x )\n", (int) blk_p); kfree(blk_p); } else /* kseg2 vmalloc | kuseg malloc */ { // printf("lzma_free -> vfree( 0x%08x )\n", (int) blk_p); vfree(blk_p); } } #define malloc(x) lzma_malloc(x) #define free(x) lzma_free(x) #endif /* BRCM modification end */ /* #define RC_INIT_VAR \ UINT32 aRange = aRangeDecoder->m_Range; \ UINT32 aCode = aRangeDecoder->m_Code; #define RC_FLUSH_VAR \ aRangeDecoder->m_Range = aRange; \ aRangeDecoder->m_Code = aCode; */ #if 1 #define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ {UINT32 aNewBound = (aRange >> kNumBitModelTotalBits) * aProb; \ if (aCode < aNewBound) \ { \ Action0; \ aRange = aNewBound; \ aProb += (kBitModelTotal - aProb) >> aNumMoveBits; \ aModelIndex <<= 1; \ } \ else \ { \ Action1; \ aRange -= aNewBound; \ aCode -= aNewBound; \ aProb -= (aProb) >> aNumMoveBits; \ aModelIndex = (aModelIndex << 1) + 1; \ }} \ if (aRange < kTopValue) \ { \ aCode = (aCode << 8) | InStreamReadByte(in_stream); \ aRange <<= 8; } #define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/RangeCoder.h ================================================ #ifndef __COMPRESSION_RANGECODER_H #define __COMPRESSION_RANGECODER_H #include "IInOutStreams.h" #define kNumTopBits 24 #define kTopValue (1 << kNumTopBits) typedef struct CRangeDecoder { UINT32 m_Range; UINT32 m_Code; } CRangeDecoder; INLINE void RangeDecoderInit( ISequentialInStream *in_stream, CRangeDecoder *rangeDecoder) { int i; rangeDecoder->m_Code = 0; rangeDecoder->m_Range = (UINT32)(-1); for(i = 0; i < 5; i++) rangeDecoder->m_Code = (rangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); } INLINE UINT32 RangeDecodeDirectBits( ISequentialInStream *in_stream, CRangeDecoder *rangeDecoder, UINT32 aNumTotalBits) { UINT32 aRange = rangeDecoder->m_Range; UINT32 aCode = rangeDecoder->m_Code; UINT32 aResult = 0; UINT32 i; for (i = aNumTotalBits; i > 0; i--) { UINT32 t; aRange >>= 1; t = (aCode - aRange) >> 31; aCode -= aRange & (t - 1); aResult = (aResult << 1) | (1 - t); if (aRange < kTopValue) { aCode = (aCode << 8) | InStreamReadByte(in_stream); aRange <<= 8; } } rangeDecoder->m_Range = aRange; rangeDecoder->m_Code = aCode; return aResult; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/WindowOut.h ================================================ #ifndef __STREAM_WINDOWOUT_H #define __STREAM_WINDOWOUT_H #include "IInOutStreams.h" typedef struct WindowOut { BYTE *Buffer; UINT32 Pos; } WindowOut; extern WindowOut out_window; #define OutWindowInit() \ { \ out_window.Buffer = (BYTE *) out_stream.data; \ out_window.Pos = 0; \ } #define OutWindowFlush() \ { \ OutStreamSizeSet( out_window.Pos ); \ } // BRCM modification INLINE void OutWindowCopyBackBlock(UINT32 aDistance, UINT32 aLen) { BYTE *p = out_window.Buffer + out_window.Pos; UINT32 i; aDistance++; for(i = 0; i < aLen; i++) p[i] = p[i - aDistance]; out_window.Pos += aLen; } #define OutWindowPutOneByte(aByte) \ { \ out_window.Buffer[out_window.Pos++] = aByte; \ } #define OutWindowGetOneByte(anIndex) \ (out_window.Buffer[out_window.Pos + anIndex]) #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/lzma/decompress/vxTypesOld.h ================================================ /* vxTypesOld.h - old VxWorks type definition header */ /* Copyright 1984-1997 Wind River Systems, Inc. */ /* modification history -------------------- 02c,15aug97,cym added simnt support. 02d,26mar97,cdp added Thumb (ARM7TDMI_T) support. 02c,28nov96,cdp added ARM support. 02b,28sep95,ms removed "static __inline__" (SPR #4500) 02b,12jul95,ism added simsolaris support 02a,19mar95,dvs removed tron references. 01z,01sep94,ism fixed comment as per SPR# 1512. 01y,02dec93,pme added Am29K family support. 01x,12jun93,rrr vxsim. 02a,26may94,yao added PPC support. 01w,09jun93,hdn added support for I80X86 01v,12feb93,srh added C++ versions of FUNCPTR, et al. 01u,13nov92,dnw added definition of VOID (SPR #1781) 01t,02oct92,srh replaced conditional around volatile, const, and signed so they won't be elided when __STDC__ is defined. added __cplusplus to __STDC__ condition. 01s,22sep92,rrr added support for c++ 01r,08sep92,smb made some additions for the MIPS. 01q,07sep92,smb added __STDC__ and modes to maintain compatibility with 5.0 01p,07jul92,rrr moved STACK_GROW and ENDIAN to vxArch.h 01o,03jul92,smb changed name from vxTypes.h. 01n,26may92,rrr the tree shuffle 01m,25nov91,llk included sys/types.h. 01l,04oct91,rrr passed through the ansification filter -fixed #else and #endif -removed TINY and UTINY -changed VOID to void -changed ASMLANGUAGE to _ASMLANGUAGE -changed copyright notice 01k,01oct91,jpb fixed MIPS conditional for undefined CPU_FAMILY. 01j,20sep91,wmd conditionalized out defines for const, unsigned and volatile for the MIPS architecture. 01i,02aug91,ajm added support for MIPS_R3k. 01h,15may91,gae added define for "signed" when not available for pre-ANSI. 01g,29apr91,hdn added defines and macros for TRON architecture. 01f,28apr91,del added defines of __volatile__ and __const__ if !_STDC_ && _GNUC__ 01f,24mar91,del added INSTR * define for I960. 01e,28jan91,kdl added DBLFUNCPTR and FLTFUNCPTR. 01d,25oct90,dnw changed void to void except when linting. 01c,05oct90,shl added copyright notice. made #endif ANSI style. 01b,10aug90,dnw added VOIDFUNCPTR 01a,29may90,del written. */ /* DESCRIPTION This header file contains a mixture of stuff. 1) the old style typedefs (ie. POSIX now says they must end with _t). These will be phased out gradually. 2) a mechanism for getting rid of const warning which are produced by the GNU C compiler. Hopefully, this will be removed in the future. 3) macros that are so longer needed for vxWorks source code but maybe needed by some customer applications and are therefore provided for backward compatability. 4) system III typedefs (used by netinet) which do not fit in anywhere else. */ #ifndef __INCvxTypesOldh #define __INCvxTypesOldh #ifdef __cplusplus extern "C" { #endif #include "sys/types.h" /* vxWorks types */ typedef char INT8; typedef short INT16; typedef int INT32; typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; typedef int BOOL; typedef int STATUS; typedef int ARGINT; typedef void VOID; #ifdef __cplusplus typedef int (*FUNCPTR) (...); /* ptr to function returning int */ typedef void (*VOIDFUNCPTR) (...); /* ptr to function returning void */ typedef double (*DBLFUNCPTR) (...); /* ptr to function returning double*/ typedef float (*FLTFUNCPTR) (...); /* ptr to function returning float */ #else typedef int (*FUNCPTR) (); /* ptr to function returning int */ typedef void (*VOIDFUNCPTR) (); /* ptr to function returning void */ typedef double (*DBLFUNCPTR) (); /* ptr to function returning double*/ typedef float (*FLTFUNCPTR) (); /* ptr to function returning float */ #endif /* _cplusplus */ /* This structure and the following definitions are needed to get rid of const warning produced by the GNU C compiler. */ #if defined(__STDC__) || defined(__cplusplus) typedef union { long pm_int; void *pm_v; const void *pm_cv; char *pm_c; unsigned char *pm_uc; signed char *pm_sc; const char *pm_cc; const unsigned char *pm_cuc; const signed char *pm_csc; short *pm_s; ushort_t *pm_us; const short *pm_cs; const ushort_t *pm_cus; int *pm_i; uint_t *pm_ui; const int *pm_ci; const uint_t *pm_cui; long *pm_l; ulong_t *pm_ul; const long *pm_cl; const ulong_t *pm_cul; int8_t *pm_i8; uint8_t *pm_ui8; const int8_t *pm_ci8; const uint8_t *pm_cui8; int16_t *pm_i16; uint16_t *pm_ui16; const int16_t *pm_ci16; const uint16_t *pm_cui16; int32_t *pm_i32; uint32_t *pm_ui32; const int32_t *pm_ci32; const uint32_t *pm_cui32; #if _ARCH_MOVE_SIZE > 4 int64_t *pm_i64; const int64_t *pm_ci64; #if _ARCH_MOVE_SIZE > 8 int128_t *pm_i128; const int128_t *pm_ci128; #endif #endif } pointer_mix_t; #define CHAR_FROM_CONST(x) (char *)(x) #define VOID_FROM_CONST(x) (void *)(x) #endif /* __STDC__ */ #define STACK_DIR _ARCH_STACK_DIR #define ALIGN_MEMORY _ARCH_ALIGN_MEMORY #define ALIGN_STACK _ARCH_ALIGN_STACK #define ALIGN_REGS _ARCH_ALIGN_REGS #define NBBY 8 /* number of bits in a byte */ /* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */ #define READ 0 #define WRITE 1 #define UPDATE 2 /* Select uses bit masks of file descriptors in longs. * These macros manipulate such bit fields (the filesystem macros use chars). * FD_SETSIZE may be defined by the user, but the default here * should be >= maxFiles parameter in iosInit call found in usrConfig.c. * If this define is changed, recompile the source, or else select() will * not work. */ #ifndef FD_SETSIZE #define FD_SETSIZE 256 #endif /* FD_SETSIZE */ typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ #ifndef howmany #define howmany(x, y) ((unsigned int)(((x)+((y)-1)))/(unsigned int)(y)) #endif /* howmany */ typedef struct fd_set { fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; } fd_set; #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) /* system III typedefs (used by netinet) */ typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short ushort; /* historical definitions - now obsolete */ typedef char TBOOL; /* obsolete */ /* architecture dependent typedefs */ #ifdef CPU_FAMILY #if CPU_FAMILY==MC680X0 typedef unsigned short INSTR; /* word-aligned instructions */ #endif /* CPU_FAMILY==MC680X0 */ #if CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS */ #if CPU_FAMILY==I960 typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==I960 */ #if CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT typedef unsigned char INSTR; /* char instructions */ #endif /* CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT */ #if CPU_FAMILY==AM29XXX typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==AM29XXX */ #if (CPU_FAMILY==PPC) typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* (CPU_FAMILY==PPC) */ #if CPU_FAMILY==ARM #if CPU==ARM7TDMI_T typedef unsigned short INSTR; /* 16 bit instructions */ #else typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif #endif /* CPU_FAMILY==ARM */ #endif /* CPU_FAMILY */ /* ANSI type qualifiers */ #if !defined(__STDC__) && !defined(__cplusplus) #ifdef __GNUC__ #define volatile __volatile__ #define const __const__ #define signed __signed__ #else #if !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) #define volatile #define const #define signed #endif /* !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) */ #endif /* __GNUC__ */ #endif /* !defined(__STDC__) && !defined(__cplusplus) */ #if CPU_FAMILY==MIPS #define CHAR_FROM_CONST(x) (char *)(x) #define VOID_FROM_CONST(x) (void *)(x) #endif #ifdef __cplusplus } #endif #endif /* __INCvxTypesOldh */ ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/Makefile ================================================ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@ mksquashfs.o: mksquashfs.c mksquashfs.h read_fs.o: read_fs.c read_fs.h sort.o: sort.c ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __MACOSX__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include #include #include #include "mksquashfs.h" #include /* BRCM begin */ #include #include "7zapi.h" /* BRCM end */ /* Exit codes used by mkfs-type programs */ #define MKFS_OK 0 /* No errors */ #define MKFS_ERROR 8 /* Operational error */ #define MKFS_USAGE 16 /* Usage or syntax error */ #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { if(!silent) printf("mksquashfs: "s, ## args); } while(0) #define ERROR(s, args...) do { fprintf(stderr, s, ## args); } while(0) #define EXIT_MKSQUASHFS() do { if(restore)\ restorefs();\ exit(1); } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) /* the GNU C library has a wonderful scanf("%as", string) which will allocate the string with the right size, good to avoid buffer overruns. the following macros use it if available or use a hacky workaround... */ #ifdef __GNUC__ #define SCANF_PREFIX "a" #define SCANF_STRING(s) (&s) #define GETCWD_SIZE 0 #else #define SCANF_PREFIX "511" #define SCANF_STRING(s) (s = xmalloc(512)) #define GETCWD_SIZE -1 inline int snprintf(char *str, size_t n, const char *fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = vsprintf(str, fmt, ap); va_end(ap); return ret; } #endif static FILE *devtable = NULL; int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int total_compressed = 0, total_uncompressed = 0; int fd; /* superblock attributes */ int noI = 0, noD = 0, check_data = 0, block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; /* write position within data section */ unsigned int bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* in memory directory header */ struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; squashfs_dir_header *entry_count_p; }; struct file_info *dupl[65536], *frag_dups[65536]; int dup_files = 0; int swap, silent = TRUE; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; static char *fragment_data; static int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; /* list of source dirs/files */ int source = 0; char **source_path; char dev_path[1024]; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; }; /* in memory file info */ struct file_info { unsigned int bytes; unsigned short checksum; unsigned int start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; unsigned short fragment_checksum; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; unsigned int sbytes, sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count, sfile_count, ssym_count, sdev_count, sdir_count, sdup_files; int sfragments; int restore = 0; /*flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; long long global_uid = -1, global_gid = -1; /* structure to used to pass in a pointer or an integer * to duplicate buffer read helper functions. */ struct duplicate_buffer_handle { unsigned char *ptr; unsigned int start; }; struct old_root_entry_info *old_root_entry; void add_old_root_entry(char *name, squashfs_inode inode, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **inode_table, int *inode_bytes, char **data_cache, int *cache_bytes, int *cache_size, char **directory_table, int *directory_bytes, char **directory_data_cache, int *directory_cache_bytes, int *directory_cache_size, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table); squashfs_inode get_sorted_inode(struct stat *buf); int read_sort_file(char *filename, int source, char *source_path[]); void sort_files_and_write(int source, char *source_path[]); struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes); #define FALSE 0 #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) /* BRCM begin */ #define LZMA 0 #define GZIP 1 int compress_algorithm = LZMA; /* BRCM end */ static void verror_msg(const char *s, va_list p) { fflush(stdout); fprintf(stderr, "mkcramfs: "); vfprintf(stderr, s, p); } static void vperror_msg(const char *s, va_list p) { int err = errno; if (s == 0) s = ""; verror_msg(s, p); if (*s) s = ": "; fprintf(stderr, "%s%s\n", s, strerror(err)); } static void perror_msg(const char *s, ...) { va_list p; va_start(p, s); vperror_msg(s, p); va_end(p); } static void error_msg_and_die(const char *s, ...) { va_list p; va_start(p, s); verror_msg(s, p); va_end(p); putc('\n', stderr); exit(MKFS_ERROR); } static void perror_msg_and_die(const char *s, ...) { va_list p; va_start(p, s); vperror_msg(s, p); va_end(p); exit(MKFS_ERROR); } static FILE *xfopen(const char *path, const char *mode) { FILE *fp; if ((fp = fopen(path, mode)) == NULL) perror_msg_and_die("%s", path); return fp; } void restorefs() { ERROR("Exiting - restoring original filesystem!\n\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(interrupted == 1) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); interrupted ++; } } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; /* BRCM begin */ if (compress_algorithm == GZIP) { c_byte = block_size << 1; if(!uncompressed && (res = compress2(d, &c_byte, s, size, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); return 0; } } if (compress_algorithm == LZMA) { unsigned lzma_algo; unsigned lzma_dictsize; unsigned lzma_fastbytes; int opt_compression_level = 1; c_byte = block_size << 3; switch (opt_compression_level) { case 1 : lzma_algo = 1; lzma_dictsize = 1 << 20; lzma_fastbytes = 64; break; case 2 : lzma_algo = 2; lzma_dictsize = 1 << 22; lzma_fastbytes = 128; break; case 3 : lzma_algo = 2; lzma_dictsize = 1 << 24; lzma_fastbytes = 255; break; default : BAD_ERROR("Invalid LZMA compression level. Must be 1,2,3."); return 0; } if(!uncompressed && !(res = compress_lzma_7zapi((const unsigned char*)s, (unsigned)size, (unsigned char*)d, (unsigned *)&c_byte, lzma_algo, lzma_dictsize, lzma_fastbytes))) { /* this should NEVER happen */ BAD_ERROR("Internal error - LZMA compression failed.\n"); return 0; } //printf("LZMA: block_size=%d, in_size=%d, out_size=%d\n", block_size, size, c_byte); } /* BRCM end */ if(uncompressed || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy((void *) (inode_table + inode_bytes), (void *) &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, unsigned int byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } } void write_bytes(int fd, unsigned int byte, int bytes, char *buff) { off_t off = byte; if(off + bytes > ((long long)1<<32) - 1 ) BAD_ERROR("Filesystem greater than maximum size 2^32 - 1\n"); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } } unsigned int write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; unsigned int start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy((void *) (inode_table + inode_bytes), (void *) &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } unsigned int write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; unsigned int start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy((void *) (directory_table + directory_bytes), (void *) &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } squashfs_inode create_inode(char *filename, int type, int byte_size, squashfs_block start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct stat* devtable_inode_info) { squashfs_inode i_no; struct stat buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; if(filename[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); } else /* We set st_mode different than 0 for all files in the device table list. ** That is how we "recognize" that the file is from the device table list. ** For files not in the table list st_mode is initially set to 0 and ** then reinitialized using lstat */ if ( devtable_inode_info != NULL && devtable_inode_info->st_mode != 0 ) { buf.st_mode = devtable_inode_info->st_mode; buf.st_rdev = devtable_inode_info->st_rdev; buf.st_uid = devtable_inode_info->st_uid; buf.st_gid = devtable_inode_info->st_gid; buf.st_mtime = time(NULL);; } else if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); return SQUASHFS_INVALID; } base->mode = SQUASHFS_MODE(buf.st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf.st_gid : global_gid); if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; /* CONFIG_MIPS_BRCM Begin Broadcom changed code. */ /* GCC4.0 does not like two assigns and a cast in one line. Split them up. */ inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; /* CONFIG_MIPS_BRCM end Broadcom changed code. */ reg->mtime = buf.st_mtime; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy((void *) inodep, (void *) reg, sizeof(*reg)); memcpy((void *) inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %x, blocks %d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->mtime = buf.st_mtime; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; if(!swap) memcpy((void *) inode, (void *) dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %x, offset %x\n", byte_size, start_block, offset); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->rdev = (unsigned short) ((major(buf.st_rdev) << 8) | (minor(buf.st_rdev) & 0xff)); if(!swap) memcpy((void *) inode, (void *) dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x\n", dev->rdev); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return SQUASHFS_INVALID; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return SQUASHFS_INVALID; } /* CONFIG_MIPS_BRCM Begin Broadcom changed code. */ /* GCC4.0 does not like two assigns and a cast in one line. Split them up. */ inode = get_inode(sizeof(*symlink) + byte); inodep = (squashfs_symlink_inode_header *) inode; /* CONFIG_MIPS_BRCM end Broadcom changed code. */ symlink->symlink_size = byte; if(!swap) memcpy((void *) inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d\n", byte); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); if(!swap) memcpy((void *) inode, (void *) ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket"); } else return SQUASHFS_INVALID; i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%Lx, type %d, uid %d, guid %d\n", i_no, type, base->uid, base->guid); return i_no; } void init_dir(struct directory *dir) { if((dir->buff = (char *)malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; } void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir) { char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + 6 >= dir->buff + dir->size) { if((buff = (char *) realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (squashfs_dir_header *) (((unsigned char *) dir->entry_count_p) - dir->buff + buff); dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block) { if(dir->entry_count_p) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; if(!swap) memcpy((void *) dir->entry_count_p, (void *) &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), dir->entry_count_p); } dir->entry_count_p = (squashfs_dir_header *) dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; if(!swap) memcpy((void *) idirp, (void *) &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } squashfs_inode write_dir(char *filename, struct directory *dir) { squashfs_inode inode; unsigned int dir_size; int data_space; unsigned short c_byte; while(directory_cache_bytes >= SQUASHFS_METADATA_SIZE) { if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy((void *) directory_table + directory_bytes, (void *) &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } dir_size = dir->p - dir->buff; data_space = (directory_cache_size - directory_cache_bytes); if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; if(!swap) memcpy((void *) dir->entry_count_p, (void *) &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } inode = create_inode(filename, SQUASHFS_DIR_TYPE, dir_size, directory_bytes, directory_cache_bytes, NULL, NULL, NULL); directory_cache_bytes += dir_size; #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%Lx\n", inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return inode; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment) { if(fragment->index == fragments || fragment->index == SQUASHFS_INVALID_BLK) return fragment_data + fragment->offset; else { squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index]; int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size), res; long bytes = block_size; if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress(buffer, &bytes, (const char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); return buffer + fragment->offset; } } void write_fragment() { int compressed_size; unsigned char buffer[block_size << 1]; if(fragment_size == 0) return; if(fragments % FRAG_SIZE == 0) if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) BAD_ERROR("Out of memory in fragment table\n"); fragment_table[fragments].size = mangle(buffer, fragment_data, fragment_size, block_size, noF, 1); fragment_table[fragments].start_block = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[fragments].size); write_bytes(fd, bytes, compressed_size, buffer); bytes += compressed_size; total_uncompressed += fragment_size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n",fragments, fragment_size, compressed_size); fragments ++; fragment_size = 0; } static struct fragment empty_fragment = {SQUASHFS_INVALID_BLK, 0, 0}; struct fragment *get_and_fill_fragment(char *buff, int size) { struct fragment *ffrg; if(size == 0) return &empty_fragment; if(fragment_size + size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = size; memcpy(fragment_data + fragment_size, buff, size); fragment_size += size; return ffrg; } unsigned int write_fragment_table() { unsigned int start_bytes, frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments), meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; unsigned short c_byte; int i, compressed_size; squashfs_fragment_index list[meta_blocks]; TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %x, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy((void *) p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } for(i = 0; i < meta_blocks; i++) { int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0); if(!swap) memcpy((void *) cbuffer, (void *) &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { squashfs_fragment_index slist[meta_blocks]; SQUASHFS_SWAP_FRAGMENT_INDEXES(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); return start_bytes; } unsigned char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { unsigned char *v = handle->ptr; handle->ptr += avail_bytes; return v; } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; unsigned char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer); handle->start += avail_bytes; return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, int l) { unsigned short chksum = 0; unsigned int bytes = 0; unsigned char *b; struct duplicate_buffer_handle position = *handle; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; b = get_next_file_block(&position, bytes); while(bytes--) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } } return chksum; } static unsigned int cached_frag = -1; void add_file(int start, int file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; struct file_info *dupl_ptr; char *datap; struct duplicate_buffer_handle handle; if(!duplicate_checking) return; if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; if(cached_frag == fragment) datap = fragment_data + offset; else datap = get_fragment(fragment_data, frg); handle.start = start; if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL) dupl_ptr->fragment = frg; cached_frag = fragment; } struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes) { unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes); struct duplicate_buffer_handle handle = { frag_data, 0 }; unsigned short fragment_checksum = get_checksum(read_from_buffer, &handle, frag_bytes); struct file_info *dupl_ptr = bytes ? dupl[checksum] : frag_dups[fragment_checksum]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) { unsigned char buffer1[SQUASHFS_FILE_MAX_SIZE]; unsigned int dup_bytes = dupl_ptr->bytes, dup_start = dupl_ptr->start; struct duplicate_buffer_handle position = *file_start; unsigned char *buffer; while(dup_bytes) { int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes; buffer = get_next_file_block(&position, avail_bytes); read_bytes(fd, dup_start, avail_bytes, buffer1); if(memcmp(buffer, buffer1, avail_bytes) != 0) break; dup_bytes -= avail_bytes; dup_start += avail_bytes; } if(dup_bytes == 0) { char frag_buffer1[block_size]; char *fragment_buffer1 = get_fragment(frag_buffer1, dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%x, size %d, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->bytes = bytes; dupl_ptr->checksum = checksum; dupl_ptr->start = *start; dupl_ptr->fragment_checksum = fragment_checksum; if((dupl_ptr->block_list = (unsigned int *) malloc(blocks * sizeof(unsigned int))) == NULL) { BAD_ERROR("Out of memory allocating block_list\n"); } memcpy(dupl_ptr->block_list, *block_list, blocks * sizeof(unsigned int)); dup_files ++; if(bytes) { dupl_ptr->next = dupl[checksum]; dupl[checksum] = dupl_ptr; } else { dupl_ptr->next = frag_dups[fragment_checksum]; frag_dups[fragment_checksum] = dupl_ptr; } return dupl_ptr; } #define MINALLOCBYTES (1024 * 1024) squashfs_inode write_file(char *filename, long long size, int *duplicate_file) { unsigned int frag_bytes, file, start, file_bytes = 0, block = 0; unsigned int c_byte; long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; unsigned int blocks = (read_size + block_size - 1) >> block_log; unsigned int block_list[blocks], *block_listp = block_list; char buff[block_size], *c_buffer; int allocated_blocks = blocks, i, bbytes, whole_file = 1; struct fragment *fragment; struct file_info *dupl_ptr; struct duplicate_buffer_handle handle; if(!no_fragments && (read_size < block_size || always_use_fragments)) { allocated_blocks = blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if(size > read_size) ERROR("file %s truncated to %Ld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE); total_bytes += read_size; if((file = open(filename, O_RDONLY)) == -1) { perror("Error in opening file, skipping..."); return SQUASHFS_INVALID; } do { if((c_buffer = (char *) malloc((allocated_blocks + 1) << block_log)) == NULL) { TRACE("Out of memory allocating write_file buffer, allocated_blocks %d, blocks %d\n", allocated_blocks, blocks); whole_file = 0; if((allocated_blocks << (block_log - 1)) < MINALLOCBYTES) BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %d blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10)); allocated_blocks >>= 1; } } while(!c_buffer); for(start = bytes; block < blocks; file_bytes += bbytes) { for(i = 0, bbytes = 0; (i < allocated_blocks) && (block < blocks); i++) { int available_bytes = read_size - (block * block_size) > block_size ? block_size : read_size - (block * block_size); if(read(file, buff, available_bytes) == -1) goto read_err; c_byte = mangle(c_buffer + bbytes, buff, available_bytes, block_size, noD, 1); block_list[block ++] = c_byte; bbytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); } if(!whole_file) { write_bytes(fd, bytes, bbytes, c_buffer); bytes += bbytes; } } if(frag_bytes != 0) if(read(file, buff, frag_bytes) == -1) goto read_err; close(file); if(whole_file) { handle.ptr = c_buffer; if(duplicate_checking && (dupl_ptr = duplicate(read_from_buffer, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { *duplicate_file = TRUE; goto wr_inode; } write_bytes(fd, bytes, file_bytes, c_buffer); bytes += file_bytes; } else { handle.start = start; if(duplicate_checking && (dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { bytes = start; if(!block_device) ftruncate(fd, bytes); *duplicate_file = TRUE; goto wr_inode; } } fragment = get_and_fill_fragment(buff, frag_bytes); if(duplicate_checking) dupl_ptr->fragment = fragment; *duplicate_file = FALSE; wr_inode: free(c_buffer); file_count ++; return create_inode(filename, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); read_err: perror("Error in reading file, skipping..."); free(c_buffer); return SQUASHFS_INVALID; } struct linuxdir { DIR *linuxdir; char pathname[8192]; }; void *linux_opendir(char *pathname, struct directory *dir) { struct linuxdir *linuxdir; if((linuxdir = malloc(sizeof(struct linuxdir))) == NULL) return NULL; if((linuxdir->linuxdir = opendir(pathname)) == NULL) { free(linuxdir); return NULL; } strcpy(linuxdir->pathname, pathname); return (void *) linuxdir; } int linux_readdir(void *l, char *filename, char *dir_name, struct stat* devtable_inode_info) { struct dirent *d_name; struct linuxdir *linuxdir = (struct linuxdir *)l; devtable_inode_info->st_mode = 0; do { if((d_name = readdir(linuxdir->linuxdir)) == NULL) { if ( strncmp(linuxdir->pathname, dev_path, sizeof(linuxdir->pathname)) == 0 ) { if ( devtable_readdir(l, filename, dir_name, devtable_inode_info ) ) { return( TRUE ); } } return FALSE; } } while(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0); strcat(strcat(strcpy(filename, linuxdir->pathname), "/"), d_name->d_name); strcpy(dir_name, d_name->d_name); return TRUE; } void linux_closedir(void *linuxdir) { closedir(((struct linuxdir *)linuxdir)->linuxdir); free(linuxdir); } static int interpret_table_entry(char *line, char* filename, char* dirname, struct stat* devtable_inode_info) { char type, *name = NULL; char* full; unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0; unsigned long start = 0, increment = 1, count = 0; if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu", SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor, &start, &increment, &count) < 0) { return 1; } if (!strcmp(name, "/")) { error_msg_and_die("Device table entries require absolute paths"); } strcpy( filename, source_path[0] ); strcat( filename, name ); full = strdup( name ); strcpy( dirname, (char*)basename(full) ); free(full); switch (type) { case 'd': mode |= S_IFDIR; break; case 'f': mode |= S_IFREG; break; case 'p': mode |= S_IFIFO; break; case 'c': case 'b': mode |= (type == 'c') ? S_IFCHR : S_IFBLK; if (count > 0) { char *buf; unsigned long i; dev_t rdev; for (i = start; i < count; i++) { asprintf(&buf, "%s%lu", name, i); rdev = makedev(major, minor + (i * increment - start)); free(buf); devtable_inode_info->st_rdev = rdev; } } else { dev_t rdev = makedev(major, minor); devtable_inode_info->st_rdev = rdev; } break; default: error_msg_and_die("Unsupported file type"); } free(name); devtable_inode_info->st_mode = mode; return 0; } int devtable_readdir(void *l, char *filename, char *dir_name, struct stat* devtable_inode_info) { char *line; int status = FALSE; int commentLine = FALSE; size_t length = 0; strcpy(filename, ""); strcpy(dir_name, ""); /* Looks ok so far. The general plan now is to read in one * line at a time, check for leading comment delimiters ('#'), * then try and parse the line as a device table. If we fail * to parse things, try and help the poor fool to fix their * device table with a useful error msg... */ line = NULL; do { if (getline(&line, &length, devtable) != -1) { status = TRUE; /* First trim off any whitespace */ int len = strlen(line); /* trim trailing whitespace */ while (len > 0 && isspace(line[len - 1])) line[--len] = '\0'; /* trim leading whitespace */ memmove(line, &line[strspn(line, " \n\r\t\v")], len); /* How long are we after trimming? */ len = strlen(line); /* If this is NOT a comment line, try to interpret it */ if (len && *line != '#') { commentLine = FALSE; if (interpret_table_entry(line, filename, dir_name, devtable_inode_info)) status = FALSE; } else { commentLine = TRUE; continue; } free(line); line = NULL; } else { free(line); } } while (commentLine == TRUE); return status; } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } char encomp_pathname[8192]; int encomp_entry = 0; void *encomp_opendir(char *pathname, struct directory *dir) { int i; for(i = 0; i < old_root_entries; i++) add_dir(old_root_entry[i].inode, old_root_entry[i].name, old_root_entry[i].type, dir); return (void *)source_path; } int encomp_readdir(void *l, char *filename, char *dir_name, struct stat* devtable_inode_info) { char *basename; int n, pass = 1; devtable_inode_info->st_mode = 0; while(encomp_entry < source) { if((basename = getbase(source_path[encomp_entry])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[encomp_entry]); encomp_entry++; continue; } strcpy(filename, source_path[encomp_entry]); strcpy(dir_name, basename); for(;;) { for(n = 0; n < old_root_entries && strcmp(old_root_entry[n].name, dir_name) != 0; n++); if(n == old_root_entries) { add_old_root_entry(dir_name, 0, 0); encomp_entry++; return TRUE; } ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } } return FALSE; } void encomp_closedir(void *linuxdir) { } void *single_opendir(char *pathname, struct directory *dir) { encomp_opendir(pathname, dir); return linux_opendir(pathname, dir); } int single_readdir(void *l, char *filename, char *dir_name, struct stat* devtable_inode_info) { int i, pass = 1; char name[SQUASHFS_NAME_LEN + 1]; devtable_inode_info->st_mode = 0; if(linux_readdir(l, filename, dir_name, devtable_inode_info) == FALSE) return FALSE; strcpy(name, dir_name); for(;;) { for(i = 0; i < old_root_entries && strcmp(old_root_entry[i].name, dir_name) != 0; i++); if(i == old_root_entries) { add_old_root_entry(dir_name, 0, 0); return TRUE; } ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", name, pass++); ERROR("%s\n", dir_name); } } squashfs_inode dir_scan(char *pathname, void* (_opendir)(char *, struct directory *), int (_readdir)(void *, char *, char *, struct stat*), void (_closedir)(void *)) { void *linuxdir; struct stat buf; char filename[8192], dir_name[8192]; int squashfs_type; squashfs_inode inode = SQUASHFS_INVALID; struct directory dir; struct stat devtable_inode_info; unsigned long mode; devtable_inode_info.st_mode = 0; init_dir(&dir); if((linuxdir = _opendir(pathname, &dir)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(linuxdir, filename, dir_name, &devtable_inode_info) != FALSE) { mode = devtable_inode_info.st_mode; if ( devtable_inode_info.st_mode == 0 ) { if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } mode = buf.st_mode; } if(excluded(filename, &buf)) continue; switch(mode & S_IFMT) { case S_IFREG: { int duplicate_file; squashfs_type = SQUASHFS_FILE_TYPE; if(!sorted) { inode = write_file(filename, buf.st_size, &duplicate_file); INFO("file %s, uncompressed size %Ld bytes, %s\n", filename, buf.st_size, duplicate_file ? "DUPLICATE" : ""); } else inode = get_sorted_inode(&buf); break; } case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; inode = dir_scan(filename, linux_opendir, linux_readdir, linux_closedir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL, &devtable_inode_info); INFO("symbolic link %s inode 0x%Lx\n", dir_name, inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL, &devtable_inode_info); INFO("character device %s inode 0x%Lx\n", dir_name, inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL, &devtable_inode_info); INFO("block device %s inode 0x%Lx\n", dir_name, inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL, &devtable_inode_info); INFO("fifo %s inode 0x%Lx\n", dir_name, inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; inode = create_inode(filename, squashfs_type, 0, 0, 0, NULL, NULL, &devtable_inode_info); INFO("unix domain socket %s inode 0x%Lx\n", dir_name, inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, mode); continue; } if(inode != SQUASHFS_INVALID) add_dir(inode, dir_name, squashfs_type, &dir); } _closedir(linuxdir); inode = write_dir(pathname, &dir); INFO("directory %s inode 0x%Lx\n", pathname, inode); error: free(dir.buff); return inode; } unsigned int slog(unsigned int block) { int i; for(i = 9; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries++].type = type; } #define VERSION() \ printf("mksquashfs version 2.0\n");\ printf("copyright (C) 2004 Phillip Lougher (plougher@users.sourceforge.net)\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, delete = FALSE, keep_as_directory = FALSE, orig_be; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 512 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-D") == 0) { TRACE("-D passed as parameter\n"); if(++i == argc) { ERROR("%s: -D missing filename\n", argv[0]); exit(1); } TRACE("devTable filename = %s\n", argv[i]); devtable = xfopen(argv[i], "r"); if (fstat(fileno(devtable), &buf) < 0) perror_msg_and_die(argv[i]); if (buf.st_size < 10) ERROR("%s: not a proper device table file\n", argv[0]); } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; /* BRCM begin */ else if(strcmp(argv[i], "-gzip") == 0) compress_algorithm = GZIP; else if(strcmp(argv[i], "-lzma") == 0) compress_algorithm = LZMA; /* BRCM end */ else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude dirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("\t-info\t\t\t\tprint files written to filesystem\n"); ERROR("\t-sort sort file\t\t\tsort files according to priorities in sort file. One file or dir\n"); ERROR("\t\t\t\t\twith priority per line. Priority -32768 to 32767, default priority 0\n"); ERROR("\t-b block size\t\t\tsize of blocks in "); ERROR("filesystem, default %d\n", SQUASHFS_FILE_SIZE); ERROR("\t-noappend\t\t\tDo not append to existing filesystem on dest, write a new filesystem\n"); ERROR("\t\t\t\t\tThis is the default action if dest does not exist, or if no filesystem is on it\n"); ERROR("\t-keep-as-directory\t\tIf one source directory is specified, create a root directory\n"); ERROR("\t\t\t\t\tcontaining that directory, rather than the contents of the directory\n"); ERROR("\t-root-becomes name\t\tWhen appending source files/directories, make the original\n"); ERROR("\t\t\t\t\troot become a subdirectory in the new root called name, rather\n"); ERROR("\t\t\t\t\tthan adding the new source items to the original root\n"); ERROR("\t-noI -noInodeCompression\tdo not compress inode table\n"); ERROR("\t-noD -noDataCompression\t\tdo not compress data blocks\n"); ERROR("\t-noF -noFragmentCompression\tdo not compress fragment blocks\n"); ERROR("\t-no-duplicates\t\t\tdo not perform duplicate checking\n"); ERROR("\t-no-fragments\t\t\tdo not use fragments\n"); ERROR("\t-always-use-fragments\t\tuse fragment blocks for files larger than block size\n"); ERROR("\t-nopad\t\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("\t-check_data\t\t\tadd checkdata for greater filesystem checks\n"); ERROR("\t-le\t\t\t\tcreate a little endian filesystem\n"); ERROR("\t-be\t\t\t\tcreate a big endian filesystem\n"); /* BRCM begin */ ERROR("\t-gzip\t\t\t\tuse gzip compression\n"); ERROR("\t-lzma\t\t\t\tuse lzma compression(default)\n"); /* BRCM end */ ERROR("\t-ef exclude file\t\tfile is a list of exclude dirs/files - one per line\n"); ERROR("\t-all-root\t\t\toverride file uid/gid and make all file uid/gids owned by root\n"); ERROR("\t-root-owned\t\t\talternative name for -all-root\n"); ERROR("\t-force-uid uid\t\t\tset all file uids to uid\n"); ERROR("\t-force-gid gid\t\t\tset all file gids to gid\n"); ERROR("\t-version\t\t\tprint version, licence and copyright message\n"); exit(1); } } if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { if(S_ISREG(buf.st_mode)) { /* reopen truncating file */ close(fd); if((fd = open(argv[source + 1], O_TRUNC | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } delete = TRUE; } } } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); exit(1); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); exit(1); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if((fragment_data = (char *) malloc(block_size)) == NULL) BAD_ERROR("Out of memory allocating fragment_data"); if(delete) { printf("Creating %s filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); fragments = SQUASHFS_INVALID_BLK; if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &inode_bytes, &data_cache, &cache_bytes, &cache_size, &directory_table, &directory_bytes, &directory_data_cache, &directory_cache_bytes, &directory_cache_size, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, add_old_root_entry, &fragment_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); exit(1); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s squashfs filesystem on %s, block size %d\n", be ? "big endian" : "little endian", argv[source + 1], block_size); printf("All -be, -le, -b, -noI, noD, noF, -check_data, no-duplicates, no-fragments and always-use-fragments options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); inode_size = inode_bytes; directory_size = directory_bytes; /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; inode_count = file_count + dir_count + sym_count + dev_count; sdata_cache = (char *)malloc(scache_bytes = cache_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = directory_cache_size); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache, sdirectory_cache_bytes); sinode_bytes = inode_bytes; sdirectory_bytes = directory_bytes; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(stat(source_path[0], &buf) == -1) { perror("Cannot stat source directory"); EXIT_MKSQUASHFS(); } snprintf(dev_path, sizeof(dev_path), "%s/dev", source_path[0]); if(sorted) sort_files_and_write(source, source_path); if(delete && !keep_as_directory && source == 1 && S_ISDIR(buf.st_mode)) sBlk.root_inode = dir_scan(source_path[0], linux_opendir, linux_readdir, linux_closedir); else if(!keep_as_directory && source == 1 && S_ISDIR(buf.st_mode)) sBlk.root_inode = dir_scan(source_path[0], single_opendir, single_readdir, linux_closedir); else sBlk.root_inode = dir_scan("", encomp_opendir, encomp_readdir, encomp_closedir); sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); TRACE("sBlk->inode_table_start 0x%x\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%x\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%x\n", sBlk.fragment_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { unsigned char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ? "Big endian" : "Little endian", block_size, noI ? "uncompressed" : "compressed", noD ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } if(fd) close(fd); if(devtable) fclose(devtable); return 0; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, unsigned int, int, char *); extern int add_file(int, int, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifdef __MACOSX__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include "read_fs.h" #include #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) fprintf(stderr, s, ## args) int swap; int read_block(int fd, int start, int *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { unsigned char buffer[SQUASHFS_METADATA_SIZE]; int res; long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, int start, int end, int root_inode_start, squashfs_super_block *sBlk, squashfs_dir_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%x, end 0x%x, root_inode_start 0x%x\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%x containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%x\n", start); if((bytes += read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ bytes -= sizeof(squashfs_dir_inode_header); if(swap) { squashfs_dir_inode_header sinode; memcpy((void *)&sinode, (void *)(*inode_table + bytes), sizeof(*dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(dir_inode, &sinode); } else memcpy((void *)dir_inode, (void *)(*inode_table + bytes), sizeof(*dir_inode)); directory_start_block = dir_inode->start_block; for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy((void *)&sinode, (void *)cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy((void *)&inode, (void *)cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_BLK ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_BLK ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; int file_bytes = 0, i, start = inode.start_block; unsigned int block_list[blocks]; TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy((void *)sblock_list, (void *)cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy((void *)block_list, (void *)cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy((void *)&sinodep, (void *)cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy((void *)&inodep, (void *)cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy((void *)&sinode, (void *)cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy((void *)&dir_inode, (void *)cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); free(*inode_table); return FALSE; } } return files; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major == 1) ERROR("Filesystem on %s is a SQUASHFS 1.x filesystem. Appending\nto SQUASHFS 1.x filesystems is not supported. Please convert it to a SQUASHFS 2.0 filesystem...n", source); else ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d), I support (%d: <= %d)\n", source, sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid SQUASHFS superblock on %s.\n", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); printf("\tFilesystem size %d bytes\n", sBlk->bytes_used); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %x\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, int start, int offset, int size, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int bytes = 0, dir_count; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%x, bytes read so far %d\n", start, bytes); if((bytes += read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy((void *)&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy((void *)&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy((void *)&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy((void *)dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy((void *)dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->type); bytes += dire->size + 1; } } all_done: return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%x\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, int *inode_bytes, char **data_cache, int *cache_bytes, int *cache_size, char **cdirectory_table, int *directory_bytes, char **directory_data_cache, int *directory_cache_bytes, int *directory_cache_size, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table) { unsigned char *inode_table = NULL, *directory_table; unsigned int start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_directory_offset; squashfs_dir_inode_header inode; unsigned int files, root_inode_block; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, sBlk, &inode, &inode_table, &root_inode_block, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.inode_type == SQUASHFS_DIR_TYPE) { if((directory_table = squashfs_readdir(fd, !root_name, sBlk->directory_table_start + inode.start_block, inode.offset, inode.file_size, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } if((*cinode_table = (char *) malloc(root_inode_start - start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start - start, *cinode_table); if((*cdirectory_table = (char *) malloc(inode.start_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, inode.start_block, *cdirectory_table); *inode_bytes = root_inode_start - start; *directory_bytes = inode.start_block; root_inode_offset += sizeof(inode); root_directory_offset = inode.offset + inode.file_size; (*dir_count) ++; if(((*data_cache = (char *) malloc(root_inode_offset)) == NULL) || ((*directory_data_cache = (char *) malloc(root_directory_offset)) == NULL)) { ERROR("read_filesystem: failed to alloc inode/directory caches\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset); memcpy(*directory_data_cache, directory_table, root_directory_offset); *cache_size = root_inode_offset; *directory_cache_size = root_directory_offset; if(root_name) { push_directory_entry(root_name, sBlk->root_inode, SQUASHFS_DIR_TYPE); *cache_bytes = root_inode_offset; *directory_cache_bytes = root_directory_offset; } else { *cache_bytes = root_inode_offset - sizeof(inode); *directory_cache_bytes = inode.offset; } if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define INFO(s, args...) if(!silent) printf("mksquashfs: "s, ## args) #define ERROR(s, args...) fprintf(stderr, s, ## args) #define EXIT_MKSQUASHFS() exit(1) #define BAD_ERROR(s, args...) {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry { char *filename; long long size; ino_t st_ino; dev_t st_dev; struct priority_entry *next; }; struct priority_entry *priority_list[65536]; struct sorted_inode_entry { squashfs_inode inode; ino_t st_ino; dev_t st_dev; struct sorted_inode_entry *next; }; struct sorted_inode_entry *sorted_inode_list[65536]; extern int silent; extern int excluded(char *filename, struct stat *buf); extern squashfs_inode write_file(char *filename, long long size, int *c_size); int add_to_sorted_inode_list(squashfs_inode inode, dev_t st_dev, ino_t st_ino) { int hash = st_ino & 0xffff; struct sorted_inode_entry *new_sorted_inode_entry; if((new_sorted_inode_entry = malloc(sizeof(struct sorted_inode_entry))) == NULL) { ERROR("Out of memory allocating sorted inode entry\n"); return FALSE; } new_sorted_inode_entry->inode = inode; new_sorted_inode_entry->st_ino = st_ino; new_sorted_inode_entry->st_dev = st_dev; new_sorted_inode_entry->next = sorted_inode_list[hash]; sorted_inode_list[hash] = new_sorted_inode_entry; return TRUE; } squashfs_inode get_sorted_inode(struct stat *buf) { int hash = buf->st_ino & 0xffff; struct sorted_inode_entry *sorted_inode_entry; for(sorted_inode_entry = sorted_inode_list[hash]; sorted_inode_entry; sorted_inode_entry = sorted_inode_entry->next) if(buf->st_ino == sorted_inode_entry->st_ino && buf->st_dev == sorted_inode_entry->st_dev) break; if(sorted_inode_entry) return sorted_inode_entry->inode; else return (squashfs_inode) 0; } int add_priority_list(char *filename, struct stat *buf, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->filename = strdup(filename); new_priority_entry->size = buf->st_size; new_priority_entry->st_dev = buf->st_dev; new_priority_entry->st_ino = buf->st_ino; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i; char buffer[4096], filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", path); perror(buffer); return TRUE; } TRACE("adding filename %s, priority %d, st_dev %Lx, st_ino %Lx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf, priority); } return TRUE; } void generate_file_priorities(char *pathname, int priority, struct stat *buf) { char filename[8192]; DIR *linuxdir; struct dirent *d_name; priority = get_priority(pathname, buf, priority); if((linuxdir = opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); return; } while((d_name = readdir(linuxdir)) != NULL) { if(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0) continue; strcat(strcat(strcpy(filename, pathname), "/"), d_name->d_name); if(lstat(filename, buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, buf)) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(filename, buf, get_priority(filename, buf, priority)); break; case S_IFDIR: generate_file_priorities(filename, priority, buf); break; } } closedir(linuxdir); } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(int source, char *source_path[]) { struct stat buf; int i, c_size; struct priority_entry *entry; squashfs_inode inode; for(i = 0; i < source; i++) { if(lstat(source_path[i], &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", source_path[i]); perror(buffer); continue; } if(excluded(source_path[i], &buf)) continue; switch(buf.st_mode & S_IFMT) { case S_IFREG: add_priority_list(source_path[i], &buf, get_priority(source_path[i], &buf, 0)); break; case S_IFDIR: generate_file_priorities(source_path[i], 0, &buf); break; } } for(i = 0; i < 65536; i++) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->filename); inode = write_file(entry->filename, entry->size, &c_size); INFO("file %s, size %d bytes, inode 0x%Lx\n", entry->filename, c_size, inode); INFO("\t%.2f%% of uncompressed file size (%Ld bytes)\n", ((float) c_size / entry->size) * 100.0, entry->size); add_to_sorted_inode_list(inode, entry->st_dev, entry->st_ino); } } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_MAJOR 2 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #if defined(BUILD_SQUASH_HIGH) #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 #elif defined(BUILD_SQUASH_NORMAL) #define SQUASHFS_FILE_SIZE 32768 #define SQUASHFS_FILE_LOG 15 #define SQUASHFS_FILE_MAX_SIZE 32768 #elif defined(BUILD_SQUASH_LOW) #define SQUASHFS_FILE_SIZE 8192 #define SQUASHFS_FILE_LOG 13 #define SQUASHFS_FILE_MAX_SIZE 8192 #else #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 #endif /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_BLK ((long long) 0xffffffff) #define SQUASHFS_USED_BLK ((long long) 0xfffffffe) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking) (noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an uncompressed * offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A) << 16)\ + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ typedef unsigned int squashfs_fragment_index; #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index)) #define SQUASHFS_CACHED_FRAGMENTS 3 /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 32 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1)) #define SQUASHFS_MARKER_BYTE 0xff /* * definitions for structures on disk */ typedef unsigned int squashfs_block; typedef long long squashfs_inode; typedef unsigned int squashfs_uid; typedef struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used; unsigned int uid_start; unsigned int guid_start; unsigned int inode_table_start; unsigned int directory_table_start; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start; } __attribute__ ((packed)) squashfs_super_block; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)) squashfs_base_inode_header; typedef squashfs_base_inode_header squashfs_ipc_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)) squashfs_dev_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)) squashfs_symlink_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; squashfs_block start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; unsigned short block_list[0]; } __attribute__ ((packed)) squashfs_reg_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_inode_header; typedef union { squashfs_base_inode_header base; squashfs_dev_inode_header dev; squashfs_symlink_inode_header symlink; squashfs_reg_inode_header reg; squashfs_dir_inode_header dir; squashfs_ipc_inode_header ipc; } squashfs_inode_header; typedef struct { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)) squashfs_dir_entry; typedef struct { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_header; typedef struct { unsigned int start_block; unsigned int size; } __attribute__ ((packed)) squashfs_fragment_entry; extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem on a * machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\ } #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header)) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) #ifdef SQUASHFS_1_0_COMPATIBILITY typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)) squashfs_base_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)) squashfs_ipc_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)) squashfs_dev_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)) squashfs_symlink_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; squashfs_block start_block; unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; unsigned short block_list[0]; } __attribute__ ((packed)) squashfs_reg_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4);\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/squashfs_fs_i.h ================================================ #ifndef SQUASHFS_FS_I #define SQUASHFS_FS_I /* * Squashfs * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs_i.h */ typedef struct squashfs_inode_info { unsigned int start_block; unsigned int block_list_start; unsigned int offset; unsigned int fragment_start_block; unsigned int fragment_size; unsigned int fragment_offset; struct inode vfs_inode; } squashfs_inode_info; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-mksquashfs/squashfs/squashfs_fs_sb.h ================================================ #ifndef SQUASHFS_FS_SB #define SQUASHFS_FS_SB /* * Squashfs * * Copyright (c) 2002, 2003, 2004 Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs_sb.h */ #include typedef struct { unsigned int block; int length; unsigned int next_index; char *data; } squashfs_cache; struct squashfs_fragment_cache { unsigned int block; int length; unsigned int locked; char *data; }; typedef struct squashfs_sb_info { squashfs_super_block sBlk; int devblksize; int devblksize_log2; int swap; squashfs_cache *block_cache; struct squashfs_fragment_cache *fragment; int next_cache; int next_fragment; squashfs_uid *uid; squashfs_uid *guid; squashfs_fragment_index *fragment_index; unsigned int read_size; char *read_data; char *read_page; struct semaphore read_page_mutex; struct semaphore block_cache_mutex; struct semaphore fragment_mutex; wait_queue_head_t waitq; wait_queue_head_t fragment_wait_queue; struct inode *(*iget)(struct super_block *s, squashfs_inode inode); unsigned int (*read_blocklist)(struct inode *inode, int index, int readahead_blks, char *block_list, char **block_p, unsigned int *bsize); } squashfs_sb_info; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/Makefile ================================================ CC=gcc CFLAGS := -I. -Ibrcm-lzma -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 all: unsquashfs unsquashfs: nb4-unsquash.o cd brcm-lzma; make gcc nb4-unsquash.o brcm-lzma/7zlzma.o brcm-lzma/IInOutStreams.o brcm-lzma/LZMADecoder.o -lpthread -lm -o $@ nb4-unsquash.o: nb4-unsquash.c squashfs_fs.h read_fs.h global.h clean: cd brcm-lzma; make clean rm -f nb4-unsquash.o unsquashfs ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/README ================================================ Cette application nb4-unsquash est juste l'adaption de la suite inflate-lzma prsente dans le rpertoire kernel/linux/fs/inflate-lzma de la distribution Broadcom la procdure unsquashfs.c de la suite squashfs3.3 http://sourceforge.net/project/showfiles.php?group_id=63835 Un simple Make devrait construire l'utilitaire nb4-unsquash Pour l'utiliser ./nb4-unsquash SYNTAX: ./unsqlzma [options] filesystem [directories or files to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -li[nfo] print files as they are unsquashed with file attributes (like ls -l output) -l[s] list filesystem, but don't unsquash -ll[s] list filesystem with file attributes (like ls -l output), but don't unsquash -d[est] unsquash to , default "squashfs-root" -f[orce] if file already exists then overwrite -s[tat] display filesystem superblock information -e[f] list of directories or files to extract. One per line -r[egex] treat extract names as POSIX regular expressions rather than use the default shell wildcard expansion (globbing) pour lister les fichiers du fichier xx.sqsh ./nb4-unsquash -ll xx.sqsh pour extraire les fichiers du fichier xx.sqsh dans le rpertoire yy ./nb4-unsquash -d yy xx.sqsh ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/7z.h ================================================ #ifndef __7Z_H #define __7Z_H #if defined __cplusplus extern "C" { #endif int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size); #if defined __cplusplus } #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/7zlzma.c ================================================ #include "7z.h" #include "stdio.h" #include "string.h" #include "stdlib.h" #include "LZMADecoder.h" static LzmaDecoder cc; ISequentialInStream in_stream; ISequentialOutStream out_stream; int decompress_lzma_7z( unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) { // LzmaDecoder cc; int RC; UINT64 in_size_l = in_size; UINT64 out_size_l = out_size; InStreamInit(in_data, in_size); OutStreamInit((char *)out_data, out_size); LzmaDecoderConstructor(&cc); if ((RC = LzmaDecoderReadCoderProperties(&cc)) != S_OK) { return RC; } if (LzmaDecoderCode(&cc, &in_size_l, &out_size_l) != S_OK) { return -2; } if (out_stream.size != out_size) { return -3; } if ( out_stream.overflow ) { return -4; } return 0; } //BRCM modification #ifdef __KERNEL__ EXPORT_SYMBOL(decompress_lzma_7z); #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/AriBitCoder.h ================================================ #ifndef __COMPRESSION_BITCODER_H #define __COMPRESSION_BITCODER_H #include "RangeCoder.h" #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveReducingBits 2 typedef UINT32 CBitDecoder; INLINE void BitDecoderInit(CBitDecoder *bitDecoder) { *bitDecoder = kBitModelTotal / 2; } #if 0 UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder); #else INLINE UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * (*bitDecoder); if (aRangeDecoder->m_Code < aNewBound) { aRangeDecoder->m_Range = aNewBound; *bitDecoder += (kBitModelTotal - *bitDecoder) >> kNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); aRangeDecoder->m_Range <<= 8; } return 0; } else { aRangeDecoder->m_Range -= aNewBound; aRangeDecoder->m_Code -= aNewBound; *bitDecoder -= (*bitDecoder) >> kNumMoveBits; if (aRangeDecoder->m_Range < kTopValue) { aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); aRangeDecoder->m_Range <<= 8; } return 1; } } #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/BitTreeCoder.h ================================================ #ifndef __BITTREECODER_H #define __BITTREECODER_H #include "AriBitCoder.h" #include "RCDefs.h" //BRCM modification start #ifdef _HOST_TOOL #include "stdio.h" #include "stdlib.h" #include "malloc.h" #endif #ifdef _CFE_ #include "lib_malloc.h" #include "lib_printf.h" #define malloc(x) KMALLOC(x, 0) #endif #ifdef __KERNEL__ #include #include #include #define printf printk //#define malloc(x) kmalloc(x,GFP_KERNEL) #define malloc(x) vmalloc(x) #define free(x) vfree(x) #endif //BRCM modification end ////////////////////////// // CBitTreeDecoder typedef struct CBitTreeDecoder { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CBitTreeDecoder; // ~CBitTreeDecoder() { free(m_Models); } INLINE void BitTreeDecoderInit(CBitTreeDecoder *bitTreeDecoder, UINT32 aNumBitLevels) { int i; bitTreeDecoder->m_NumBitLevels = aNumBitLevels; bitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); //BRCM modification //printf("malloc in BitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels)); if (!bitTreeDecoder->m_Models) { printf("Error in allocating memory for bitTreeDecoder!\n"); return; } for(i = 1; i < (1 << aNumBitLevels); i++) BitDecoderInit(&bitTreeDecoder->m_Models[i]); } INLINE UINT32 BitTreeDecode(ISequentialInStream *in_stream, CBitTreeDecoder *bitTreeDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = bitTreeDecoder->m_NumBitLevels; aBitIndex > 0; aBitIndex--) { RC_GETBIT(kNumMoveBits, bitTreeDecoder->m_Models[aModelIndex], aModelIndex) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aModelIndex - (1 << bitTreeDecoder->m_NumBitLevels); } //////////////////////////////// // CReverseBitTreeDecoder2 typedef struct CReverseBitTreeDecoder2 { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CReverseBitTreeDecoder2; // CReverseBitTreeDecoder2(): m_Models(0) { } // ~CReverseBitTreeDecoder2() { free(m_Models); } INLINE BOOL ReverseBitTreeDecoder2Create(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, UINT32 aNumBitLevels) { reverseBitTreeDecoder2->m_NumBitLevels = aNumBitLevels; reverseBitTreeDecoder2->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); //printf("malloc in ReverseBitTreeDecoder2Create=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels)); if (!reverseBitTreeDecoder2->m_Models) { printf("Error in allocating memory for reverseBitTreeDecoder2!\n"); return 0; } return (reverseBitTreeDecoder2->m_Models != 0); } INLINE void ReverseBitTreeDecoder2Init(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2) { UINT32 aNumModels = 1 << reverseBitTreeDecoder2->m_NumBitLevels; UINT32 i; for(i = 1; i < aNumModels; i++) BitDecoderInit(&reverseBitTreeDecoder2->m_Models[i]); } INLINE UINT32 ReverseBitTreeDecoder2Decode(ISequentialInStream *in_stream, CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder2->m_NumBitLevels; aBitIndex++) { RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder2->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } //////////////////////////// // CReverseBitTreeDecoder typedef struct CReverseBitTreeDecoder { UINT32 m_NumBitLevels; CBitDecoder *m_Models; } CReverseBitTreeDecoder; // CReverseBitTreeDecoder(): m_Models(0) { } // ~CReverseBitTreeDecoder() { free(m_Models); } INLINE void ReverseBitTreeDecoderInit(CReverseBitTreeDecoder *reverseBitTreeDecoder, UINT32 aNumBitLevels) { int i; reverseBitTreeDecoder->m_NumBitLevels = aNumBitLevels; reverseBitTreeDecoder->m_Models = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); //printf("malloc in ReverseBitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels)); if (!reverseBitTreeDecoder->m_Models) { printf("Error in allocating memory for reverseBitTreeDecoder!\n"); return; } for(i = 1; i < (1 << reverseBitTreeDecoder->m_NumBitLevels); i++) BitDecoderInit(&reverseBitTreeDecoder->m_Models[i]); } INLINE UINT32 ReverseBitTreeDecoderDecode(ISequentialInStream *in_stream, CReverseBitTreeDecoder *reverseBitTreeDecoder, CRangeDecoder *aRangeDecoder) { UINT32 aModelIndex = 1; UINT32 aSymbol = 0; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; UINT32 aBitIndex; for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder->m_NumBitLevels; aBitIndex++) { RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex)) } aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/IInOutStreams.c ================================================ #include "stdlib.h" #include "IInOutStreams.h" // BRCM modification static void *lib_memcpy(void *dest,const void *src,size_t cnt); static void *lib_memcpy(void *dest,const void *src,size_t cnt) { unsigned char *d; const unsigned char *s; d = (unsigned char *) dest; s = (const unsigned char *) src; while (cnt) { *d++ = *s++; cnt--; } return dest; } HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize) { if (aSize > in_stream.remainingBytes) aSize = in_stream.remainingBytes; *aProcessedSize = aSize; lib_memcpy(aData, in_stream.data, aSize); // brcm modification in_stream.remainingBytes -= aSize; in_stream.data += aSize; return S_OK; } #if 0 BYTE InStreamReadByte() { if (in_stream.remainingBytes == 0) return 0x0; in_stream.remainingBytes--; return (BYTE) *in_stream.data++; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/IInOutStreams.h ================================================ #ifndef __IINOUTSTREAMS_H #define __IINOUTSTREAMS_H #include "Portable.h" typedef struct ISequentialInStream { unsigned char* data; unsigned remainingBytes; } ISequentialInStream; extern ISequentialInStream in_stream; INLINE void InStreamInit(unsigned char * Adata, unsigned Asize) { in_stream.data = Adata; in_stream.remainingBytes = Asize; } HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize); #if 0 BYTE InStreamReadByte(); #else INLINE BYTE InStreamReadByte(ISequentialInStream *in_stream) { if (in_stream->remainingBytes == 0) return 0x0; in_stream->remainingBytes--; return (BYTE) *in_stream->data++; } #endif typedef struct ISequentialOutStream { char* data; unsigned size; BOOL overflow; unsigned total; } ISequentialOutStream; extern ISequentialOutStream out_stream; #define OutStreamInit(Adata, Asize) \ { \ out_stream.data = Adata; \ out_stream.size = Asize; \ out_stream.overflow = FALSE; \ out_stream.total = 0; \ } #define OutStreamSizeSet(newsize) \ { \ out_stream.total = newsize; \ if (out_stream.total > out_stream.size) \ out_stream.overflow = TRUE; \ } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/LZMA.h ================================================ #include "LenCoder.h" #ifndef __LZMA_H #define __LZMA_H #define kNumRepDistances 4 #define kNumStates 12 static const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; typedef BYTE CState; INLINE void CStateInit(CState *m_Index) { *m_Index = 0; } INLINE void CStateUpdateChar(CState *m_Index) { *m_Index = kLiteralNextStates[*m_Index]; } INLINE void CStateUpdateMatch(CState *m_Index) { *m_Index = kMatchNextStates[*m_Index]; } INLINE void CStateUpdateRep(CState *m_Index) { *m_Index = kRepNextStates[*m_Index]; } INLINE void CStateUpdateShortRep(CState *m_Index) { *m_Index = kShortRepNextStates[*m_Index]; } #define kNumPosSlotBits 6 #define kDicLogSizeMax 28 #define kDistTableSizeMax 56 //extern UINT32 kDistStart[kDistTableSizeMax]; static const BYTE kDistDirectBits[kDistTableSizeMax] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 }; #define kNumLenToPosStates 4 INLINE UINT32 GetLenToPosState(UINT32 aLen) { aLen -= 2; if (aLen < kNumLenToPosStates) return aLen; return kNumLenToPosStates - 1; } #define kMatchMinLen 2 #define kMatchMaxLen (kMatchMinLen + kNumSymbolsTotal - 1) #define kNumAlignBits 4 #define kAlignTableSize 16 #define kAlignMask 15 #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels 10 #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #define kMainChoiceLiteralIndex 0 #define kMainChoiceMatchIndex 1 #define kMatchChoiceDistanceIndex0 #define kMatchChoiceRepetitionIndex 1 #define kNumMoveBitsForMainChoice 5 #define kNumMoveBitsForPosCoders 5 #define kNumMoveBitsForAlignCoders 5 #define kNumMoveBitsForPosSlotCoder 5 #define kNumLitPosStatesBitsEncodingMax 4 #define kNumLitContextBitsMax 8 #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/LZMADecoder.c ================================================ #include "Portable.h" #include "stdio.h" #include "stdlib.h" #include "LZMADecoder.h" //#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } static UINT32 kDistStart[kDistTableSizeMax]; struct WindowOut out_window; /* * BRCM modification: free all the allocated buffer by malloc * */ static void LzmaDecoderFreeBuffer(LzmaDecoder *lzmaDecoder) { int i,aPosState; //printf("free lzmaDecoder->m_LiteralDecoder\n"); free((&lzmaDecoder->m_LiteralDecoder)->m_Coders); for (i = 0; i < kNumLenToPosStates; i++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free((&lzmaDecoder->m_PosSlotDecoder[i])->m_Models); } // from LenDecoderInit(&lzmaDecoder->m_LenDecoder; for (aPosState = 0; aPosState < (&lzmaDecoder->m_LenDecoder)->m_NumPosStates; aPosState++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_LowCoder[aPosState])->m_Models ); //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_MidCoder[aPosState])->m_Models ); } //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_LenDecoder)->m_HighCoder)->m_Models ); // from LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); for (aPosState = 0; aPosState < (&lzmaDecoder->m_RepMatchLenDecoder)->m_NumPosStates; aPosState++) { //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_LowCoder[aPosState])->m_Models ); //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_MidCoder[aPosState])->m_Models ); } //printf("free lzmaDecoder->m_PosSlotDecoder\n"); free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_HighCoder)->m_Models ); //printf("free lzmaDecoder->m_PosAlignDecoder\n"); free((&lzmaDecoder->m_PosAlignDecoder)->m_Models); for(i = 0; i < kNumPosModels; i++) { //printf("free lzmaDecoder->m_PosDecoders\n"); free((&lzmaDecoder->m_PosDecoders[i])->m_Models); } } HRESULT LzmaDecoderSetDictionarySize( LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize) { if (aDictionarySize > (1 << kDicLogSizeMax)) return E_INVALIDARG; // UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); if (lzmaDecoder->m_DictionarySize != aDictionarySize) { lzmaDecoder->m_DictionarySize = aDictionarySize; } return S_OK; } HRESULT LzmaDecoderSetLiteralProperties( LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) { if (aLiteralPosStateBits > 8) return E_INVALIDARG; if (aLiteralContextBits > 8) return E_INVALIDARG; LitDecoderCreate(&lzmaDecoder->m_LiteralDecoder, aLiteralPosStateBits, aLiteralContextBits); return S_OK; } HRESULT LzmaDecoderSetPosBitsProperties( LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits) { UINT32 aNumPosStates; if (aNumPosStateBits > (UINT32) kNumPosStatesBitsMax) return E_INVALIDARG; aNumPosStates = 1 << aNumPosStateBits; LenDecoderCreate(&lzmaDecoder->m_LenDecoder, aNumPosStates); LenDecoderCreate(&lzmaDecoder->m_RepMatchLenDecoder, aNumPosStates); lzmaDecoder->m_PosStateMask = aNumPosStates - 1; return S_OK; } void LzmaDecoderConstructor(LzmaDecoder *lzmaDecoder) { lzmaDecoder->m_DictionarySize = ((UINT32)-1); LzmaDecoderCreate(lzmaDecoder); } HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder) { int i; for(i = 0; i < kNumPosModels; i++) { if (!(ReverseBitTreeDecoder2Create(&lzmaDecoder->m_PosDecoders[i],kDistDirectBits[kStartPosModelIndex + i]))) return E_OUTOFMEMORY;; } return S_OK; } HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder) { int i; UINT32 j; RangeDecoderInit(&in_stream, &lzmaDecoder->m_RangeDecoder); OutWindowInit(); for(i = 0; i < kNumStates; i++) { for (j = 0; j <= lzmaDecoder->m_PosStateMask; j++) { BitDecoderInit(&lzmaDecoder->m_MainChoiceDecoders[i][j]); BitDecoderInit(&lzmaDecoder->m_MatchRepShortChoiceDecoders[i][j]); } BitDecoderInit(&lzmaDecoder->m_MatchChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRepChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRep1ChoiceDecoders[i]); BitDecoderInit(&lzmaDecoder->m_MatchRep2ChoiceDecoders[i]); } LitDecoderInit(&lzmaDecoder->m_LiteralDecoder); for (i = 0; i < (int) kNumLenToPosStates; i++) BitTreeDecoderInit(&lzmaDecoder->m_PosSlotDecoder[i],kNumPosSlotBits); for(i = 0; i < kNumPosModels; i++) ReverseBitTreeDecoder2Init(&lzmaDecoder->m_PosDecoders[i]); LenDecoderInit(&lzmaDecoder->m_LenDecoder); LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder); ReverseBitTreeDecoderInit(&lzmaDecoder->m_PosAlignDecoder, kNumAlignBits); return S_OK; } HRESULT LzmaDecoderCodeReal( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize) { BOOL aPeviousIsMatch = FALSE; BYTE aPreviousByte = 0; UINT32 aRepDistances[kNumRepDistances]; int i; UINT64 aNowPos64 = 0; UINT64 aSize = *anOutSize; ISequentialInStream my_in_stream; // WindowOut out_window; CState aState; CStateInit(&aState); if (anOutSize == NULL) { printf("CodeReal: invalid argument %x\n", (UINT32) anOutSize ); return E_INVALIDARG; } LzmaDecoderInit(lzmaDecoder); my_in_stream.data = in_stream.data; my_in_stream.remainingBytes = in_stream.remainingBytes; for(i = 0 ; i < (int) kNumRepDistances; i++) aRepDistances[i] = 0; //while(aNowPos64 < aSize) while(my_in_stream.remainingBytes > 0) { UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); while(aNowPos64 < aNext) { UINT32 aPosState = (UINT32)(aNowPos64) & lzmaDecoder->m_PosStateMask; if (BitDecode(&my_in_stream, &lzmaDecoder->m_MainChoiceDecoders[aState][aPosState], &lzmaDecoder->m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) { CStateUpdateChar(&aState); if(aPeviousIsMatch) { BYTE aMatchByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); aPreviousByte = LitDecodeWithMatchByte(&my_in_stream, &lzmaDecoder->m_LiteralDecoder, &lzmaDecoder->m_RangeDecoder, (UINT32)(aNowPos64), aPreviousByte, aMatchByte); aPeviousIsMatch = FALSE; } else aPreviousByte = LitDecodeNormal(&my_in_stream, &lzmaDecoder->m_LiteralDecoder, &lzmaDecoder->m_RangeDecoder, (UINT32)(aNowPos64), aPreviousByte); OutWindowPutOneByte(aPreviousByte); aNowPos64++; } else { UINT32 aDistance, aLen; aPeviousIsMatch = TRUE; if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex) { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRepChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRepShortChoiceDecoders[aState][aPosState], &lzmaDecoder->m_RangeDecoder) == 0) { CStateUpdateShortRep(&aState); aPreviousByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1); OutWindowPutOneByte(aPreviousByte); aNowPos64++; continue; } aDistance = aRepDistances[0]; } else { if(BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRep1ChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { aDistance = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } else { if (BitDecode(&my_in_stream, &lzmaDecoder->m_MatchRep2ChoiceDecoders[aState], &lzmaDecoder->m_RangeDecoder) == 0) { aDistance = aRepDistances[2]; } else { aDistance = aRepDistances[3]; aRepDistances[3] = aRepDistances[2]; } aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; } aRepDistances[0] = aDistance; } aLen = LenDecode(&my_in_stream, &lzmaDecoder->m_RepMatchLenDecoder, &lzmaDecoder->m_RangeDecoder, aPosState) + kMatchMinLen; CStateUpdateRep(&aState); } else { UINT32 aPosSlot; aLen = kMatchMinLen + LenDecode(&my_in_stream, &lzmaDecoder->m_LenDecoder, &lzmaDecoder->m_RangeDecoder, aPosState); CStateUpdateMatch(&aState); aPosSlot = BitTreeDecode(&my_in_stream, &lzmaDecoder->m_PosSlotDecoder[GetLenToPosState(aLen)], &lzmaDecoder->m_RangeDecoder); if (aPosSlot >= (UINT32) kStartPosModelIndex) { aDistance = kDistStart[aPosSlot]; if (aPosSlot < (UINT32) kEndPosModelIndex) aDistance += ReverseBitTreeDecoder2Decode(&my_in_stream, &lzmaDecoder->m_PosDecoders[aPosSlot - kStartPosModelIndex], &lzmaDecoder->m_RangeDecoder); else { aDistance += (RangeDecodeDirectBits(&my_in_stream, &lzmaDecoder->m_RangeDecoder, kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits); aDistance += ReverseBitTreeDecoderDecode(&my_in_stream, &lzmaDecoder->m_PosAlignDecoder, &lzmaDecoder->m_RangeDecoder); } } else aDistance = aPosSlot; aRepDistances[3] = aRepDistances[2]; aRepDistances[2] = aRepDistances[1]; aRepDistances[1] = aRepDistances[0]; aRepDistances[0] = aDistance; } if (aDistance >= aNowPos64) { printf("CodeReal: invalid data\n" ); return E_INVALIDDATA; } OutWindowCopyBackBlock(aDistance, aLen); aNowPos64 += aLen; aPreviousByte = OutWindowGetOneByte(0 - 1); } } } //BRCM modification LzmaDecoderFreeBuffer(lzmaDecoder); OutWindowFlush(); return S_OK; } HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize) { UINT32 aStartValue = 0; int i; for (i = 0; i < kDistTableSizeMax; i++) { kDistStart[i] = aStartValue; aStartValue += (1 << kDistDirectBits[i]); } return LzmaDecoderCodeReal( lzmaDecoder, anInSize, anOutSize); } HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder) { UINT32 aNumPosStateBits; UINT32 aLiteralPosStateBits; UINT32 aLiteralContextBits; UINT32 aDictionarySize; BYTE aRemainder; UINT32 aProcessesedSize; BYTE aByte; RETURN_IF_NOT_S_OK(InStreamRead(&aByte, sizeof(aByte), &aProcessesedSize)); if (aProcessesedSize != sizeof(aByte)) return E_INVALIDARG; aLiteralContextBits = aByte % 9; aRemainder = aByte / 9; aLiteralPosStateBits = aRemainder % 5; aNumPosStateBits = aRemainder / 5; RETURN_IF_NOT_S_OK(InStreamRead(&aDictionarySize, sizeof(aDictionarySize), &aProcessesedSize)); if (aProcessesedSize != sizeof(aDictionarySize)) return E_INVALIDARG; RETURN_IF_NOT_S_OK( LzmaDecoderSetDictionarySize(lzmaDecoder, aDictionarySize) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetLiteralProperties(lzmaDecoder, aLiteralPosStateBits, aLiteralContextBits) ); RETURN_IF_NOT_S_OK( LzmaDecoderSetPosBitsProperties(lzmaDecoder, aNumPosStateBits) ); return S_OK; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/LZMADecoder.h ================================================ #ifndef __LZARITHMETIC_DECODER_H #define __LZARITHMETIC_DECODER_H #include "WindowOut.h" #include "LZMA.h" #include "LenCoder.h" #include "LiteralCoder.h" typedef struct LzmaDecoder { CRangeDecoder m_RangeDecoder; CBitDecoder m_MainChoiceDecoders[kNumStates][kNumPosStatesMax]; CBitDecoder m_MatchChoiceDecoders[kNumStates]; CBitDecoder m_MatchRepChoiceDecoders[kNumStates]; CBitDecoder m_MatchRep1ChoiceDecoders[kNumStates]; CBitDecoder m_MatchRep2ChoiceDecoders[kNumStates]; CBitDecoder m_MatchRepShortChoiceDecoders[kNumStates][kNumPosStatesMax]; CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; CReverseBitTreeDecoder m_PosAlignDecoder; LenDecoder m_LenDecoder; LenDecoder m_RepMatchLenDecoder; LitDecoder m_LiteralDecoder; UINT32 m_DictionarySize; UINT32 m_PosStateMask; } LzmaDecoder; HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder); HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder); //static inline HRESULT LzmaDecoderFlush() { return OutWindowFlush(); } HRESULT LzmaDecoderCodeReal( LzmaDecoder *lzmaDecoder, // ISequentialInStream *in_stream, UINT64 *anInSize, // WindowOut *out_window, UINT64 *anOutSize); void LzmaDecoderConstructor( LzmaDecoder *lzmaDecoder ); HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize); HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder ); HRESULT LzmaDecoderSetDictionarySize(LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize); HRESULT LzmaDecoderSetLiteralProperties(LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); HRESULT LzmaDecoderSetPosBitsProperties(LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits); #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/LenCoder.h ================================================ #ifndef __LENCODER_H #define __LENCODER_H #include "BitTreeCoder.h" #define kNumPosStatesBitsMax 4 #define kNumPosStatesMax 16 #define kNumPosStatesBitsEncodingMax 4 #define kNumPosStatesEncodingMax 16 //#define kNumMoveBits 5 #define kNumLenBits 3 #define kNumLowSymbols (1 << kNumLenBits) #define kNumMidBits 3 #define kNumMidSymbols (1 << kNumMidBits) #define kNumHighBits 8 #define kNumSymbolsTotal (kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits)) typedef struct LenDecoder { CBitDecoder m_Choice; CBitDecoder m_Choice2; CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; CBitTreeDecoder m_HighCoder; UINT32 m_NumPosStates; } LenDecoder; INLINE void LenDecoderCreate(LenDecoder *lenCoder, UINT32 aNumPosStates) { lenCoder->m_NumPosStates = aNumPosStates; } INLINE void LenDecoderInit(LenDecoder *lenCoder) { UINT32 aPosState; BitDecoderInit(&lenCoder->m_Choice); for (aPosState = 0; aPosState < lenCoder->m_NumPosStates; aPosState++) { BitTreeDecoderInit(&lenCoder->m_LowCoder[aPosState],kNumLenBits); BitTreeDecoderInit(&lenCoder->m_MidCoder[aPosState],kNumMidBits); } BitTreeDecoderInit(&lenCoder->m_HighCoder,kNumHighBits); BitDecoderInit(&lenCoder->m_Choice2); } INLINE UINT32 LenDecode(ISequentialInStream *in_stream, LenDecoder *lenCoder, CRangeDecoder *aRangeDecoder, UINT32 aPosState) { if(BitDecode(in_stream, &lenCoder->m_Choice, aRangeDecoder) == 0) return BitTreeDecode(in_stream, &lenCoder->m_LowCoder[aPosState],aRangeDecoder); else { UINT32 aSymbol = kNumLowSymbols; if(BitDecode(in_stream, &lenCoder->m_Choice2, aRangeDecoder) == 0) aSymbol += BitTreeDecode(in_stream, &lenCoder->m_MidCoder[aPosState],aRangeDecoder); else { aSymbol += kNumMidSymbols; aSymbol += BitTreeDecode(in_stream, &lenCoder->m_HighCoder,aRangeDecoder); } return aSymbol; } } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/LiteralCoder.h ================================================ #ifndef __LITERALCODER_H #define __LITERALCODER_H #include "AriBitCoder.h" #include "RCDefs.h" //BRCM modification start #ifdef _HOST_TOOL #include "stdio.h" #include "malloc.h" #endif #ifdef _CFE_ #include "lib_malloc.h" #include "lib_printf.h" #define malloc(x) KMALLOC(x, 0) #define free(x) KFREE(x) #endif #ifdef __KERNEL__ #include #include #define printf printk //#define malloc(x) kmalloc(x,GFP_KERNEL) #define malloc(x) vmalloc(x) #define free(x) vfree(x) #endif //BRCM modification end //#define kNumMoveBits 5 typedef struct LitDecoder2 { CBitDecoder m_Decoders[3][1 << 8]; } LitDecoder2; INLINE void LitDecoder2Init(LitDecoder2 *litDecoder2) { int i, j; for (i = 0; i < 3; i++) for (j = 1; j < (1 << 8); j++) BitDecoderInit(&litDecoder2->m_Decoders[i][j]); } INLINE BYTE LitDecoder2DecodeNormal(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder) { UINT32 aSymbol = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; do { RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) } while (aSymbol < 0x100); aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } INLINE BYTE LitDecoder2DecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder, BYTE aMatchByte) { UINT32 aSymbol = 1; UINT32 aRange = aRangeDecoder->m_Range; UINT32 aCode = aRangeDecoder->m_Code; do { UINT32 aBit; UINT32 aMatchBit = (aMatchByte >> 7) & 1; aMatchByte <<= 1; RC_GETBIT2(kNumMoveBits, litDecoder2->m_Decoders[1 + aMatchBit][aSymbol], aSymbol, aBit = 0, aBit = 1) if (aMatchBit != aBit) { while (aSymbol < 0x100) { RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol) } break; } } while (aSymbol < 0x100); aRangeDecoder->m_Range = aRange; aRangeDecoder->m_Code = aCode; return aSymbol; } typedef struct LitDecoder { LitDecoder2 *m_Coders; UINT32 m_NumPrevBits; UINT32 m_NumPosBits; UINT32 m_PosMask; } LitDecoder; // LitDecoder(): m_Coders(0) {} // ~LitDecoder() { Free(); } /* INLINE void LitDecoderFree(LitDecoder *litDecoder) { free( (char *) litDecoder->m_Coders ); litDecoder->m_Coders = 0; } */ INLINE void LitDecoderCreate(LitDecoder *litDecoder, UINT32 aNumPosBits, UINT32 aNumPrevBits) { // LitDecoderFree(litDecoder); UINT32 aNumStates; litDecoder->m_NumPosBits = aNumPosBits; litDecoder->m_PosMask = (1 << aNumPosBits) - 1; litDecoder->m_NumPrevBits = aNumPrevBits; aNumStates = 1 << (aNumPrevBits + aNumPosBits); litDecoder->m_Coders = (LitDecoder2*) malloc( sizeof( LitDecoder2 ) * aNumStates ); //printf("malloc in LitDecoderCreate=%d\n",sizeof( LitDecoder2 ) * aNumStates); if (litDecoder->m_Coders == 0) printf( "Error allocating memory for LitDecoder m_Coders!\n" ); } INLINE void LitDecoderInit(LitDecoder *litDecoder) { UINT32 i; UINT32 aNumStates = 1 << (litDecoder->m_NumPrevBits + litDecoder->m_NumPosBits); for (i = 0; i < aNumStates; i++) LitDecoder2Init(&litDecoder->m_Coders[i]); } INLINE UINT32 LitDecoderGetState(LitDecoder *litDecoder, UINT32 aPos, BYTE aPrevByte) { return ((aPos & litDecoder->m_PosMask) << litDecoder->m_NumPrevBits) + (aPrevByte >> (8 - litDecoder->m_NumPrevBits)); } INLINE BYTE LitDecodeNormal(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) { return LitDecoder2DecodeNormal(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder); } INLINE BYTE LitDecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) { return LitDecoder2DecodeWithMatchByte(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder, aMatchByte); } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/Makefile ================================================ INCLUDEDIR = . CC=gcc CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 all:7zlzma.o IInOutStreams.o LZMADecoder.o clean : rm -f *.o ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/Portable.h ================================================ #ifndef __PORTABLE_H #define __PORTABLE_H //BRCM modification #ifdef _HOST_TOOL #include #endif #ifdef _CFE_ #include #endif #ifdef __KERNEL__ #include #endif //bcm //#ifdef __GNUC__ //#include //#define INLINE static inline //#else typedef char INT8; typedef unsigned char UINT8; typedef short INT16; typedef unsigned short UINT16; typedef int INT32; typedef unsigned int UINT32; typedef int BOOL; #define INLINE static inline //#define INLINE static __inline__ //#endif typedef long long INT64; // %%%% Changed from "long long" typedef unsigned long long UINT64; // %%%% Changed from "long long" typedef UINT8 BYTE; typedef UINT16 WORD; typedef UINT32 DWORD; typedef unsigned UINT_PTR; #define FALSE 0 #define TRUE 1 #define HRESULT int #define S_OK 0 #define E_INVALIDARG -1 #define E_OUTOFMEMORY -2 #define E_FAIL -3 #define E_INTERNAL_ERROR -4 #define E_INVALIDDATA -5 #define MyMin( a, b ) ( a < b ? a : b ) #define MyMax( a, b ) ( a > b ? a : b ) #define kNumMoveBits 5 #define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/RCDefs.h ================================================ #ifndef __RCDEFS_H #define __RCDEFS_H #include "AriBitCoder.h" /* #define RC_INIT_VAR \ UINT32 aRange = aRangeDecoder->m_Range; \ UINT32 aCode = aRangeDecoder->m_Code; #define RC_FLUSH_VAR \ aRangeDecoder->m_Range = aRange; \ aRangeDecoder->m_Code = aCode; */ #if 1 #define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ {UINT32 aNewBound = (aRange >> kNumBitModelTotalBits) * aProb; \ if (aCode < aNewBound) \ { \ Action0; \ aRange = aNewBound; \ aProb += (kBitModelTotal - aProb) >> aNumMoveBits; \ aModelIndex <<= 1; \ } \ else \ { \ Action1; \ aRange -= aNewBound; \ aCode -= aNewBound; \ aProb -= (aProb) >> aNumMoveBits; \ aModelIndex = (aModelIndex << 1) + 1; \ }} \ if (aRange < kTopValue) \ { \ aCode = (aCode << 8) | InStreamReadByte(in_stream); \ aRange <<= 8; } #define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) #endif #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/RangeCoder.h ================================================ #ifndef __COMPRESSION_RANGECODER_H #define __COMPRESSION_RANGECODER_H #include "IInOutStreams.h" #define kNumTopBits 24 #define kTopValue (1 << kNumTopBits) typedef struct CRangeDecoder { UINT32 m_Range; UINT32 m_Code; } CRangeDecoder; INLINE void RangeDecoderInit( ISequentialInStream *in_stream, CRangeDecoder *rangeDecoder) { int i; rangeDecoder->m_Code = 0; rangeDecoder->m_Range = (UINT32)(-1); for(i = 0; i < 5; i++) rangeDecoder->m_Code = (rangeDecoder->m_Code << 8) | InStreamReadByte(in_stream); } INLINE UINT32 RangeDecodeDirectBits( ISequentialInStream *in_stream, CRangeDecoder *rangeDecoder, UINT32 aNumTotalBits) { UINT32 aRange = rangeDecoder->m_Range; UINT32 aCode = rangeDecoder->m_Code; UINT32 aResult = 0; UINT32 i; for (i = aNumTotalBits; i > 0; i--) { UINT32 t; aRange >>= 1; t = (aCode - aRange) >> 31; aCode -= aRange & (t - 1); aResult = (aResult << 1) | (1 - t); if (aRange < kTopValue) { aCode = (aCode << 8) | InStreamReadByte(in_stream); aRange <<= 8; } } rangeDecoder->m_Range = aRange; rangeDecoder->m_Code = aCode; return aResult; } #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/WindowOut.h ================================================ #ifndef __STREAM_WINDOWOUT_H #define __STREAM_WINDOWOUT_H #include "IInOutStreams.h" typedef struct WindowOut { BYTE *Buffer; UINT32 Pos; } WindowOut; extern WindowOut out_window; #define OutWindowInit() \ { \ out_window.Buffer = (BYTE *) out_stream.data; \ out_window.Pos = 0; \ } #define OutWindowFlush() \ { \ OutStreamSizeSet( out_window.Pos ); \ } // BRCM modification INLINE void OutWindowCopyBackBlock(UINT32 aDistance, UINT32 aLen) { BYTE *p = out_window.Buffer + out_window.Pos; UINT32 i; aDistance++; for(i = 0; i < aLen; i++) p[i] = p[i - aDistance]; out_window.Pos += aLen; } #define OutWindowPutOneByte(aByte) \ { \ out_window.Buffer[out_window.Pos++] = aByte; \ } #define OutWindowGetOneByte(anIndex) \ (out_window.Buffer[out_window.Pos + anIndex]) #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/brcm-lzma/vxTypesOld.h ================================================ /* vxTypesOld.h - old VxWorks type definition header */ /* Copyright 1984-1997 Wind River Systems, Inc. */ /* modification history -------------------- 02c,15aug97,cym added simnt support. 02d,26mar97,cdp added Thumb (ARM7TDMI_T) support. 02c,28nov96,cdp added ARM support. 02b,28sep95,ms removed "static __inline__" (SPR #4500) 02b,12jul95,ism added simsolaris support 02a,19mar95,dvs removed tron references. 01z,01sep94,ism fixed comment as per SPR# 1512. 01y,02dec93,pme added Am29K family support. 01x,12jun93,rrr vxsim. 02a,26may94,yao added PPC support. 01w,09jun93,hdn added support for I80X86 01v,12feb93,srh added C++ versions of FUNCPTR, et al. 01u,13nov92,dnw added definition of VOID (SPR #1781) 01t,02oct92,srh replaced conditional around volatile, const, and signed so they won't be elided when __STDC__ is defined. added __cplusplus to __STDC__ condition. 01s,22sep92,rrr added support for c++ 01r,08sep92,smb made some additions for the MIPS. 01q,07sep92,smb added __STDC__ and modes to maintain compatibility with 5.0 01p,07jul92,rrr moved STACK_GROW and ENDIAN to vxArch.h 01o,03jul92,smb changed name from vxTypes.h. 01n,26may92,rrr the tree shuffle 01m,25nov91,llk included sys/types.h. 01l,04oct91,rrr passed through the ansification filter -fixed #else and #endif -removed TINY and UTINY -changed VOID to void -changed ASMLANGUAGE to _ASMLANGUAGE -changed copyright notice 01k,01oct91,jpb fixed MIPS conditional for undefined CPU_FAMILY. 01j,20sep91,wmd conditionalized out defines for const, unsigned and volatile for the MIPS architecture. 01i,02aug91,ajm added support for MIPS_R3k. 01h,15may91,gae added define for "signed" when not available for pre-ANSI. 01g,29apr91,hdn added defines and macros for TRON architecture. 01f,28apr91,del added defines of __volatile__ and __const__ if !_STDC_ && _GNUC__ 01f,24mar91,del added INSTR * define for I960. 01e,28jan91,kdl added DBLFUNCPTR and FLTFUNCPTR. 01d,25oct90,dnw changed void to void except when linting. 01c,05oct90,shl added copyright notice. made #endif ANSI style. 01b,10aug90,dnw added VOIDFUNCPTR 01a,29may90,del written. */ /* DESCRIPTION This header file contains a mixture of stuff. 1) the old style typedefs (ie. POSIX now says they must end with _t). These will be phased out gradually. 2) a mechanism for getting rid of const warning which are produced by the GNU C compiler. Hopefully, this will be removed in the future. 3) macros that are so longer needed for vxWorks source code but maybe needed by some customer applications and are therefore provided for backward compatability. 4) system III typedefs (used by netinet) which do not fit in anywhere else. */ #ifndef __INCvxTypesOldh #define __INCvxTypesOldh #ifdef __cplusplus extern "C" { #endif #include "sys/types.h" /* vxWorks types */ typedef char INT8; typedef short INT16; typedef int INT32; typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; typedef int BOOL; typedef int STATUS; typedef int ARGINT; typedef void VOID; #ifdef __cplusplus typedef int (*FUNCPTR) (...); /* ptr to function returning int */ typedef void (*VOIDFUNCPTR) (...); /* ptr to function returning void */ typedef double (*DBLFUNCPTR) (...); /* ptr to function returning double*/ typedef float (*FLTFUNCPTR) (...); /* ptr to function returning float */ #else typedef int (*FUNCPTR) (); /* ptr to function returning int */ typedef void (*VOIDFUNCPTR) (); /* ptr to function returning void */ typedef double (*DBLFUNCPTR) (); /* ptr to function returning double*/ typedef float (*FLTFUNCPTR) (); /* ptr to function returning float */ #endif /* _cplusplus */ /* This structure and the following definitions are needed to get rid of const warning produced by the GNU C compiler. */ #if defined(__STDC__) || defined(__cplusplus) typedef union { long pm_int; void *pm_v; const void *pm_cv; char *pm_c; unsigned char *pm_uc; signed char *pm_sc; const char *pm_cc; const unsigned char *pm_cuc; const signed char *pm_csc; short *pm_s; ushort_t *pm_us; const short *pm_cs; const ushort_t *pm_cus; int *pm_i; uint_t *pm_ui; const int *pm_ci; const uint_t *pm_cui; long *pm_l; ulong_t *pm_ul; const long *pm_cl; const ulong_t *pm_cul; int8_t *pm_i8; uint8_t *pm_ui8; const int8_t *pm_ci8; const uint8_t *pm_cui8; int16_t *pm_i16; uint16_t *pm_ui16; const int16_t *pm_ci16; const uint16_t *pm_cui16; int32_t *pm_i32; uint32_t *pm_ui32; const int32_t *pm_ci32; const uint32_t *pm_cui32; #if _ARCH_MOVE_SIZE > 4 int64_t *pm_i64; const int64_t *pm_ci64; #if _ARCH_MOVE_SIZE > 8 int128_t *pm_i128; const int128_t *pm_ci128; #endif #endif } pointer_mix_t; #define CHAR_FROM_CONST(x) (char *)(x) #define VOID_FROM_CONST(x) (void *)(x) #endif /* __STDC__ */ #define STACK_DIR _ARCH_STACK_DIR #define ALIGN_MEMORY _ARCH_ALIGN_MEMORY #define ALIGN_STACK _ARCH_ALIGN_STACK #define ALIGN_REGS _ARCH_ALIGN_REGS #define NBBY 8 /* number of bits in a byte */ /* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */ #define READ 0 #define WRITE 1 #define UPDATE 2 /* Select uses bit masks of file descriptors in longs. * These macros manipulate such bit fields (the filesystem macros use chars). * FD_SETSIZE may be defined by the user, but the default here * should be >= maxFiles parameter in iosInit call found in usrConfig.c. * If this define is changed, recompile the source, or else select() will * not work. */ #ifndef FD_SETSIZE #define FD_SETSIZE 256 #endif /* FD_SETSIZE */ typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ #ifndef howmany #define howmany(x, y) ((unsigned int)(((x)+((y)-1)))/(unsigned int)(y)) #endif /* howmany */ typedef struct fd_set { fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; } fd_set; #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) /* system III typedefs (used by netinet) */ typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short ushort; /* historical definitions - now obsolete */ typedef char TBOOL; /* obsolete */ /* architecture dependent typedefs */ #ifdef CPU_FAMILY #if CPU_FAMILY==MC680X0 typedef unsigned short INSTR; /* word-aligned instructions */ #endif /* CPU_FAMILY==MC680X0 */ #if CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS */ #if CPU_FAMILY==I960 typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==I960 */ #if CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT typedef unsigned char INSTR; /* char instructions */ #endif /* CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT */ #if CPU_FAMILY==AM29XXX typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* CPU_FAMILY==AM29XXX */ #if (CPU_FAMILY==PPC) typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif /* (CPU_FAMILY==PPC) */ #if CPU_FAMILY==ARM #if CPU==ARM7TDMI_T typedef unsigned short INSTR; /* 16 bit instructions */ #else typedef unsigned long INSTR; /* 32 bit word-aligned instructions */ #endif #endif /* CPU_FAMILY==ARM */ #endif /* CPU_FAMILY */ /* ANSI type qualifiers */ #if !defined(__STDC__) && !defined(__cplusplus) #ifdef __GNUC__ #define volatile __volatile__ #define const __const__ #define signed __signed__ #else #if !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) #define volatile #define const #define signed #endif /* !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) */ #endif /* __GNUC__ */ #endif /* !defined(__STDC__) && !defined(__cplusplus) */ #if CPU_FAMILY==MIPS #define CHAR_FROM_CONST(x) (char *)(x) #define VOID_FROM_CONST(x) (void *)(x) #endif #ifdef __cplusplus } #endif #endif /* __INCvxTypesOldh */ ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/nb4-unsquash.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #define Z_OK 0 #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__GNUC__) && !defined(__MACOSX__) #include #else #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "7z.h" #if defined(__CYGWIN__) || defined(__MACOSX__) #define FNM_EXTMATCH (1 << 5) #endif #ifdef __CYGWIN__ #define SYSTEM_UID 18 #else #define SYSTEM_UID 0 #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("unsquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ exit(1); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(char *pathname, unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, unsigned char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; struct test { int mask; int value; int position; char mode; }; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; res = decompress_lzma_7z((unsigned char *) buffer, c_byte, (unsigned char *) block, bytes); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; res = decompress_lzma_7z((unsigned char *) data, c_byte, (unsigned char *) block, bytes); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, unsigned char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, unsigned char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); ERROR("chown(%s, %d, %d)\n", pathname, uid, guid); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int lseek_broken = FALSE; char *zero_data; long long hole; int write_block(int file_fd, char *buffer, int size) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } hole = 0; } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } int write_file(long long file_size, char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; int file_end = file_size / block_size; TRACE("write_file: regular file, blocks %d, file_size %d\n", blocks,file_size); hole = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } s_ops.read_block_list(block_list, block_ptr, blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if(block_list[i] == 0) { /* sparse file */ hole += i == file_end ? file_size & (block_size - 1) : block_size; continue; } if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(i < blocks-1) bytes=65536; else bytes=file_size - (blocks-1)*65536 - frag_bytes; TRACE("decompress %d bytes into %d bytes\n", SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]),bytes); if(write_block(file_fd, file_data, bytes) == FALSE) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write_block(file_fd, fragment_data + offset, frag_bytes) == FALSE) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } if(hole) { /* corner case for hole extending to end of file */ hole --; if(write_block(file_fd, "\0", 1) == FALSE) { ERROR("write_file: failed to write sparse data block\n"); goto failure; } } close(file_fd); free(block_list); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i->data, pathname, i->fragment, i->frag_bytes, i->offset, i->blocks, i->start, i->block_ptr, i->mode)) { set_attributes(pathname, i->mode, i->uid, i->gid, i->time, force); file_count ++; } break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %d\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%x\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB)) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { struct dir *dir = s_ops.squashfs_opendir(parent_name, start_block, offset); unsigned int type; char *name, pathname[1024]; struct pathnames *new; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) create_inode(pathname, i); } free_subdir(new); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk.s_magic != SQUASHFS_MAGIC) { if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "rb")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } #define VERSION() \ printf("unsquashfs version 1.5 (2007/10/31)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; char **target_name = NULL; int n, targets = 0; struct pathnames *paths = NULL; struct pathname *path = NULL; if(root_process = (geteuid() == SYSTEM_UID)) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] \tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-2.0-nb4/nb4-unsquashfs/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/Makefile ================================================ INCLUDEDIR = . LZMAPATH = ./lzma/C/7zip/Compress/LZMA_Lib CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 all: mksquashfs mksquashfs-lzma unsquashfs unsquashfs-lzma CC=gcc CXX=g++ mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@ mksquashfs-lzma: mksquashfs.o read_fs.o sort.o make -C $(LZMAPATH) $(CXX) mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -llzma -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs-lzma: unsquashfs.o make -C $(LZMAPATH) $(CXX) -O3 unsquashfs.o -L$(LZMAPATH) -llzma -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h install: mksquashfs-lzma cp mksquashfs-lzma /opt/buildroot-gdb/bin/mksquashfs_lzma-3.0 clean: $(MAKE) -C lzma/C/7zip/Compress/LZMA_Lib clean rm -f *.o mksquashfs mksquashfs-lzma unsquashfs unsquashfs-lzma ================================================ FILE: src/others/squashfs-3.0-e2100/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/.built ================================================ ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/.unpacked ================================================ ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.23 ---------------------- 7z ANSI-C Decoder 4.23 Copyright (C) 1999-2005 Igor Pavlov 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- Read lzma.txt for information about license. Files --------------------- 7zAlloc.* - Allocate and Free 7zBuffer.* - Buffer structure 7zCrc.* - CRC32 code 7zDecode.* - Low level memory->memory decoding 7zExtract.* - High level stream->memory decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application 7zMethodID.* - MethodID structure 7zTypes.h - Base types and constants How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec : e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- .7z Decoder can be compiled in one of two modes: 1) Default mode. In that mode 7z Decoder will read full compressed block to RAM before decompressing. 2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read compressed block by parts. And you can specify desired buffer size. So memory requirements can be reduced. But decompressing speed will be 5-10% lower and code size is slightly larger. Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ISzInStream interface */ CArchiveDatabaseEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call InitCrcTable(); function to initialize CRC structures. 3) call SzArDbExInit(&db); function to initialize db structures. 4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined) - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for compressed solid block (if _LZMA_IN_CB is not defined) - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. EXIT codes ----------- 7z Decoder functions can return one of the following codes: #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) LZMA Defines ------------ _LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements _SZ_FILE_SIZE_64 - define it if you need support for files larger than 4 GB _SZ_NO_INT_64 - define it if your compiler doesn't support long long int _LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs. _SZ_ONE_DIRECTORY - define it if you want to locate all source files to one directory _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zAlloc.c ================================================ /* 7zAlloc.c */ #include #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include #endif #include int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include #include "7zTypes.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void InitCrcTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCrcPoly; else r >>= 1; g_CrcTable[i] = r; } } void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } void CrcUpdateByte(UInt32 *crc, Byte b) { *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); } void CrcUpdateUInt16(UInt32 *crc, UInt16 v) { CrcUpdateByte(crc, (Byte)v); CrcUpdateByte(crc, (Byte)(v >> 8)); } void CrcUpdateUInt32(UInt32 *crc, UInt32 v) { int i; for (i = 0; i < 4; i++) CrcUpdateByte(crc, (Byte)(v >> (8 * i))); } void CrcUpdateUInt64(UInt32 *crc, UInt64 v) { int i; for (i = 0; i < 8; i++) { CrcUpdateByte(crc, (Byte)(v)); v >>= 8; } } void CrcUpdate(UInt32 *crc, const void *data, size_t size) { UInt32 v = *crc; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); *crc = v; } UInt32 CrcCalculateDigest(const void *data, size_t size) { UInt32 crc; CrcInit(&crc); CrcUpdate(&crc, data, size); return CrcGetDigest(&crc); } int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) { return (CrcCalculateDigest(data, size) == digest); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include #include "7zTypes.h" extern UInt32 g_CrcTable[256]; void InitCrcTable(); void CrcInit(UInt32 *crc); UInt32 CrcGetDigest(UInt32 *crc); void CrcUpdateByte(UInt32 *crc, Byte v); void CrcUpdateUInt16(UInt32 *crc, UInt16 v); void CrcUpdateUInt32(UInt32 *crc, UInt32 v); void CrcUpdateUInt64(UInt32 *crc, UInt64 v); void CrcUpdate(UInt32 *crc, const void *data, size_t size); UInt32 CrcCalculateDigest(const void *data, size_t size); int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zDecode.c ================================================ /* 7zDecode.c */ #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/LZMA_C/LzmaDecode.h" #endif CMethodID k_Copy = { { 0x0 }, 1 }; CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; size_t Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); *size = (SizeT)processedSize; if (processedSize > cb->Size) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; size_t inSize = 0; CCoderInfo *coder; if (folder->NumPackStreams != 1) return SZE_NOTIMPL; if (folder->NumCoders != 1) return SZE_NOTIMPL; coder = folder->Coders; *outSizeProcessed = 0; for (si = 0; si < folder->NumPackStreams; si++) inSize += (size_t)packSizes[si]; if (AreMethodsEqual(&coder->MethodID, &k_Copy)) { size_t i; if (inSize != outSize) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB for (i = 0; i < inSize;) { size_t j; Byte *inBuffer; size_t bufferSize; RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); if (bufferSize == 0) return SZE_DATA_ERROR; if (bufferSize > inSize - i) return SZE_FAIL; *outSizeProcessed += bufferSize; for (j = 0; j < bufferSize && i < inSize; j++, i++) outBuffer[i] = inBuffer[j]; } #else for (i = 0; i < inSize; i++) outBuffer[i] = inBuffer[i]; *outSizeProcessed = inSize; #endif return SZ_OK; } if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); *outSizeProcessed = (size_t)outSizeProcessedLoc; allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return SZ_OK; } return SZE_NOTIMPL; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSize = SzFolderGetUnPackSize(folder); #ifndef _LZMA_IN_CB CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); Byte *inBuffer = 0; size_t processedSize; #endif *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); if (res == SZ_OK && processedSize != (size_t)packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = (size_t)unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { size_t outRealSize; res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) { if (outRealSize == (size_t)unPackSize) { if (folder->UnPackCRCDefined) { if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) res = SZE_FAIL; } } else res = SZE_FAIL; } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) res = SZE_FAIL; } } } return res; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "7zTypes.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zCrc.h" #include "7zDecode.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size)) { if (size == 0) *p = 0; else { *p = allocFunc(size); RINOM(*p); } return SZ_OK; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc)); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ while(1) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) size += db->Database.PackSizes[packStreamIndex + i]; return size; } /* SZ_RESULT SzReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { Byte *inBuffer; size_t processedSize; RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc)); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc)); RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc)); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc)); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { RINOK(SzReadByte(sd, &mainByte)); coder->MethodID.IDSize = (Byte)(mainByte & 0xF); RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc)); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc)); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc)); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc)); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; while(1) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; while(1) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc)); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc)); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); while(1) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; size_t outRealSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc)); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, &outRealSize, allocTemp); RINOK(res) if (outRealSize != (UInt32)unPackSize) return SZE_FAIL; if (folder->UnPackCRCDefined) if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); CrcInit(&crc); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); CrcUpdateUInt64(&crc, nextHeaderOffset); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); CrcUpdateUInt64(&crc, nextHeaderSize); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); CrcUpdateUInt32(&crc, nextHeaderCRC); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CrcGetDigest(&crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) { while (1) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); /* #define CArchiveFileTime UInt64 */ typedef struct _CFileItem { /* CArchiveFileTime LastWriteTime; CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.26 Copyright (c) 1999-2005 Igor Pavlov (2005-08-02) */ #include #include #include #include "7zCrc.h" #include "7zIn.h" #include "7zExtract.h" typedef struct _CFileInStream { ISzInStream InStream; FILE *File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = fread(buffer, 1, size, s->File); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.30 Copyright (c) 1999-2005 Igor Pavlov 2005-11-20\n"); if (numargs == 1) { printf( "\nUsage: 7zDec \n\n" "\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; InitCrcTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; // if you need cache, use these 3 variables. // if you use external function, you can make these variable as static. UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0) Byte *outBuffer = 0; // it must be 0 before first call for each new archive. size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0) printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { FILE *outputHandle; UInt32 processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = fopen(fileName, "wb+"); if (outputHandle == 0) { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (fclose(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); fclose(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { int i; if (a1->IDSize != a2->IDSize) return 0; for (i = 0; i < a1->IDSize; i++) if (a1->ID[i] != a2->ID[i]) return 0; return 1; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "7zTypes.h" #define kMethodIDSize 15 typedef struct _CMethodID { Byte ID[kMethodIDSize]; Byte IDSize; } CMethodID; int AreMethodsEqual(CMethodID *a1, CMethodID *a2); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7zTypes.h ================================================ /* 7zTypes.h */ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef UInt32 #ifdef _LZMA_UINT32_IS_ULONG #define UInt32 unsigned long #else #define UInt32 unsigned int #endif #endif #ifndef Byte #define Byte unsigned char #endif #ifndef UInt16 #define UInt16 unsigned short #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifdef _SZ_NO_INT_64 #define UInt64 unsigned long #else #ifdef _MSC_VER #define UInt64 unsigned __int64 #else #define UInt64 unsigned long long int #endif #endif /* #define _SZ_FILE_SIZE_64 */ /* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_64 #define CFileSize UInt64 #else #define CFileSize UInt32 #endif #endif #define SZ_RESULT int #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zCrc.c # End Source File # Begin Source File SOURCE=.\7zCrc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # Begin Source File SOURCE=.\7zTypes.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/makefile ================================================ PROG = 7zDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zCrc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Archive/7z_C/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: 7zCrc.c $(CXX) $(CFLAGS) 7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { // return result ? S_OK: E_FAIL; #ifdef _WIN32 return result ? S_OK: (::GetLastError()); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef _WIN32 #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream bool COutFileStream::Create(LPCTSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #ifdef _WIN32 #ifndef _UNICODE bool COutFileStream::Create(LPCWSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #endif #endif STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef _WIN32 UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef _WIN32 #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways); #ifdef _WIN32 #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways); #endif #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" #include "../../Common/Alloc.h" CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS class CInBufferException { public: HRESULT ErrorCode; CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" #include "../../Common/Alloc.h" bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode != S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = FlushPart(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS struct COutBufferException { HRESULT ErrorCode; COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) break; } return S_OK; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" #include "BranchARM.c" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" #include "BranchARMThumb.c" UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchARM.c ================================================ // BranchARM.c #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (dest >> 16); data[i + 1] = (dest >> 8); data[i + 0] = dest; } } return i; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchARM.h ================================================ // BranchARM.h #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "Common/Types.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchARMThumb.c ================================================ // BranchARMThumb.c #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; UInt32 dest; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = 0xF0 | ((dest >> 19) & 0x7); data[i + 0] = (dest >> 11); data[i + 3] = 0xF8 | ((dest >> 8) & 0x7); data[i + 2] = (dest); i += 2; } } return i; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchARMThumb.h ================================================ // BranchARMThumb.h #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "Common/Types.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "Common/Alloc.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClass2b(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClassA(Name, id, subId) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderA(Name ## _Encoder) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchIA64.c ================================================ // BranchIA64.c #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; for (int slot = 0; slot < 3; slot++, bitPos += 41) { if (((mask >> slot) & 1) == 0) continue; UInt32 bytePos = (bitPos >> 3); UInt32 bitRes = bitPos & 0x7; // UInt64 instruction = *(UInt64 *)(data + i + bytePos); UInt64 instruction = 0; int j; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); UInt64 instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 // && (instNorm & 0x3F)== 0 ) { UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF); src |= ((instNorm >> 36) & 1) << 20; src <<= 4; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~(UInt64(0x8FFFFF) << 13); instNorm |= (UInt64(dest & 0xFFFFF) << 13); instNorm |= (UInt64(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); // *(UInt64 *)(data + i + bytePos) = instruction; for (j = 0; j < 6; j++) data[i + j + bytePos] = Byte(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchIA64.h ================================================ // BranchIA64.h #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "Common/Types.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchPPC.c ================================================ // BranchPPC.c #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { // PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 // || (data[i+3] & 3) == 3 ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = 0x48 | ((dest >> 24) & 0x3); data[i + 1] = (dest >> 16); data[i + 2] = (dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchPPC.h ================================================ // BranchPPC.h #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "Common/Types.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchSPARC.c ================================================ // BranchSPARC.c #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchSPARC.h ================================================ // BranchSPARC.h #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "Common/Types.h" UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" /* static int inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } */ #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; /* void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos) { *prevMask = 0; *prevPos = (UInt32)(-5); } */ UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding) { UInt32 bufferPos = 0; UInt32 limit; if (endPos < 5) return 0; if (nowPos - *prevPos > 5) *prevPos = nowPos - 5; limit = endPos - 5; while(bufferPos <= limit) { Byte b = buffer[bufferPos]; UInt32 offset; if (b != 0xE8 && b != 0xE9) { bufferPos++; continue; } offset = (nowPos + bufferPos - *prevPos); *prevPos = (nowPos + bufferPos); if (offset > 5) *prevMask = 0; else { UInt32 i; for (i = 0; i < offset; i++) { *prevMask &= 0x77; *prevMask <<= 1; } } b = buffer[bufferPos + 4]; if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] && (*prevMask >> 1) < 0x10) { UInt32 src = ((UInt32)(b) << 24) | ((UInt32)(buffer[bufferPos + 3]) << 16) | ((UInt32)(buffer[bufferPos + 2]) << 8) | (buffer[bufferPos + 1]); UInt32 dest; while(1) { UInt32 index; if (encoding) dest = (nowPos + bufferPos + 5) + src; else dest = src - (nowPos + bufferPos + 5); if (*prevMask == 0) break; index = kMaskToBitNumber[*prevMask >> 1]; b = (Byte)(dest >> (24 - index * 8)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index * 8)) - 1); } buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1)); buffer[bufferPos + 3] = (Byte)(dest >> 16); buffer[bufferPos + 2] = (Byte)(dest >> 8); buffer[bufferPos + 1] = (Byte)dest; bufferPos += 5; *prevMask = 0; } else { bufferPos++; *prevMask |= 1; if (Test86MSByte(b)) *prevMask |= 0x10; } } return bufferPos; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #ifndef UInt32 #define UInt32 unsigned int #endif #ifndef Byte #define Byte unsigned char #endif #define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); } UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" #include "BranchIA64.c" UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" #include "Windows/Defs.h" #include "BranchPPC.c" UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" #include "Windows/Defs.h" #include "BranchSPARC.c" UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" #include "Windows/Defs.h" #include "BranchX86.c" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" #include "BranchX86.h" struct CBranch86 { UInt32 _prevMask; UInt32 _prevPos; void x86Init() { x86_Convert_Init(_prevMask, _prevPos); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" #include "../../../Common/Alloc.h" static const int kBufferSize = 1 << 17; inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } #ifndef EXTRACT_ONLY static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CBCJ2_x86_Encoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder() { ::MidFree(_buffer); } HRESULT CBCJ2_x86_Encoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256; i++) _statusE8Encoder[i].Init(); _statusE9Encoder.Init(); _statusJccEncoder.Init(); CCoderReleaser releaser(this); CMyComPtr getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; while(true) { UInt32 processedSize = 0; while(true) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else if (IsJcc(prevByte, b)) _statusJccEncoder.Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); if (convert) { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 1); else _statusJccEncoder.Encode(&_rangeEncoder, 1); bufferPos += 5; if (b == 0xE8) { _callStream.WriteByte((Byte)(dest >> 24)); _callStream.WriteByte((Byte)(dest >> 16)); _callStream.WriteByte((Byte)(dest >> 8)); _callStream.WriteByte((Byte)(dest)); } else { _jumpStream.WriteByte((Byte)(dest >> 24)); _jumpStream.WriteByte((Byte)(dest >> 16)); _jumpStream.WriteByte((Byte)(dest >> 8)); _jumpStream.WriteByte((Byte)(dest)); } prevByte = nextByte; } else { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else _statusJccEncoder.Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256; i++) _statusE8Decoder[i].Init(); _statusE9Decoder.Init(); _statusJccDecoder.Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; while(true) { if (processedBytes > (1 << 20) && progress != NULL) { UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } processedBytes++; Byte b; if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { prevByte = b; continue; } bool status; if (b == 0xE8) status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1); else if (b == 0xE9) status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1); else status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1); if (status) { UInt32 src; if (b == 0xE8) { Byte b0; if(!_callStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } else { Byte b0; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" // {23170F69-40C1-278B-0303-010100000100} #define MyClass2_a(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClass_a(Name, id, subId) \ MyClass2_a(Name ## _Encoder, id, subId, 0x01) \ MyClass2_a(Name ## _Decoder, id, subId, 0x00) MyClass_a(BCJ2_x86, 0x01, 0x1B) const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CBCJ2_x86_Encoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CBCJ2_x86_Encoder(): _buffer(0) {}; ~CBCJ2_x86_Encoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder _statusE8Encoder[256]; NCompress::NRangeCoder::CBitEncoder _statusE9Encoder; NCompress::NRangeCoder::CBitEncoder _statusJccEncoder; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CBCJ2_x86_Encoder *_coder; public: CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CBCJ2_x86_Decoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder _statusE8Decoder[256]; NCompress::NRangeCoder::CBitDecoder _statusE9Decoder; NCompress::NRangeCoder::CBitDecoder _statusJccDecoder; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CBCJ2_x86_Decoder *_coder; public: CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h ================================================ // BinTree.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace BT_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderBinTree: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderBinTree(); virtual ~CMatchFinderBinTree(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h ================================================ // BinTree2.h #ifndef __BINTREE2_H #define __BINTREE2_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT2 #include "BinTree.h" #include "BinTreeMain.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h ================================================ // BinTree3.h #ifndef __BINTREE3_H #define __BINTREE3_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h ================================================ // BinTree3Z.h #ifndef __BINTREE3Z_H #define __BINTREE3Z_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ZIP #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h ================================================ // BinTree4.h #ifndef __BINTREE4_H #define __BINTREE4_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h ================================================ // BinTree4b.h #ifndef __BINTREE4B_H #define __BINTREE4B_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4B #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h ================================================ // BinTreeMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 3; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderBinTree::CMatchFinderBinTree(): _hash(0), _cutValue(0xFF) { } void CMatchFinderBinTree::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderBinTree::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderBinTree::~CMatchFinderBinTree() { FreeMemory(); } STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1); return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2]; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; #endif _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; // We don't need tree in this case } else #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; break; } Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < len) distances[++maxLen] = delta - 1; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch() { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit != kNumHashDirectBytes) #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) break; Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; } void CMatchFinderBinTree::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2); for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderBinTree::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderBinTree::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderBinTree::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HC.h ================================================ // HC.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace HC_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderHC: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderHC(); virtual ~CMatchFinderHC(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HC2.h ================================================ // HC2.h #ifndef __HC2_H #define __HC2_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC2 #include "HCMF.h" #include "HCMFMain.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HC3.h ================================================ // HC3.h #ifndef __HC3_H #define __HC3_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC3 #define HASH_ARRAY_2 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HC4.h ================================================ // HC4.h #ifndef __HC4_H #define __HC4_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h ================================================ // HC4b.h #ifndef __HC4B__H #define __HC4B__H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4b #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h ================================================ // HC.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace HC_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (16); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderHC::CMatchFinderHC(): _hash(0), _cutValue(16) { } void CMatchFinderHC::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderHC::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderHC::~CMatchFinderHC() { FreeMemory(); } STDMETHODIMP CMatchFinderHC::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderHC::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderHC::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *chain = _hash + kHashSizeSum; chain[_cyclicBufferPos] = curMatch; distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; } else #endif { UInt32 count = _cutValue; do { if(curMatch <= matchMinPos) break; Byte *pby1 = _buffer + curMatch; UInt32 currentLen = kNumHashDirectBytes; do { if (pby1[currentLen] != cur[currentLen]) break; } while(++currentLen != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < currentLen) distances[++maxLen] = delta - 1; if(currentLen == lenLimit) break; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); curMatch = chain[cyclicPos]; } while(--count != 0); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch() { if (_streamPos - _pos < kNumHashBytes) return; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif _hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue]; _hash[hashValue] = _pos; } void CMatchFinderHC::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = kHashSizeSum + _cyclicBufferSize; for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderHC::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderHC::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderHC::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/IMatchFinder.h ================================================ // MatchFinders/IMatchFinder.h #ifndef __IMATCHFINDER_H #define __IMATCHFINDER_H // {23170F69-40C1-278A-0000-000200010000} DEFINE_GUID(IID_IInWindowStream, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000") IInWindowStream: public IUnknown { STDMETHOD(Init)(ISequentialInStream *inStream) PURE; STDMETHOD_(void, ReleaseStream)() PURE; STDMETHOD(MovePos)() PURE; STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020000} DEFINE_GUID(IID_IMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000") IMatchFinder: public IInWindowStream { STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE; STDMETHOD_(void, DummyLongestMatch)() PURE; }; // {23170F69-40C1-278A-0000-000200020100} DEFINE_GUID(IID_IMatchFinderCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100") IMatchFinderCallback: public IUnknown { STDMETHOD(BeforeChangingBufferPos)() PURE; STDMETHOD(AfterChangingBufferPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020200} DEFINE_GUID(IID_IMatchFinderSetCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200") IMatchFinderSetCallback: public IUnknown { STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE; }; /* // {23170F69-40C1-278A-0000-000200030000} DEFINE_GUID(IID_IInitMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000") IMatchFinderInit: public IUnknown { STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/LZInWindow.cpp ================================================ // LZInWindow.cpp #include "StdAfx.h" #include "LZInWindow.h" #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" void CLZInWindow::Free() { ::BigFree(_bufferBase); _bufferBase = 0; } bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == 0 || _blockSize != blockSize) { Free(); _blockSize = blockSize; if (_blockSize != 0) _bufferBase = (Byte *)::BigAlloc(_blockSize); } _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; if (_blockSize == 0) return true; return (_bufferBase != 0); } HRESULT CLZInWindow::Init(ISequentialInStream *stream) { _stream = stream; _buffer = _bufferBase; _pos = 0; _streamPos = 0; _streamEndWasReached = false; return ReadBlock(); } /* void CLZInWindow::ReleaseStream() { _stream.Release(); } */ /////////////////////////////////////////// // ReadBlock // In State: // (_buffer + _streamPos) <= (_bufferBase + _blockSize) // Out State: // _posLimit <= _blockSize - _keepSizeAfter; // if(_streamEndWasReached == false): // _streamPos >= _pos + _keepSizeAfter // _posLimit = _streamPos - _keepSizeAfter; // else // HRESULT CLZInWindow::ReadBlock() { if(_streamEndWasReached) return S_OK; while(true) { UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos; if(size == 0) return S_OK; UInt32 numReadBytes; RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; const Byte *pointerToPostion = _buffer + _posLimit; if(pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); _streamEndWasReached = true; return S_OK; } _streamPos += numReadBytes; if(_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; return S_OK; } } } void CLZInWindow::MoveBlock() { BeforeMoveBlock(); UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore; UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset; memmove(_bufferBase, _bufferBase + offset, numBytes); _buffer -= offset; AfterMoveBlock(); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/LZInWindow.h ================================================ // LZInWindow.h #ifndef __LZ_IN_WINDOW_H #define __LZ_IN_WINDOW_H #include "../../IStream.h" class CLZInWindow { Byte *_bufferBase; // pointer to buffer with data ISequentialInStream *_stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream const Byte *_pointerToLastSafePosition; protected: Byte *_buffer; // Pointer to virtual Buffer begin UInt32 _blockSize; // Size of Allocated memory block UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream virtual void BeforeMoveBlock() {}; virtual void AfterMoveBlock() {}; void MoveBlock(); virtual HRESULT ReadBlock(); void Free(); public: CLZInWindow(): _bufferBase(0) {} virtual ~CLZInWindow() { Free(); } bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); HRESULT Init(ISequentialInStream *stream); // void ReleaseStream(); Byte *GetBuffer() const { return _buffer; } const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } HRESULT MovePos() { _pos++; if (_pos > _posLimit) { const Byte *pointerToPostion = _buffer + _pos; if(pointerToPostion > _pointerToLastSafePosition) MoveBlock(); return ReadBlock(); } else return S_OK; } Byte GetIndexByte(Int32 index)const { return _buffer[(size_t)_pos + index]; } // index + limit have not to exceed _keepSizeAfter; UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const { if(_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; Byte *pby = _buffer + (size_t)_pos + index; UInt32 i; for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); return i; } UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } void ReduceOffsets(Int32 subValue) { _buffer += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "../../../Common/Alloc.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" /* #ifndef _NO_EXCEPTIONS class CLZOutWindowException { public: HRESULT ErrorCode; CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif */ typedef COutBufferException CLZOutWindowException; class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) { if (!_overDict) return false; pos += _bufferSize; } do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat.h ================================================ // Pat.h // #ifndef __PATRICIA__H // #define __PATRICIA__H #include "../../../../Common/MyCom.h" #include "../../../../Common/Types.h" #include "../LZInWindow.h" namespace PAT_NAMESPACE { struct CNode; typedef CNode *CNodePointer; // #define __AUTO_REMOVE // #define __NODE_4_BITS // #define __NODE_3_BITS // #define __NODE_2_BITS // #define __NODE_2_BITS_PADDING // #define __HASH_3 typedef UInt32 CIndex; #ifdef __NODE_4_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else #ifdef __NODE_3_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else typedef UInt32 CIndex; typedef UInt32 CSameBitsType; typedef CIndex CIndex2; #endif #endif const UInt32 kNumBitsInIndex = sizeof(CIndex) * 8; const UInt32 kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // don't change kMatchStartValue definition, since it is used in // PatMain.h: typedef CIndex CMatchPointer; const UInt32 kDescendantEmptyValue = kMatchStartValue - 1; union CDescendant { CIndex NodePointer; CMatchPointer MatchPointer; bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; } bool IsNode() const { return NodePointer < kDescendantEmptyValue; } bool IsMatch() const { return NodePointer > kDescendantEmptyValue; } void MakeEmpty() { NodePointer = kDescendantEmptyValue; } }; #undef MY_BYTE_SIZE #ifdef __NODE_4_BITS #define MY_BYTE_SIZE 8 const UInt32 kNumSubBits = 4; #else #ifdef __NODE_3_BITS #define MY_BYTE_SIZE 9 const UInt32 kNumSubBits = 3; #else #define MY_BYTE_SIZE 8 #ifdef __NODE_2_BITS const UInt32 kNumSubBits = 2; #else const UInt32 kNumSubBits = 1; #endif #endif #endif const UInt32 kNumSubNodes = 1 << kNumSubBits; const UInt32 kSubNodesMask = kNumSubNodes - 1; struct CNode { CIndex2 LastMatch; CSameBitsType NumSameBits; union { CDescendant Descendants[kNumSubNodes]; UInt32 NextFreeNode; }; #ifdef __NODE_2_BITS #ifdef __NODE_2_BITS_PADDING UInt32 Padding[2]; #endif #endif }; #undef kIDNumBitsByte #undef kIDNumBitsString #ifdef __NODE_4_BITS #define kIDNumBitsByte 0x30 #define kIDNumBitsString TEXT("4") #else #ifdef __NODE_3_BITS #define kIDNumBitsByte 0x20 #define kIDNumBitsString TEXT("3") #else #ifdef __NODE_2_BITS #define kIDNumBitsByte 0x10 #define kIDNumBitsString TEXT("2") #else #define kIDNumBitsByte 0x00 #define kIDNumBitsString TEXT("1") #endif #endif #endif #undef kIDManualRemoveByte #undef kIDManualRemoveString #ifdef __AUTO_REMOVE #define kIDManualRemoveByte 0x00 #define kIDManualRemoveString TEXT("") #else #define kIDManualRemoveByte 0x08 #define kIDManualRemoveString TEXT("R") #endif #undef kIDHash3Byte #undef kIDHash3String #ifdef __HASH_3 #define kIDHash3Byte 0x04 #define kIDHash3String TEXT("H") #else #define kIDHash3Byte 0x00 #define kIDHash3String TEXT("") #endif #undef kIDUse3BytesByte #undef kIDUse3BytesString #define kIDUse3BytesByte 0x00 #define kIDUse3BytesString TEXT("") #undef kIDPaddingByte #undef kIDPaddingString #ifdef __NODE_2_BITS_PADDING #define kIDPaddingByte 0x01 #define kIDPaddingString TEXT("P") #else #define kIDPaddingByte 0x00 #define kIDPaddingString TEXT("") #endif // #undef kIDString // #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String // {23170F69-40C1-278C-01XX-0000000000} DEFINE_GUID(PAT_CLSID, 0x23170F69, 0x40C1, 0x278C, 0x01, kIDNumBitsByte | kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // III(PAT_NAMESPACE) class CPatricia: public IMatchFinder, public IMatchFinderSetCallback, public CMyUnknownImp, CLZInWindow { MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *aStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); void FreeMemory(); public: CPatricia(); ~CPatricia(); UInt32 _sizeHistory; UInt32 _matchMaxLen; CDescendant *m_HashDescendants; #ifdef __HASH_3 CDescendant *m_Hash2Descendants; #endif CNode *m_Nodes; UInt32 m_FreeNode; UInt32 m_FreeNodeMax; #ifdef __AUTO_REMOVE UInt32 m_NumUsedNodes; UInt32 m_NumNodes; #else bool m_SpecialRemoveMode; #endif bool m_SpecialMode; UInt32 m_NumNotChangedCycles; UInt32 *m_TmpBacks; CMyComPtr m_Callback; virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); void ChangeLastMatch(UInt32 hashValue); #ifdef __AUTO_REMOVE void TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos); void TestRemoveNodes(); void RemoveNode(UInt32 index); void TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue); void TestRemoveNodesAndNormalize(); #else void NormalizeDescendant(CDescendant &descendant, UInt32 subValue); void Normalize(); void RemoveMatch(); #endif private: void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos) { while((aByteXOR & kSubNodesMask) == 0) { aByteXOR >>= kNumSubBits; aByte >>= kNumSubBits; aNumSameBits -= kNumSubBits; } // Insert New Node CNodePointer aNewNode = &m_Nodes[m_FreeNode]; UInt32 aNodeIndex = *aNodePointerPointer; *aNodePointerPointer = m_FreeNode; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = aByte & kSubNodesMask; UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex; aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits); aNewNode->LastMatch = aPos; aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits); } void AddLeafNode(CNodePointer aNode, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos, UInt32 aDescendantIndex) { for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits) { aByte >>= kNumSubBits; aByteXOR >>= kNumSubBits; } UInt32 aNewNodeIndex = m_FreeNode; CNodePointer aNewNode = &m_Nodes[m_FreeNode]; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = (aByte & kSubNodesMask); UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].MatchPointer = aNode->Descendants[aDescendantIndex].MatchPointer; aNewNode->NumSameBits = CSameBitsType(aNumSameBits); aNewNode->LastMatch = aPos; aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex; } }; } // #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h ================================================ // Pat2.h #ifndef __PAT2__H #define __PAT2__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2 #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2 #define __AUTO_REMOVE #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h ================================================ // Pat2H.h #ifndef __PAT2H__H #define __PAT2H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2H #define __AUTO_REMOVE #define __NODE_2_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #undef __HASH_3 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h ================================================ // Pat2R.h #ifndef __PAT2R__H #define __PAT2R__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2R #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2R #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __NODE_2_BITS #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h ================================================ // Pat3H.h #ifndef __PAT3H__H #define __PAT3H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat3H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat3H #define __AUTO_REMOVE #define __NODE_3_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_3_BITS #undef __HASH_3 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h ================================================ // Pat4H.h #ifndef __PAT4H__H #define __PAT4H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat4H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat4H #define __AUTO_REMOVE #define __NODE_4_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_4_BITS #undef __HASH_3 #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h ================================================ // PatMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/Alloc.h" namespace PAT_NAMESPACE { STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CPatricia::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CPatricia::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } const UInt32 kMatchStartValue2 = 2; const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1; const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1; #ifdef __HASH_3 static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kNumHash2Bytes = 2; static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes); static const UInt32 kPrevHashSize = kNumHash2Bytes; #else static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kPrevHashSize = 0; #endif CPatricia::CPatricia(): m_HashDescendants(0), #ifdef __HASH_3 m_Hash2Descendants(0), #endif m_Nodes(0), m_TmpBacks(0) { } CPatricia::~CPatricia() { FreeMemory(); } void CPatricia::FreeMemory() { MyFree(m_TmpBacks); m_TmpBacks = 0; ::BigFree(m_Nodes); m_Nodes = 0; ::BigFree(m_HashDescendants); m_HashDescendants = 0; #ifdef __HASH_3 ::BigFree(m_Hash2Descendants); m_Hash2Descendants = 0; CLZInWindow::Free(); #endif } STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { FreeMemory(); int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8; if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits))) return E_INVALIDARG; const UInt32 kAlignMask = (1 << 16) - 1; UInt32 windowReservSize = historySize; windowReservSize += kAlignMask; windowReservSize &= ~(kAlignMask); const UInt32 kMinReservSize = (1 << 19); if (windowReservSize < kMinReservSize) windowReservSize = kMinReservSize; windowReservSize += 256; if (!CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize)) return E_OUTOFMEMORY; _sizeHistory = historySize; _matchMaxLen = matchMaxLen; m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant)); if (m_HashDescendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #ifdef __HASH_3 m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant)); if (m_Hash2Descendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #endif #ifdef __AUTO_REMOVE #ifdef __HASH_3 m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19); #else m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10); #endif #else UInt32 m_NumNodes = historySize; #endif const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1); if (m_NumNodes + 32 > kMaxNumNodes) return E_INVALIDARG; // m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode)); m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode)); if (m_Nodes == 0) { FreeMemory(); return E_OUTOFMEMORY; } m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32)); if (m_TmpBacks == 0) { FreeMemory(); return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream) { RINOK(CLZInWindow::Init(aStream)); // memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0])); #ifdef __HASH_3 for (UInt32 i = 0; i < kHash2Size; i++) m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2; #else for (UInt32 i = 0; i < kHashSize; i++) m_HashDescendants[i].MakeEmpty(); #endif m_Nodes[0].NextFreeNode = 1; m_FreeNode = 0; m_FreeNodeMax = 0; #ifdef __AUTO_REMOVE m_NumUsedNodes = 0; #else m_SpecialRemoveMode = false; #endif m_SpecialMode = false; return S_OK; } STDMETHODIMP_(void) CPatricia::ReleaseStream() { // CLZInWindow::ReleaseStream(); } // pos = _pos + kNumHashBytes // fullCurrentLimit = currentLimit + kNumHashBytes // fullMatchLen = matchLen + kNumHashBytes void CPatricia::ChangeLastMatch(UInt32 hashValue) { UInt32 pos = _pos + kNumHashBytes - 1; UInt32 descendantIndex; const Byte *currentBytePointer = _buffer + pos; UInt32 numLoadedBits = 0; Byte curByte = 0; // = 0 to disable warning of GCC CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer]; while(true) { UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits < numSameBits) { numSameBits -= numLoadedBits; currentBytePointer += (numSameBits / MY_BYTE_SIZE); numSameBits %= MY_BYTE_SIZE; curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } curByte >>= numSameBits; numLoadedBits -= numSameBits; } if(numLoadedBits == 0) { curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } descendantIndex = (curByte & kSubNodesMask); node->LastMatch = pos; numLoadedBits -= kNumSubBits; curByte >>= kNumSubBits; if(node->Descendants[descendantIndex].IsNode()) node = &m_Nodes[node->Descendants[descendantIndex].NodePointer]; else break; } node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; } UInt32 CPatricia::GetLongestMatch(UInt32 *distances) { UInt32 fullCurrentLimit; if (_pos + _matchMaxLen <= _streamPos) fullCurrentLimit = _matchMaxLen; else { fullCurrentLimit = _streamPos - _pos; if(fullCurrentLimit < kNumHashBytes) return 0; } UInt32 pos = _pos + kNumHashBytes; #ifdef __HASH_3 UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1]; UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2) { if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2) { UInt32 base = hashValue & 0xFFFF00; for (UInt32 i = 0; i < 0x100; i++) m_HashDescendants[base + i].MakeEmpty(); } hash2Descendant.MatchPointer = pos + kMatchStartValue2; hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1; hash2Descendant.MatchPointer = pos + kMatchStartValue2; #ifdef __AUTO_REMOVE if (distances[kNumHash2Bytes] >= _sizeHistory) { if (hashDescendant.IsNode()) RemoveNode(hashDescendant.NodePointer); hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } #endif if (fullCurrentLimit == kNumHash2Bytes) return kNumHash2Bytes; #else UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(m_SpecialMode) { if(hashDescendant.IsMatch()) m_NumNotChangedCycles = 0; if(m_NumNotChangedCycles >= _sizeHistory - 1) { ChangeLastMatch(hashValue); m_NumNotChangedCycles = 0; } if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2)) { if(hashDescendant.IsMatch()) hashDescendant.MatchPointer = pos + kMatchStartValue; else m_NumNotChangedCycles++; for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++) distances[i] = 0; return fullCurrentLimit; } else if(m_NumNotChangedCycles > 0) ChangeLastMatch(hashValue); m_SpecialMode = false; } if(hashDescendant.IsEmpty()) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } UInt32 currentLimit = fullCurrentLimit - kNumHashBytes; if(hashDescendant.IsMatch()) { CMatchPointer matchPointer = hashDescendant.MatchPointer; UInt32 backReal = pos - (matchPointer - kMatchStartValue); UInt32 back = backReal - 1; #ifdef __AUTO_REMOVE if (back >= _sizeHistory) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } #endif UInt32 matchLen; distances += kNumHashBytes; Byte *buffer = _buffer + pos; for(matchLen = 0; true; matchLen++) { *distances++ = back; if (matchLen == currentLimit) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kNumHashBytes + matchLen; } if (buffer[matchLen] != buffer[(size_t)matchLen - backReal]) break; } // UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit); UInt32 fullMatchLen = matchLen + kNumHashBytes; hashDescendant.NodePointer = m_FreeNode; CNodePointer node = &m_Nodes[m_FreeNode]; m_FreeNode = node->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].NodePointer = kDescendantEmptyValue; node->LastMatch = pos; Byte byteNew = GetIndexByte(fullMatchLen); Byte byteOld = GetIndexByte(fullMatchLen - backReal); Byte bitsNew, bitsOld; UInt32 numSameBits = matchLen * MY_BYTE_SIZE; while (true) { bitsNew = (byteNew & kSubNodesMask); bitsOld = (byteOld & kSubNodesMask); if(bitsNew != bitsOld) break; byteNew >>= kNumSubBits; byteOld >>= kNumSubBits; numSameBits += kNumSubBits; } node->NumSameBits = CSameBitsType(numSameBits); node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue; node->Descendants[bitsOld].MatchPointer = matchPointer; return fullMatchLen; } const Byte *baseCurrentBytePointer = _buffer + pos; const Byte *currentBytePointer = baseCurrentBytePointer; UInt32 numLoadedBits = 0; Byte curByte = 0; CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[*nodePointerPointer]; distances += kNumHashBytes; const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit; const Byte *currentAddingOffset = _buffer; #ifdef __AUTO_REMOVE UInt32 lowPos; if (pos > _sizeHistory) lowPos = pos - _sizeHistory; else lowPos = 0; #endif while(true) { #ifdef __AUTO_REMOVE if (node->LastMatch < lowPos) { RemoveNode(*nodePointerPointer); *nodePointerPointer = pos + kMatchStartValue; if (currentBytePointer == baseCurrentBytePointer) return kPrevHashSize; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif if(numLoadedBits == 0) { *distances++ = pos - node->LastMatch - 1; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = 0; return fullCurrentLimit; } curByte = (*currentBytePointer++); currentAddingOffset++; numLoadedBits = MY_BYTE_SIZE; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >> (MY_BYTE_SIZE - numLoadedBits)) ^ curByte; while(numLoadedBits <= numSameBits) { if(byteXOR != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } *distances++ = pos - node->LastMatch - 1; numSameBits -= numLoadedBits; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits); return fullCurrentLimit; } numLoadedBits = MY_BYTE_SIZE; curByte = (*currentBytePointer++); byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch)); currentAddingOffset++; } if((byteXOR & ((1 << numSameBits) - 1)) != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } curByte >>= numSameBits; numLoadedBits -= numSameBits; } UInt32 descendantIndex = (curByte & kSubNodesMask); numLoadedBits -= kNumSubBits; nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; UInt32 nextNodeIndex = *nodePointerPointer; node->LastMatch = pos; if (nextNodeIndex < kDescendantEmptyValue) { curByte >>= kNumSubBits; node = &m_Nodes[nextNodeIndex]; } else if (nextNodeIndex == kDescendantEmptyValue) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } else break; } UInt32 descendantIndex = (curByte & kSubNodesMask); curByte >>= kNumSubBits; CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer; CMatchPointer realMatchPointer; realMatchPointer = matchPointer - kMatchStartValue; #ifdef __AUTO_REMOVE if (realMatchPointer < lowPos) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif Byte byteXOR; UInt32 numSameBits = 0; if(numLoadedBits != 0) { Byte matchByte = *(currentAddingOffset + realMatchPointer -1); matchByte >>= (MY_BYTE_SIZE - numLoadedBits); byteXOR = matchByte ^ curByte; if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } numSameBits += numLoadedBits; } const Byte *matchBytePointer = _buffer + realMatchPointer + (currentBytePointer - baseCurrentBytePointer); for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE) { curByte = (*currentBytePointer++); *distances++ = pos - realMatchPointer - 1; byteXOR = curByte ^ (*matchBytePointer++); if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } } *distances = pos - realMatchPointer - 1; node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; if(*distances == 0) { m_SpecialMode = true; m_NumNotChangedCycles = 0; } return fullCurrentLimit; } STDMETHODIMP_(void) CPatricia::DummyLongestMatch() { GetLongestMatch(m_TmpBacks); } // ------------------------------------ // Remove Match typedef Byte CRemoveDataWord; static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord); #ifndef __AUTO_REMOVE void CPatricia::RemoveMatch() { if(m_SpecialRemoveMode) { if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) == GetIndexByte(_matchMaxLen - _sizeHistory)) return; m_SpecialRemoveMode = false; } UInt32 pos = _pos + kNumHashBytes - _sizeHistory; #ifdef __HASH_3 const Byte *pp = _buffer + _pos - _sizeHistory; UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1]; UInt32 hashValue = (hash2Value << 8) | pp[2]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; if (hash2Descendant >= kMatchStartValue2) if(hash2Descendant.MatchPointer == pos + kMatchStartValue2) hash2Descendant.MatchPointer = kDescendantEmptyValue2; #else UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) | (UInt32(GetIndexByte(0 - _sizeHistory)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(hashDescendant.IsEmpty()) return; if(hashDescendant.IsMatch()) { if(hashDescendant.MatchPointer == pos + kMatchStartValue) hashDescendant.MakeEmpty(); return; } UInt32 descendantIndex; const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos); UInt32 numLoadedBits = 0; CRemoveDataWord curWord = 0; // = 0 to disable GCC warning CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[hashDescendant.NodePointer]; while(true) { if(numLoadedBits == 0) { curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits <= numSameBits) { numSameBits -= numLoadedBits; currentPointer += (numSameBits / kSizeRemoveDataWordInBits); numSameBits %= kSizeRemoveDataWordInBits; curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } curWord >>= numSameBits; numLoadedBits -= numSameBits; } descendantIndex = (curWord & kSubNodesMask); numLoadedBits -= kNumSubBits; curWord >>= kNumSubBits; UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer; if (nextNodeIndex < kDescendantEmptyValue) { nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; node = &m_Nodes[nextNodeIndex]; } else break; } if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue) { const Byte *currentBytePointer = _buffer + _pos - _sizeHistory; const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen; for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++) if(*currentBytePointer != *(currentBytePointer+1)) return; m_SpecialRemoveMode = true; return; } UInt32 numNodes = 0, numMatches = 0; UInt32 i; for (i = 0; i < kNumSubNodes; i++) { UInt32 nodeIndex = node->Descendants[i].NodePointer; if (nodeIndex < kDescendantEmptyValue) numNodes++; else if (nodeIndex > kDescendantEmptyValue) numMatches++; } numMatches -= 1; if (numNodes + numMatches > 1) { node->Descendants[descendantIndex].MakeEmpty(); return; } if(numNodes == 1) { UInt32 i; for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsNode()) break; UInt32 nextNodeIndex = node->Descendants[i].NodePointer; CNodePointer nextNode = &m_Nodes[nextNodeIndex]; nextNode->NumSameBits += node->NumSameBits + kNumSubBits; *node = *nextNode; nextNode->NextFreeNode = m_FreeNode; m_FreeNode = nextNodeIndex; return; } UInt32 matchPointer = 0; // = 0 to disable GCC warning for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsMatch() && i != descendantIndex) { matchPointer = node->Descendants[i].MatchPointer; break; } node->NextFreeNode = m_FreeNode; m_FreeNode = *nodePointerPointer; *nodePointerPointer = matchPointer; } #endif // Commented code is more correct, but it gives warning // on GCC: (1 << 32) // So we use kMatchStartValue twice: // kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // must be defined in Pat.h /* const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) - kMatchStartValue - kNumHashBytes - 1; */ const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1; STDMETHODIMP CPatricia::MovePos() { #ifndef __AUTO_REMOVE if(_pos >= _sizeHistory) RemoveMatch(); #endif RINOK(CLZInWindow::MovePos()); #ifdef __AUTO_REMOVE if (m_NumUsedNodes >= m_NumNodes) TestRemoveNodes(); #endif if (_pos >= kNormalizeStartPos) { #ifdef __AUTO_REMOVE TestRemoveNodesAndNormalize(); #else Normalize(); #endif } return S_OK; } #ifndef __AUTO_REMOVE void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) descendant.MatchPointer = descendant.MatchPointer - subValue; else { CNode &node = m_Nodes[descendant.NodePointer]; node.LastMatch = node.LastMatch - subValue; for (UInt32 i = 0; i < kNumSubNodes; i++) NormalizeDescendant(node.Descendants[i], subValue); } } void CPatricia::Normalize() { UInt32 subValue = _pos - _sizeHistory; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) NormalizeDescendant(m_HashDescendants[base + i], subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) NormalizeDescendant(m_HashDescendants[hash], subValue); #endif } #else void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos) { CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsEmpty()) continue; if (descendant2.IsMatch()) { if (descendant2.MatchPointer < limitPos) descendant2.MakeEmpty(); else { numChilds++; childIndex = i; } } else { TestRemoveDescendant(descendant2, limitPos); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } } if (numChilds > 1) return; CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::RemoveNode(UInt32 index) { CNode &node = m_Nodes[index]; for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsNode()) RemoveNode(descendant2.NodePointer); } node.NextFreeNode = m_FreeNode; m_FreeNode = index; m_NumUsedNodes--; } void CPatricia::TestRemoveNodes() { UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) { CDescendant &descendant = m_HashDescendants[base + i]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) { CDescendant &descendant = m_HashDescendants[hash]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } #endif } void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); else descendant.MatchPointer = descendant.MatchPointer - subValue; return; } CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } if (numChilds > 1) { node.LastMatch = node.LastMatch - subValue; return; } CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::TestRemoveNodesAndNormalize() { UInt32 subValue = _pos - _sizeHistory; UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; else descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue); #endif } #endif STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); while (true) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); return SetDecoderPropertiesRaw(lc, lp, pb, dictionarySize); } STDMETHODIMP CDecoder::SetDecoderPropertiesRaw(int lc, int lp, int pb, UInt32 dictionarySize) { if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { if (_outSizeDefined = (outSize != NULL)) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifdef _ST_MODE STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, #ifdef _ST_MODE public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifdef _ST_MODE MY_UNKNOWN_IMP4( ICompressSetDecoderProperties2, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP1( ICompressSetDecoderProperties2) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifdef _ST_MODE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // for minimal compressing code size define these: // #define COMPRESS_MF_BT // #define COMPRESS_MF_BT4 #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC) #define COMPRESS_MF_BT #define COMPRESS_MF_PAT #define COMPRESS_MF_HC #endif #ifdef COMPRESS_MF_BT #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B) #define COMPRESS_MF_BT2 #define COMPRESS_MF_BT3 #define COMPRESS_MF_BT4 #define COMPRESS_MF_BT4B #endif #ifdef COMPRESS_MF_BT2 #include "../LZ/BinTree/BinTree2.h" #endif #ifdef COMPRESS_MF_BT3 #include "../LZ/BinTree/BinTree3.h" #endif #ifdef COMPRESS_MF_BT4 #include "../LZ/BinTree/BinTree4.h" #endif #ifdef COMPRESS_MF_BT4B #include "../LZ/BinTree/BinTree4b.h" #endif #endif #ifdef COMPRESS_MF_PAT #include "../LZ/Patricia/Pat2.h" #include "../LZ/Patricia/Pat2H.h" #include "../LZ/Patricia/Pat3H.h" #include "../LZ/Patricia/Pat4H.h" #include "../LZ/Patricia/Pat2R.h" #endif #ifdef COMPRESS_MF_HC #include "../LZ/HashChain/HC3.h" #include "../LZ/HashChain/HC4.h" #endif #ifdef COMPRESS_MF_MT #include "../LZ/MT/MT.h" #endif namespace NCompress { namespace NLZMA { const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; enum { kBT2, kBT3, kBT4, kBT4B, kPat2, kPat2H, kPat3H, kPat4H, kPat2R, kHC3, kHC4 }; static const wchar_t *kMatchFinderIDs[] = { L"BT2", L"BT3", L"BT4", L"BT4B", L"PAT2", L"PAT2H", L"PAT3H", L"PAT4H", L"PAT2R", L"HC3", L"HC4" }; Byte g_FastPos[1024]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const { if(symbol < kNumLowSymbols) return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol); UInt32 price = _choice.GetPrice1(); if(symbol < kNumLowSymbols + kNumMidSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols); } return price; } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _dictionarySizePrev(UInt32(-1)), _numFastBytesPrev(UInt32(-1)), _matchFinderIndex(kBT4), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { _maxMode = false; _fastMode = false; } HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_matchFinder) { switch(_matchFinderIndex) { #ifdef COMPRESS_MF_BT #ifdef COMPRESS_MF_BT2 case kBT2: _matchFinder = new NBT2::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT3 case kBT3: _matchFinder = new NBT3::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4 case kBT4: _matchFinder = new NBT4::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4B case kBT4B: _matchFinder = new NBT4B::CMatchFinderBinTree; break; #endif #endif #ifdef COMPRESS_MF_PAT case kPat2: _matchFinder = new NPat2::CPatricia; break; case kPat2H: _matchFinder = new NPat2H::CPatricia; break; case kPat3H: _matchFinder = new NPat3H::CPatricia; break; case kPat4H: _matchFinder = new NPat4H::CPatricia; break; case kPat2R: _matchFinder = new NPat2R::CPatricia; break; #endif #ifdef COMPRESS_MF_HC case kHC3: _matchFinder = new NHC3::CMatchFinderHC; break; case kHC4: _matchFinder = new NHC4::CMatchFinderHC; break; #endif } if (_matchFinder == 0) return E_OUTOFMEMORY; #ifdef COMPRESS_MF_MT if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4))) { CMatchFinderMT *mfSpec = new CMatchFinderMT; if (mfSpec == 0) return E_OUTOFMEMORY; CMyComPtr mf = mfSpec; RINOK(mfSpec->SetMatchFinder(_matchFinder)); _matchFinder.Release(); _matchFinder = mf; } #endif } if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return S_OK; RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen * 2 + 1 - _numFastBytes)); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; return S_OK; } static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) { while (true) { wchar_t c = *testString; if (c >= 'a' && c <= 'z') c -= 0x20; if (*base != c) return false; if (c == 0) return true; base++; testString++; } } static int FindMatchFinder(const wchar_t *s) { for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) if (AreStringsEqual(kMatchFinderIDs[m], s)) return m; return -1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; int matchFinderIndexPrev = _matchFinderIndex; int m = FindMatchFinder(prop.bstrVal); if (m < 0) return E_INVALIDARG; _matchFinderIndex = m; if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } break; } #ifdef COMPRESS_MF_MT case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } _multiThread = newMultiThread; break; } #endif case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 28; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); // _repMatchLenEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } HRESULT CEncoder::MovePos(UInt32 num) { for (;num != 0; num--) { _matchFinder->DummyLongestMatch(); RINOK(_matchFinder->MovePos()); _additionalOffset++; } return S_OK; } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit) { back++; for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++); return i; } */ /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return S_OK; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } Byte currentByte = _matchFinder->GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if(lenMain < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for(len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); COptimal &optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); /* if (curOptimum.Prev1IsChar) for(int i = 0; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i]; */ } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 newLen; RINOK(ReadMatchDistances(newLen)); if(newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } UInt32 curPrice = curOptimum.Price; // Byte currentByte = _matchFinder->GetIndexByte(0 - 1); // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { // try Literal + rep0 UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) if (data[temp] != data[(size_t)temp - backOffset]) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while(lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (data[lenTest] != data[(size_t)lenTest - backOffset]) break; UInt32 lenTestTemp = lenTest; do { while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { // Try Match + Literal + Rep0 UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif)); } HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes) { lenRes = _matchFinder->GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes], kMatchMaxLen - lenRes); _additionalOffset++; return _matchFinder->MovePos(); } HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12))) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } } if (lenMain >= 2) { RINOK(ReadMatchDistances(_longestMatchLength)); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } for(UInt32 i = 0; i < kNumRepDistances; i++) { UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } } backRes = backMain + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 2); } backRes = UInt32(-1); lenRes = 1; return S_OK; } STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder) { _matchFinder = matchFinder; return S_OK; } HRESULT CEncoder::Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { _needReleaseMFStream = false; CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); while(true) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) return S_OK; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; return S_OK; } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { RINOK(_matchFinder->Init(_inStream)); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return S_OK; _finished = true; UInt64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); UInt32 len; // it's not used RINOK(ReadMatchDistances(len)); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); while(true) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos; UInt32 posState = UInt32(nowPos64) & _posStateMask; UInt32 len; HRESULT result; if (_fastMode) result = GetOptimumFast(UInt32(nowPos64), pos, len); else result = GetOptimum(UInt32(nowPos64), pos, len); RINOK(result); if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte); if(!_state.IsCharState()) { Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } else subCoder->Encode(&_rangeEncoder, curByte); _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); if(len == 1) _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0); else _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for(UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for(UInt32 i = kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; *finished = 0; return S_OK; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); } } void CEncoder::FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; for (; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } } } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = kAlignTableSize; } }} ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/IMatchFinder.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; extern Byte g_FastPos[1024]; inline UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } inline UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[GetState(pos, prevByte)]; } /* void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); } void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte matchByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, matchByte, symbol); } */ UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); UInt32 GetPrice(UInt32 symbol, UInt32 posState) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[symbol][posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[len][posState] = CEncoder::GetPrice(len, posState); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { CEncoder::Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } }; } class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { COptimal _optimum[kNumOpts]; CMyComPtr _matchFinder; // test it NRangeCoder::CEncoder _rangeEncoder; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen + 1]; bool _fastMode; bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _dictionarySizePrev; UInt32 _numFastBytesPrev; UInt64 lastPosSlotFillingPos; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; int _matchFinderIndex; #ifdef COMPRESS_MF_MT bool _multiThread; #endif bool _writeEndMark; bool _needReleaseMFStream; HRESULT ReadMatchDistances(UInt32 &len); HRESULT MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState); if(repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); void FillPosSlotPrices(); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseMFStream() { if (_matchFinder && _needReleaseMFStream) { _matchFinder->ReleaseStream(); _needReleaseMFStream = false; } } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // IInitMatchFinder interface STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Group "Pat" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\Patricia\Pat.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2R.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat3H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat4H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\PatMain.h # End Source File # End Group # Begin Group "BT" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\BinTree\BinTree.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree2.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3Z.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3ZMain.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4b.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTreeMain.h # End Source File # End Group # Begin Group "HC" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\HashChain\HC.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC2.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC3.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4b.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HCMain.h # End Source File # End Group # Begin Source File SOURCE=..\LZ\IMatchFinder.h # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.h # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\Branch\BranchX86.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\Alloc.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\String.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\String.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include #include #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBench.h" #include "LzmaRam.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kLitContext, kLitPos, kPosBits, kMatchFinder, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kSimple, false } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA inputFile outputFile [...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "\n" " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n" " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (n == 1) { PrintHelp(); return 0; } if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = 1 << 21; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 10; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchmark(stderr, numIterations, dictionary, mf.CompareNoCase(L"BT4") == 0); } bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr outStream; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; COutFileStream *outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 2; UInt32 numFastBytes = 128; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); /* NWindows::NCOM::CPropVariant properties[kNumProps]; properties[0] = UInt32(dictionary); properties[1] = UInt32(posStateBits); properties[2] = UInt32(litContextBits); properties[3] = UInt32(litPosBits); properties[4] = UInt32(algorithm); properties[5] = UInt32(numFastBytes); properties[6] = mf; properties[7] = eos; */ PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #include #endif #include "../../../Common/CRC.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" static const UInt32 kAdditionalSize = #ifdef _WIN32_WCE (1 << 20); #else (6 << 20); #endif static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public: CRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBitRandomGenerator { CRandomGenerator RG; UInt32 Value; int NumBits; public: void Init() { Value = 0; NumBits = 0; } UInt32 GetRnd(int numBits) { if (NumBits > numBits) { UInt32 result = Value & ((1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; UInt32 result = (Value << numBits); Value = RG.GetRnd(); result |= Value & ((1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG; UInt32 Pos; public: UInt32 BufferSize; Byte *Buffer; CBenchRandomGenerator(): Buffer(0) {} ~CBenchRandomGenerator() { delete []Buffer; } void Init() { RG.Init(); } void Set(UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd(len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } void Generate() { while(Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = Byte(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; UInt32 Pos; UInt32 Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, UInt32 size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CMyUnknownImp { UInt32 BufferSize; FILE *_f; public: UInt32 Pos; Byte *Buffer; CBenchmarkOutStream(): _f(0), Buffer(0) {} virtual ~CBenchmarkOutStream() { delete []Buffer; } void Init(FILE *f, UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; _f = f; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < BufferSize; i++) Buffer[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { fprintf(_f, "\nERROR: Buffer is full\n"); return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: CCRC CRC; MY_UNKNOWN_IMP void Init() { CRC.Init(); } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { CRC.Update(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; return GetTickCount(); #else return clock(); #endif } static UInt64 GetFreq() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; return 1000; #else return CLOCKS_PER_SEC; #endif } struct CProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { UInt64 ApprovedStart; UInt64 InSize; UInt64 Time; void Init() { InSize = 0; Time = 0; } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { if (*inSize >= ApprovedStart && InSize == 0) { Time = ::GetTimeCount(); InSize = *inSize; } return S_OK; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = GetFreq(); UInt64 elTime = elapsedTime; while(freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } /* static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } */ static void PrintRating(FILE *f, UInt64 rating) { fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000)); } static void PrintResults( FILE *f, UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024)); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(f, rating); } static void ThrowError(FILE *f, HRESULT result, const char *s) { fprintf(f, "\nError: "); if (result == E_ABORT) fprintf(f, "User break"); if (result == E_OUTOFMEMORY) fprintf(f, "Can not allocate memory"); else fprintf(f, s); fprintf(f, "\n"); } const wchar_t *bt2 = L"BT2"; const wchar_t *bt4 = L"BT4"; int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations == 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n"); return 1; } fprintf(f, "\n Compressing Decompressing\n\n"); NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream; CMyComPtr propStream = propStreamSpec; propStreamSpec->Init(f, kMaxLzmaPropSize); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMatchFinder }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = UInt32(dictionarySize); properties[1].vt = VT_BSTR; properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2; const UInt32 kBufferSize = dictionarySize + kAdditionalSize; const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) { fprintf(f, "\nError: Incorrect command\n"); return 1; } encoderSpec->WriteCoderProperties(propStream); CBenchRandomGenerator rg; rg.Init(); rg.Set(kBufferSize); rg.Generate(); CCRC crc; crc.Update(rg.Buffer, rg.BufferSize); CProgressInfo *progressInfoSpec = new CProgressInfo; CMyComPtr progressInfo = progressInfoSpec; progressInfoSpec->ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; for (UInt32 i = 0; i < numIterations; i++) { progressInfoSpec->Init(); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; inStreamSpec->Init(rg.Buffer, rg.BufferSize); CMyComPtr inStream = inStreamSpec; CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream; outStreamSpec->Init(f, kCompressedBufferSize); CMyComPtr outStream = outStreamSpec; HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo); UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time; UInt32 compressedSize = outStreamSpec->Pos; if(result != S_OK) { ThrowError(f, result, "Encoder Error"); return 1; } if (progressInfoSpec->InSize == 0) { fprintf(f, "\nError: Internal ERROR 1282\n"); return 1; } /////////////////////// // Decompressing CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr crcOutStream = crcOutStreamSpec; UInt64 decodeTime; for (int j = 0; j < 2; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK) { fprintf(f, "\nError: Set Decoder Properties Error\n"); return 1; } UInt64 outSize = kBufferSize; UInt64 startTime = ::GetTimeCount(); result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0); decodeTime = ::GetTimeCount() - startTime; if(result != S_OK) { ThrowError(f, result, "Decode Error"); return 1; } if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest()) { fprintf(f, "\nError: CRC Error\n"); return 1; } } UInt64 benchSize = kBufferSize - progressInfoSpec->InSize; PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); fprintf(f, "\n"); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } fprintf(f, "---------------------------------------------------\n"); PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, totalDecodeTime, kBufferSize * numIterations, true, totalCompressedSize); fprintf(f, " Average\n"); return 0; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LzmaBench_h #define __LzmaBench_h #include #include "../../../Common/Types.h" int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZE_FAIL (1) #define SZE_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZE_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1); } UInt32 minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZE_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZE_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZE_OUTOFMEMORY; } #endif } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../LZMA_C/LzmaDecode.h" #include "../Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0); } return 0; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) -I ../../../ LIBS = $(LIBS) oleaut32.lib user32.lib !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\Alloc.obj \ $O\CRC.obj \ $O\CommandLineParser.obj \ $O\String.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Vector.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ $O\LZOutWindow.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaRam.o \ LzmaRamDecode.o \ LzmaDecode.o \ BranchX86.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c LzmaDecode.o: ../LZMA_C/LzmaDecode.c $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c BranchX86.o: ../Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c ================================================ /* 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; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h ================================================ /* 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 #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 ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.27 Copyright (c) 1999-2005 Igor Pavlov (2005-08-07) 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 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) 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. */ #include "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; while(1) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ /* #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 #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 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include #include #include #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include #include #include #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/makefile ================================================ PROG = lzmaDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** OBJS = \ $O\LzmaTest.obj \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\LzmaTest.obj: $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_C/makefile.gcc ================================================ PROG = lzmadec CXX = gcc LIB = RM = rm -f CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 OBJS = LzmaTest.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaTest.o: LzmaTest.c $(CXX) $(CFLAGS) LzmaTest.c LzmaDecode.o: LzmaDecode.c $(CXX) $(CFLAGS) LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp ================================================ /* * lzma zlib simplified wrapper * * Copyright (c) 2005-2006 Oleg I. Vdovikin * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA */ /* * default values for encoder/decoder used by wrapper */ #include #define ZLIB_LC 0 #define ZLIB_LP 0 #define ZLIB_PB 2 #ifdef WIN32 #include #else #define INITGUID #endif #include "../../../Common/MyWindows.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #define STG_E_SEEKERROR ((HRESULT)0x80030019L) #define STG_E_MEDIUMFULL ((HRESULT)0x80030070L) class CInMemoryStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: CInMemoryStream(const Bytef *data, UInt64 size) : m_data(data), m_size(size), m_offset(0) {} virtual ~CInMemoryStream() {} MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (size > m_size - m_offset) size = m_size - m_offset; if (size) { memcpy(data, m_data + m_offset, size); } m_offset += size; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) { return Read(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_size) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(GetSize)(UInt64 *size) { *size = m_size; return S_OK; } protected: const Bytef *m_data; UInt64 m_size; UInt64 m_offset; }; class COutMemoryStream: public IOutStream, public CMyUnknownImp { public: COutMemoryStream(Bytef *data, UInt64 maxsize) : m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {} virtual ~COutMemoryStream() {} MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (size > m_maxsize - m_offset) size = m_maxsize - m_offset; if (size) { memcpy(m_data + m_offset, data, size); } m_offset += size; if (m_offset > m_size) m_size = m_offset; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) { return Write(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_maxsize) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(SetSize)(Int64 newSize) { if ((UInt64)newSize > m_maxsize) return STG_E_MEDIUMFULL; return S_OK; } protected: Bytef *m_data; UInt64 m_size; UInt64 m_maxsize; UInt64 m_offset; }; ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr outStream = outStreamSpec; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(1 << (level + 14)); properties[1].ulVal = UInt32(ZLIB_PB); properties[2].ulVal = UInt32(ZLIB_LC); // for normal files properties[3].ulVal = UInt32(ZLIB_LP); // for normal files properties[4].ulVal = UInt32(2); properties[5].ulVal = UInt32(128); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4"; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_TRUE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return Z_MEM_ERROR; // should not happen HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { return Z_MEM_ERROR; } else if (result != S_OK) { return Z_BUF_ERROR; // should not happen } UInt64 fileSize; outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr outStream = outStreamSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_LC, ZLIB_LP, ZLIB_PB, (1 << 23)) != S_OK) return Z_DATA_ERROR; UInt64 fileSize = *destLen; if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { return Z_DATA_ERROR; } outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/LZMA_Lib/makefile ================================================ PROG = liblzma.a CXX = g++ -O3 -Wall AR = ar RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ ZLib.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ StreamUtils.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(AR) r $(PROG) $(OBJS) ZLib.o: ZLib.cpp $(CXX) $(CFLAGS) ZLib.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template class CBitEncoder: public CBitModel { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template class CBitDecoder: public CBitModel { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template class CBitTreeEncoder { CBitEncoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template class CBitTreeDecoder { CBitDecoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template void ReverseBitTreeEncode(CBitEncoder *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template UInt32 ReverseBitTreeDecode(CBitDecoder *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" // "23170F69-40C1-278A-0000-000400xx0000" #define CODER_INTERFACE(i, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ struct i: public IUnknown CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription }; } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" // "23170F69-40C1-278A-0000-000300xx0000" #define STREAM_INTERFACE_SUB(i, b, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ struct i: public b #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Alloc.cpp ================================================ // Common/Alloc.cpp #include "StdAfx.h" #ifdef _WIN32 #include "MyWindows.h" #else #include #endif #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return ::malloc(size); } void MyFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif ::free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } static SIZE_T g_LargePageSize = #ifdef _WIN64 (1 << 21); #else (1 << 22); #endif typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); bool SetLargePageSize() { GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return false; SIZE_T size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return false; g_LargePageSize = size; return true; } void *BigAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif if (size >= (1 << 18)) { void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Alloc.h ================================================ // Common/Alloc.h #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size) throw(); void MyFree(void *address) throw(); #ifdef _WIN32 bool SetLargePageSize(); void *MidAlloc(size_t size) throw(); void MidFree(void *address) throw(); void *BigAlloc(size_t size) throw(); void BigFree(void *address) throw(); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" #include "CRC.h" static const UInt32 kCRCPoly = 0xEDB88320; UInt32 CCRC::Table[256]; void CCRC::InitTable() { for (UInt32 i = 0; i < 256; i++) { UInt32 r = i; for (int j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCRCPoly; else r >>= 1; CCRC::Table[i] = r; } } class CCRCTableInit { public: CCRCTableInit() { CCRC::InitTable(); } } g_CRCTableInit; void CCRC::UpdateByte(Byte b) { _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); } void CCRC::UpdateUInt16(UInt16 v) { UpdateByte(Byte(v)); UpdateByte(Byte(v >> 8)); } void CCRC::UpdateUInt32(UInt32 v) { for (int i = 0; i < 4; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::UpdateUInt64(UInt64 v) { for (int i = 0; i < 8; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::Update(const void *data, size_t size) { UInt32 v = _value; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); _value = v; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/CRC.h ================================================ // Common/CRC.h #ifndef __COMMON_CRC_H #define __COMMON_CRC_H #include #include "Types.h" class CCRC { UInt32 _value; public: static UInt32 Table[256]; static void InitTable(); CCRC(): _value(0xFFFFFFFF){}; void Init() { _value = 0xFFFFFFFF; } void UpdateByte(Byte v); void UpdateUInt16(UInt16 v); void UpdateUInt32(UInt32 v); void UpdateUInt64(UInt64 v); void Update(const void *data, size_t size); UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } static UInt32 CalculateDigest(const void *data, size_t size) { CCRC crc; crc.Update(data, size); return crc.GetDigest(); } static bool VerifyDigest(UInt32 digest, const void *data, size_t size) { return (CalculateDigest(data, size) == digest); } }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include #include namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include #include #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); while (true) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) return; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices) { indices.Clear(); int numUsedChars = 0; for(int i = 0; i < numForms; i++) { const CCommandSubCharsSet &set = forms[i]; int currentIndex = -1; int len = MyStringLen(set.Chars); for(int j = 0; j < len; j++) { wchar_t c = set.Chars[j]; int newIndex = commandString.Find(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.Find(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if(currentIndex == -1 && !set.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length()); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "Common/String.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); struct CCommandSubCharsSet { wchar_t *Chars; bool EmptyAllowed; }; // Returns: indices of finded chars; -1 if there is no match bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices); } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } template inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } template class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline bool operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return false; return true; } inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include #else #define INITGUID #include "MyGuidDef.h" #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include #else #define MIDL_INTERFACE(x) struct #endif #else #include #endif #include #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include #else #include // for wchar_t #include #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; }; typedef IUnknown *LPUNKNOWN; #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/String.cpp ================================================ // Common/String.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include #endif #include "Common/String.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { while (true) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/String.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include // #include #include "Vector.h" #ifdef _WIN32 #include "MyWindows.h" #endif static const char *kTrimDefaultCharSet = " \n\t"; template inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)CharUpperW((LPWSTR)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)CharLowerW((LPWSTR)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; while (true) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; while (true) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase charSet; for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / sizeof(kTrimDefaultCharSet[0])); i++) charSet += (T)kTrimDefaultCharSet[i]; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template CStringBase operator+(const CStringBase& s1, const CStringBase& s2) { CStringBase result(s1); result += s2; return result; } template CStringBase operator+(const CStringBase& s, T c) { CStringBase result(s); result += c; return result; } template CStringBase operator+(T c, const CStringBase& s) { CStringBase result(c); result += s; return result; } template CStringBase operator+(const CStringBase& s, const T * chars) { CStringBase result(s); result += chars; return result; } template CStringBase operator+(const T * chars, const CStringBase& s) { CStringBase result(chars); result += s; return result; } template bool operator==(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) == 0); } template bool operator<(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) < 0); } template bool operator==(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) == 0); } template bool operator==(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) == 0); } template bool operator!=(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) != 0); } template bool operator!=(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) != 0); } template bool operator!=(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase AString; typedef CStringBase UString; typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, NULL, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "Common/String.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT codePage) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; while(true) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; typedef int Int32; typedef unsigned int UInt32; #ifdef _MSC_VER typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Vector.cpp ================================================ // Common/Vector.cpp #include "StdAfx.h" #include #include "Vector.h" CBaseRecordVector::~CBaseRecordVector() { delete []((unsigned char *)_items); } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if(_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if(newCapacity <= _capacity) return; /* #ifndef _DEBUG static const unsigned int kMaxVectorSize = 0xF0000000; if(newCapacity < _size || ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize) throw 1052354; #endif */ unsigned char *p = new unsigned char[newCapacity * _itemSize]; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Common/Vector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } void Sort(int left, int right) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (operator[](i) < operator[](left)) Swap(++last, i); Swap(left, last); Sort(left, last); Sort(last + 1, right); } void Sort() { Sort(0, Size()); } void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (compare(&operator[](i), &operator[](left), param) < 0) Swap(++last, i); Swap(left, last); Sort(left, last, compare, param); Sort(last + 1, right, compare, param); } void Sort(int (*compare)(const T*, const T*, void *), void *param) { Sort(0, Size(), compare, param); } }; typedef CRecordVector CIntVector; typedef CRecordVector CUIntVector; typedef CRecordVector CBoolVector; typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void *param) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { Close(); _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (g_IsNT) { Close(); _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); } #endif bool CFileBase::Close() { if(!_fileIsOpen) return true; bool result = BOOLToBool(::CloseHandle(_handle)); _fileIsOpen = !result; return result; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCTSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCWSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). static UInt32 kChunkSizeMax = (1 << 24); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: bool _fileIsOpen; HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _fileIsOpen(false){}; virtual ~CFileBase(); virtual bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/C/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CPL.html ================================================ Common Public License - v 1.0

Common Public License - v 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

    a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
    b) in the case of each subsequent Contributor:
    i) changes to the Program, and
    ii) additions to the Program;
    where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

    a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
    b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
    c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
    d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

    a) it complies with the terms and conditions of this Agreement; and
    b) its license agreement:
    i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
    ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
    iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
    iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

    a) it must be made available under this Agreement; and
    b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void Init(System.IO.Stream inStream); void ReleaseStream(); void MovePos(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetLongestMatch(UInt32[] distances); void DummyLongestMatch(); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; UInt32 _historySize; UInt32 _matchMaxLen; // UInt32 []_dummy; UInt32[] _son; UInt32[] _hash; UInt32[] _hash2; UInt32[] _hash3; UInt32 _cutValue = 0xFF; bool HASH_ARRAY = true; bool HASH_BIG = false; const UInt32 kHash3Size = 1 << 18; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kBT4Hash2Size = 1 << 10; const UInt32 kBT4Hash4Size = 1 << 20; const UInt32 kBT4bHash4Size = 1 << 23; const UInt32 kBT2NumHashDirectBytes = 2; const UInt32 kBT4NumHashDirectBytes = 0; UInt32 kHash2Size = kBT4Hash2Size; UInt32 kNumHashDirectBytes = kBT4NumHashDirectBytes; UInt32 kNumHashBytes = 4; UInt32 kHashSize = kBT4Hash4Size; public void SetType(int numHashBytes, bool big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size; } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 Hash(UInt32 offset, out UInt32 hash2Value, out UInt32 hash3Value) { UInt32 temp = CRC.Table[_bufferBase[offset]] ^ _bufferBase[offset + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[offset + 2]) << 8); hash3Value = temp & (kHash3Size - 1); return (temp ^ (CRC.Table[_bufferBase[offset + 3]] << 5)) & (kHashSize - 1); } UInt32 Hash(UInt32 offset) { return _bufferBase[offset] ^ ((UInt32)(_bufferBase[offset + 1]) << 8); } public new void Init(System.IO.Stream inStream) { base.Init(inStream); UInt32 i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void ReleaseStream() { base.ReleaseStream(); } public new void MovePos() { _cyclicBufferPos++; if (_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { // _dummy = new UInt32[matchMaxLen + 1]; UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) throw new Exception(); _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new UInt32[_cyclicBufferSize * 2]; _hash = new UInt32[kHashSize]; if (HASH_ARRAY) { _hash2 = new UInt32[kHash2Size]; _hash3 = new UInt32[kHash3Size]; } } public UInt32 GetLongestMatch(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 matchHashLenMax = 0; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; UInt32 len2Distance = 0; UInt32 len3Distance = 0; bool matchLen2Exist = false; bool matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 startItem = _pos - _historySize; UInt32 subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public virtual void BeforeMoveBlock() { } public virtual void AfterMoveBlock() { } public void MoveBlock() { BeforeMoveBlock(); UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; AfterMoveBlock(); } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void Init(System.IO.Stream stream) { _stream = stream; _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void ReleaseStream() { _stream = null; } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) ; return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; } } public void Init(System.IO.Stream stream) { Init(stream, false); } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; public const int kDicLogSizeMax = 28; public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, BT4B }; static string[] kMatchFinderIDs = { "BT2", "BT4", "BT4B", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1024]; static Encoder() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return (UInt32)(g_FastPos[pos >> 9] + 18); return (UInt32)(g_FastPos[pos >> 18] + 36); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 25)) return (UInt32)(g_FastPos[pos >> 15] + 30); return (UInt32)(g_FastPos[pos >> 24] + 48); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[GetState(pos, prevByte)]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumLowBits RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumMidBits RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { UInt32 price = 0; if (symbol < Base.kNumLowLenSymbols) { price += _choice.GetPrice0(); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += _choice.GetPrice1(); if (symbol < Base.kNumMidLenSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public new UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = base.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; // posNext; public UInt32 BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; // test it RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen + 1]; bool _fastMode = false; bool _maxMode = false; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 lastPosSlotFillingPos; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark; bool _needReleaseMFStream; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; bool big = false; switch (_matchFinderType) { case EMatchFinderType.BT2: numHashBytes = 2; break; case EMatchFinderType.BT4: break; case EMatchFinderType.BT4B: big = true; break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes) { lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); } void MovePos(UInt32 num) { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes = _optimum[1].BackPrev; return 1; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for (UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 newLen; ReadMatchDistances(out newLen); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte((Int32)temp - 1) != _matchFinder.GetIndexByte((Int32)temp - (Int32)backOffset - 1)) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte((Int32)(-1 - (Int32)backOffset)) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte((Int32)(0 - (Int32)backOffset))) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte((Int32)lenTest - 1) != _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)backOffset)) break; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1)) != _matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1 - (Int32)backOffset))) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)backOffset)), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)lenTest2 - 1) != _matchFinder.GetIndexByte((Int32)lenTest2 - (Int32)backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, // data[(size_t)lenTest - 1], _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, // data[(size_t)lenTest - backOffset], data[lenTest] _matchFinder.GetIndexByte((Int32)lenTest - (Int32)backOffset - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1) ); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } UInt32 GetOptimumFast(UInt32 position, out UInt32 backRes) { UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { ReadMatchDistances(out _longestMatchLength); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } } backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = 0xFFFFFFFF; return 1; } void InitMatchFinder(LZ.IMatchFinder matchFinder) { _matchFinder = matchFinder; } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.Init(_inStream); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len; // it's not used ReadMatchDistances(out len); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 len; if (_fastMode) len = GetOptimumFast((UInt32)nowPos64, out pos); else len = GetOptimum((UInt32)nowPos64, out pos); UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 28; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + RangeCoder.BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[12]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary, mf == "bt4"); } bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; FileStream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================  Debug AnyCPU 8.0.40607 2.0 {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973} Exe LzmaAlone Lzma# 4 true full false .\bin\Debug\ DEBUG;TRACE false true .\bin\Release\ TRACE Common\CommandLineParser.cs Common\CRC.cs ICoder.cs LZ\IMatchFinder.cs LZ\LzBinTree.cs LZ\LzInWindow.cs LZ\LzOutWindow.cs LZMA\LzmaBase.cs LZMA\LzmaDecoder.cs LZMA\LzmaEncoder.cs RangeCoder\RangeCoder.cs RangeCoder\RangeCoderBit.cs RangeCoder\RangeCoderBitTree.cs Code Code True Settings.settings SettingsSingleFileGenerator Settings.cs ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// /// LZMA Benchmark /// internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } const string bt2 = "BT2"; const string bt4 = "BT4"; static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.MatchFinder }; object[] properties = { (Int32)(dictionarySize), isBT4 ? bt4: bt2 }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// /// The exception that is thrown when an error in input stream occurs during decoding. /// class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// /// The exception that is thrown when the value of an argument is outside the allowable range. /// class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// /// Callback progress. /// /// /// input size. -1 if unknown. /// /// /// output size. -1 if unknown. /// void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// /// Codes streams. /// /// /// input Stream. /// /// /// output Stream. /// /// /// input Size. -1 if unknown. /// /// /// output Size. -1 if unknown. /// /// /// callback progress reference. /// /// /// if input stream is not valid /// void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// /// Provides the fields that represent properties idenitifiers for compressing. /// public enum CoderPropID { /// /// Specifies size of dictionary. /// DictionarySize = 0x400, /// /// Specifies size of memory for PPM*. /// UsedMemorySize, /// /// Specifies order for PPM methods. /// Order, /// /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// PosStateBits = 0x440, /// /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// LitContextBits, /// /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// LitPosBits, /// /// Specifies number of fast bytes for LZ*. /// NumFastBytes = 0x450, /// /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// MatchFinder, /// /// Specifies number of passes. /// NumPasses = 0x460, /// /// Specifies number of algorithm. /// Algorithm = 0x470, /// /// Specifies multithread mode. /// MultiThread = 0x480, /// /// Specifies mode with end marker. /// EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize; int _historySize; int _matchMaxLen; int[] _son; int[] _hash; int[] _hash2; int[] _hash3; int _cutValue = 0xFF; boolean HASH_ARRAY = true; boolean HASH_BIG = false; static final int kHash3Size = 1 << 18; static final int kBT2HashSize = 1 << 16; static final int kBT4Hash2Size = 1 << 10; static final int kBT4Hash4Size = 1 << 20; static final int kBT4bHash4Size = 1 << 23; static final int kBT2NumHashDirectBytes = 2; static final int kBT4NumHashDirectBytes = 0; int kHash2Size = kBT4Hash2Size; int kNumHashDirectBytes = kBT4NumHashDirectBytes; int kNumHashBytes = 4; int kHashSize = kBT4Hash4Size; private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } public void SetType(int numHashBytes, boolean big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = (HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size); } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = ((int)1 << 30) - 1; public void Init() throws IOException { super.Init(); int i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) return false; _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new int[_cyclicBufferSize * 2]; _hash = new int[kHashSize]; if (HASH_ARRAY) { _hash2 = new int[kHash2Size]; _hash3 = new int[kHash3Size]; } return true; } public int GetLongestMatch(int[] distances) { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int matchHashLenMax = 0; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; int len2Distance = 0; int len3Distance = 0; boolean matchLen2Exist = false; boolean matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int startItem = _pos - _historySize; int subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindows package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos int _keepSizeReserv; // how many BYTEs must be kept as reserv public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; public static final int kDicLogSizeMax = 28; public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; public static final int EMatchFinderTypeBT4B = 2; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1024]; static { int kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } static int GetPosSlot2(int pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 20; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public int GetPrice(int symbol, int posState) { int price = 0; if (symbol < Base.kNumLowLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); if (symbol < Base.kNumMidLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); price += _midCoder[posState].GetPrice(symbol); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(int posState) { for (int len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = super.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } public static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; // posNext; public int BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; // test it SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen + 1]; boolean _fastMode = false; boolean _maxMode = true; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int [] _posSlotPrices = new int [Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; int [] _distancesPrices = new int [Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; int [] _alignPrices = new int [Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long lastPosSlotFillingPos; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; boolean big = false; switch (_matchFinderType) { case EMatchFinderTypeBT2: numHashBytes = 2; break; case EMatchFinderTypeBT4: break; case EMatchFinderTypeBT4B: big = true; break; default: break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); return lenRes; } void MovePos(int num) throws java.io.IOException { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetPosLenPrice(int pos, int len, int posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int[] backRes, int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes[0] = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int GetOptimum(int position, int []backRes) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes[0] = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { int backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; byte matchByte; matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes[0] = _optimum[1].BackPrev; return 1; } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; int len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; for (int lenTest = 2; lenTest <= repLen; lenTest++) { int curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } int cur = 0; int lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(backRes, cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int newLen = ReadMatchDistances(); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); int numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { int backOffset = reps[0] + 1; int temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte(temp - 1) != _matchFinder.GetIndexByte(temp - backOffset - 1)) break; int lenTest2 = temp - 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // int repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; int backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte(-1 - backOffset) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte(0 - backOffset)) continue; int lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte(lenTest - 1) != _matchFinder.GetIndexByte(lenTest - 1 - backOffset)) break; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - 1 - backOffset)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - backOffset), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (int lenTest = newLen; lenTest >= 2; lenTest--) { int curBack = _matchDistances[lenTest]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { int backOffset = curBack + 1; int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - backOffset - 1), _matchFinder.GetIndexByte(lenTest - 1) ); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } int GetOptimumFast(int position, int[] backRes) throws IOException { int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; for (int i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes[0] = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; int backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { _longestMatchLength = ReadMatchDistances(); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } for (int i = 0; i < Base.kNumRepDistances; i++) { int repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } } backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes[0] = -1; return 1; } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } int[] posTemp = new int[1]; public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int posState = ((int)nowPos64) & _posStateMask; int len; if (_fastMode) len = GetOptimumFast((int)nowPos64, posTemp); else len = GetOptimum((int)nowPos64, posTemp); int pos = posTemp[0]; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = ((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } public boolean SetAlgorithm(int algorithm) { if (algorithm < 0 || algorithm > 2) return false; _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = Base.kDicLogSizeMax; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++); _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary, params.MatchFinder >= 1); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int offset = GetOffset(); while (offset >= Pos) offset >>>= 1; offset += 1; int len = 2 + GetLen(); for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, boolean isBT4, long elapsedTime, long size) { long numCommandsForOne; if (isBT4) { long t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >>> (2 * kSubBits)); } else { long t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >>> (2 * kSubBits)); } long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, boolean isBT4, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, boolean isBT4, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } String bt2 = "BT2"; String bt4 = "BT4"; static public int LzmaBenchmark(int numIterations, int dictionarySize, boolean isBT4) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.out.println("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetMatchFinder(isBT4 ? SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT4: SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT2)) throw new Exception("Incorrect MatchFinder"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/LGPL.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/Methods.txt ================================================ Compression method IDs (4.27) ----------------------------- Each compression method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 15 bytes. List of defined IDs ------------------- 00 - Copy 01 - Reserved 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 04 Delta (subject to change) 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - BC_PPC_B (Big Endian) 03 - Alpha 01 - BC_Alpha 04 - IA64 01 - BC_IA64 05 - ARM 01 - BC_ARM 06 - M68 05 - BC_M68_B (Big Endian) 07 - ARM Thumb 01 - BC_ARMThumb 08 - SPARC 05 - BC_SPARC 04 - PPMD 01 - Version 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- Version 4.32 2005-12-09 -------------------------------------- - Java version of LZMA SDK was included Version 4.30 2005-11-20 -------------------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - Bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included Version 4.27 (Updated) 2005-09-21 -------------------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart Version 4.27 2005-08-07 -------------------------------------- - Bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. Version 4.26 2005-08-05 -------------------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 Version 4.23 2005-06-29 -------------------------------------- - Small fixes in C++ code Version 4.22 2005-06-10 -------------------------------------- - Small fixes Version 4.21 2005-06-08 -------------------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB Version 4.17 2005-04-18 -------------------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe Version 4.16 2005-03-29 -------------------------------------- - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included Version 4.06 2004-09-05 -------------------------------------- - Bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. Version 4.05 2004-08-25 -------------------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes Version 4.04 2004-07-28 -------------------------------------- - More compatibility with some C++ compilers Version 4.03 2004-06-18 -------------------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. Version 4.02 2004-06-10 -------------------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. Version 4.01 2004-02-15 -------------------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } Version 4.00 2004-02-13 -------------------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2004: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-3.0-e2100/lzma/lzma.txt ================================================ LZMA SDK 4.32 ------------- LZMA SDK 4.32 Copyright (C) 1999-2005 Igor Pavlov LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is available under any of the following licenses: 1) GNU Lesser General Public License (GNU LGPL) 2) Common Public License (CPL) 3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 4) Proprietary license It means that you can select one of these four options and follow rules of that license. 1,2) GNU LGPL and CPL licenses are pretty similar and both these licenses are classified as - "Free software licenses" at http://www.gnu.org/ - "OSI-approved" at http://www.opensource.org/ 3) 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 files from LZMA SDK without subjecting your linked code to the terms of the CPL or GNU LGPL. Any modifications or additions to files from LZMA SDK, however, are subject to the GNU LGPL or CPL terms. SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, while you keep LZMA SDK code unmodified. SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits you to use this code under the same terms and conditions contained in the License Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov. SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version of LZMA SDK as update for previous versions. SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits you to use code of examples (LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, LzmaAlone.cs, LzmaAlone.java) as public domain code. 4) Proprietary license LZMA SDK also can be available under a proprietary license which can include: 1) Right to modify code without subjecting modified code to the terms of the CPL or GNU LGPL 2) Technical support for code To request such proprietary license or any additional consultations, send email message from that page: http://www.7-zip.org/support.html You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You should have received a copy of the Common Public License along with this library. LZMA SDK Contents ----------------- LZMA SDK includes: - C++ source code of LZMA compressing and decompressing - ANSI-C compatible source code for LZMA decompressing - C# source code for LZMA compressing and decompressing - Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system ANSI-C LZMA decompression code was ported from original C++ sources to C. Also it was simplified and optimized for code size. But it is fully compatible with LZMA from 7-Zip. UNIX/Linux version ------------------ To compile C++ version of file->file LZMA, go to directory C/7zip/Compress/LZMA_Alone and type "make" or "make clean all" to recompile all. In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, change string in makefile LIB = -lm to string LIB = -lm -static Files --------------------- C - C / CPP source code CS - C# source code Java - Java source code lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description (this file) methods.txt - Compression method IDs for .7z LGPL.txt - GNU Lesser General Public License CPL.html - Common Public License lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C - C / CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm BinTree - Binary Tree Match Finder for LZ algorithm HashChain - Hash Chain Match Finder for LZ algorithm Patricia - Patricia Match Finder for LZ algorithm RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression LZMA_C - ANSI-C compatible LZMA decompressor LzmaDecode.h - interface for LZMA decoding on ANSI-C LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version) LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version) LzmaTest.c - test application that decodes LZMA encoded file LzmaStateDecode.h - interface for LZMA decoding (State version) LzmaStateDecode.c - LZMA decoding on ANSI-C (State version) LzmaStateTest.c - test application (State version) Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving 7z_C - 7z ANSI-C Decoder CS - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. You can find ANSI-C LZMA decompressing code at folder C/7zip/Compress/LZMA_C 7-Zip doesn't use that ANSI-C LZMA code and that code was developed specially for this SDK. And files from LZMA_C do not need files from other directories of SDK for compiling. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA Decompression features --------------------------- - Variable dictionary size (up to 256 MB) - Estimated compressing speed: about 500 KB/s on 1 GHz CPU - Estimated decompressing speed: - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (8-32 KB + DictionarySize) - Small code size for decompressing: 2-8 KB (depending from speed optimizations) LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect to speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations Speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA inputFile outputFile [...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with AMD Athlon XP CPU results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you can change number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. -a{N}: set compression mode 0 = fast, 1 = normal, 2 = max default: 2 (max) d{N}: Sets Dictionary size - [0, 28], default: 23 (8MB) The maximum value for dictionary size is 256 MB = 2^28 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Compression ratio for all bt* and pat* almost the same. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Methods from bt* group require less memory than methods from pat* group. Usually bt4 works faster than any pat*, but for some types of files pat* can work faster. Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d*9.5 + 1MB Binary Tree with 2 bytes hashing. bt3 d*9.5 + 65MB Binary Tree with 2-3(full) bytes hashing. bt4 d*9.5 + 6MB Binary Tree with 2-3-4 bytes hashing. bt4b d*9.5 + 34MB Binary Tree with 2-3-4(big) bytes hashing. pat2r d*26 + 1MB Patricia Tree with 2-bits nodes, removing. pat2 d*38 + 1MB Patricia Tree with 2-bits nodes. pat2h d*38 + 77MB Patricia Tree with 2-bits nodes, 2-3 bytes hashing. pat3h d*62 + 85MB Patricia Tree with 3-bits nodes, 2-3 bytes hashing. pat4h d*110 +101MB Patricia Tree with 4-bits nodes, 2-3 bytes hashing. hc3 d*5.5 + 1MB Hash Chain with 2-3 bytes hashing. hc4 d*5.5 + 6MB Hash Chain with 2-3-4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Using Filters ------------- You can increase compression ratio for some data types, using special filters before compressing. For example, it's possible to increase compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C/C++ source code of such filters in folder "7zip/Compress/Branch" You can check compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=bc_arm -m1=lzma With filter for big-endian ARM code (using additional Swap4 filter): 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. Source code of these CALL filters is pretty simple (about 20 lines of C++), so you can convert it from C++ version yourself. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties for compressed data 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ To compile ANSI-C LZMA Decoder you can use one of the following files sets: 1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version) 2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version) 3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface) Memory requirements for LZMA decoding ------------------------------------- LZMA decoder doesn't allocate memory itself, so you must allocate memory and send it to LZMA. Stack usage of LZMA decoding function for local variables is not larger than 200 bytes. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 5 interfaces: 1) Single-call Decompressing 2) Single-call Decompressing with input stream callback 3) Multi-call Decompressing with output buffer 4) Multi-call Decompressing with input callback and output buffer 5) Multi-call State Decompressing (zlib-like interface) Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions. Decompressing steps ------------------- 1) read LZMA properties (5 bytes): unsigned char properties[LZMA_PROPERTIES_SIZE]; 2) read uncompressed size (8 bytes, little-endian) 3) Decode properties: CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); 4) Allocate memory block for internal Structures: state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); LZMA decoder uses array of CProb variables as internal structure. By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make it unsigned_int. It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case. 5) Main Decompressing You must use one of the following interfaces: 5.1 Single-call Decompressing ----------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: int res = LzmaDecode(&state, inStream, compressedSize, &inProcessed, outStream, outSize, &outProcessed); 5.2 Single-call Decompressing with input stream callback -------------------------------------------------------- When to use: File->RAM or Flash->RAM decompressing. Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) { CBuffer *bo = (CBuffer *)object; *buffer = bo->Buffer; *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize); return LZMA_RESULT_OK; } CBuffer g_InBuffer; g_InBuffer.File = inFile; g_InBuffer.InCallback.Read = LzmaReadCompressed; int res = LzmaDecode(&state, &g_InBuffer.InCallback, outStream, outSize, &outProcessed); 5.3 Multi-call decompressing with output buffer ----------------------------------------------- When to use: RAM->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_OUT_READ Memory Requirements: - Input buffer: compressed size - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaTest.c for more details. 5.4 Multi-call decompressing with input callback and output buffer ------------------------------------------------------------------ When to use: File->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, &bo.InCallback, g_OutBuffer, outAvail, &outProcessed); } while you need more bytes see LzmaTest.c for more details: 5.5 Multi-call State Decompressing (zlib-like interface) ------------------------------------------------------------------ When to use: file->file decompressing Compile files: LzmaStateDecode.h, LzmaStateDecode.c Compile defines: Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaStateTest.c for more details: 6) Free all allocated blocks Note ---- LzmaDecodeSize.c is size-optimized version of LzmaDecode.c. But compiled code of LzmaDecodeSize.c can be larger than compiled code of LzmaDecode.c. So it's better to use LzmaDecode.c in most cases. EXIT codes ----------- LZMA decoder can return one of the following codes: #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 If you use callback function for input data and you return some error code, LZMA Decoder also returns that code. LZMA Defines ------------ _LZMA_IN_CB - Use callback for input data _LZMA_OUT_READ - Use read function for output data _LZMA_LOC_OPT - Enable local speed optimizations inside code. _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version). _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version) and LzmaStateDecode.c _LZMA_PROB32 - It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t. You can use it to enable 64-bit sizes supporting C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. By default, LZMA Encoder contains all Match Finders. But for compressing it's enough to have just one of them. So for reducing size of compressing code you can define: #define COMPRESS_MF_BT #define COMPRESS_MF_BT4 and it will use only bt4 match finder. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.0-e2100/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536], *frag_dups[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; char fragment_data[SQUASHFS_FILE_SIZE]; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long bytes; unsigned short checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; unsigned short fragment_checksum; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* structure to used to pass in a pointer or an integer * to duplicate buffer read helper functions. */ struct duplicate_buffer_handle { char *ptr; long long start; }; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table); int get_sorted_inode(squashfs_inode *inode, struct stat *buf); int read_sort_file(char *filename, int source, char *source_path[]); void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) void restorefs() { ERROR("Exiting - restoring original filesystem!\n\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(interrupted == 1) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); interrupted ++; } } void sighandler2() { EXIT_MKSQUASHFS(); } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte = block_size << 1; unsigned int res; if(!uncompressed && (res = compress2((unsigned char *) d, &c_byte, (unsigned char *) s, size, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); return 0; } if(uncompressed || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment) { squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index]; int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); return buffer + fragment->offset; } void write_fragment() { int compressed_size; char buffer[block_size << 1]; if(fragment_size == 0) return; if(fragments % FRAG_SIZE == 0) if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) BAD_ERROR("Out of memory in fragment table\n"); fragment_table[fragments].size = mangle(buffer, fragment_data, fragment_size, block_size, noF, 1); fragment_table[fragments].start_block = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[fragments].size); write_bytes(fd, bytes, compressed_size, buffer); bytes += compressed_size; total_uncompressed += fragment_size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n",fragments, fragment_size, compressed_size); fragments ++; fragment_size = 0; } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(char *buff, int size) { struct fragment *ffrg; if(size == 0) return &empty_fragment; if(fragment_size + size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = size; memcpy(fragment_data + fragment_size, buff, size); fragment_size += size; return ffrg; } long long write_fragment_table() { long long start_bytes; unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments), meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; unsigned short c_byte; int i, compressed_size; squashfs_fragment_index list[meta_blocks]; TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } for(i = 0; i < meta_blocks; i++) { int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { squashfs_fragment_index slist[meta_blocks]; SQUASHFS_SWAP_FRAGMENT_INDEXES(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); return start_bytes; } char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { char *v = handle->ptr; handle->ptr += avail_bytes; return v; } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer); handle->start += avail_bytes; return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, long long l) { unsigned short chksum = 0; unsigned int bytes = 0; unsigned char *b; struct duplicate_buffer_handle position = *handle; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; b = (unsigned char *) get_next_file_block(&position, bytes); while(bytes--) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } } return chksum; } int cached_frag = -1; void add_file(long long start, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; struct file_info *dupl_ptr; char *datap; struct duplicate_buffer_handle handle; unsigned int *block_list = block_listp; if(!duplicate_checking) return; if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; if(fragment == cached_frag || fragment == SQUASHFS_INVALID_FRAG) datap = fragment_data + offset; else datap = get_fragment(fragment_data, frg); handle.start = start; if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL) dupl_ptr->fragment = frg; else free(block_list); cached_frag = fragment; } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes) { unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes); struct duplicate_buffer_handle handle = { frag_data, 0 }; unsigned short fragment_checksum = get_checksum(read_from_buffer, &handle, frag_bytes); struct file_info *dupl_ptr = bytes ? dupl[checksum] : frag_dups[fragment_checksum]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) { char buffer1[SQUASHFS_FILE_MAX_SIZE]; long long dup_bytes = dupl_ptr->bytes; long long dup_start = dupl_ptr->start; struct duplicate_buffer_handle position = *file_start; char *buffer; while(dup_bytes) { int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes; buffer = get_next_file_block(&position, avail_bytes); read_bytes(fd, dup_start, avail_bytes, buffer1); if(memcmp(buffer, buffer1, avail_bytes) != 0) break; dup_bytes -= avail_bytes; dup_start += avail_bytes; } if(dup_bytes == 0) { char *fragment_buffer1; if(dupl_ptr->fragment->index == fragments || dupl_ptr->fragment->index == SQUASHFS_INVALID_FRAG) fragment_buffer1 = fragment_data + dupl_ptr->fragment->offset; else if(dupl_ptr->fragment->index == cached_frag1) fragment_buffer1 = cached_fragment + dupl_ptr->fragment->offset; else { fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment); cached_frag1 = dupl_ptr->fragment->index; } if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->bytes = bytes; dupl_ptr->checksum = checksum; dupl_ptr->start = *start; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->block_list = *block_list; dup_files ++; if(bytes) { dupl_ptr->next = dupl[checksum]; dupl[checksum] = dupl_ptr; } else { dupl_ptr->next = frag_dups[fragment_checksum]; frag_dups[fragment_checksum] = dupl_ptr; } return dupl_ptr; } #define MINALLOCBYTES (1024 * 1024) int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { int block = 0, i, file, whole_file = 1, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes = 0, start; char buff[block_size], *c_buffer = NULL, *filename = dir_ent->pathname; struct fragment *fragment; struct file_info *dupl_ptr = NULL; struct duplicate_buffer_handle handle; long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; int blocks = (read_size + block_size - 1) >> block_log, allocated_blocks = blocks; unsigned int *block_list, *block_listp; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if(!no_fragments && (read_size < block_size || always_use_fragments)) { allocated_blocks = blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE); total_bytes += read_size; if((file = open(filename, O_RDONLY)) == -1) goto read_err; do { long long bytes = (((long long) allocated_blocks) + 1) << block_log; if(bytes != ((size_t) bytes) || (c_buffer = (char *) malloc(bytes)) == NULL) { TRACE("Out of memory allocating write_file buffer, allocated_blocks %ld, blocks %d\n", allocated_blocks, blocks); whole_file = 0; if(bytes < MINALLOCBYTES) BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %ld blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10)); allocated_blocks >>= 1; } } while(!c_buffer); for(start = bytes; block < blocks; file_bytes += bbytes) { for(i = 0, bbytes = 0; (i < allocated_blocks) && (block < blocks); i++) { int available_bytes = read_size - (block * block_size) > block_size ? block_size : read_size - (block * block_size); if(read(file, buff, available_bytes) == -1) goto read_err; c_byte = mangle(c_buffer + bbytes, buff, available_bytes, block_size, noD, 1); block_list[block ++] = c_byte; bbytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); } if(!whole_file) { write_bytes(fd, bytes, bbytes, c_buffer); bytes += bbytes; } } if(frag_bytes != 0) if(read(file, buff, frag_bytes) == -1) goto read_err; close(file); if(whole_file) { handle.ptr = c_buffer; if(duplicate_checking && (dupl_ptr = duplicate(read_from_buffer, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { *duplicate_file = TRUE; goto wr_inode; } write_bytes(fd, bytes, file_bytes, c_buffer); bytes += file_bytes; } else { handle.start = start; if(duplicate_checking && (dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { bytes = start; if(!block_device) ftruncate(fd, bytes); *duplicate_file = TRUE; goto wr_inode; } } fragment = get_and_fill_fragment(buff, frag_bytes); if(duplicate_checking) dupl_ptr->fragment = fragment; *duplicate_file = FALSE; wr_inode: free(c_buffer); file_count ++; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(duplicate_checking == FALSE || *duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); free(c_buffer); free(block_list); return FALSE; } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; struct inode_info *inode_info; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if((inode_info = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->inode = inode_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; inode_info->nlink = 1; inode_info->inode_number = root_inode_number ? root_inode_number : dir_inode_no++; dir_info->dir_ent = dir_ent; if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ inode_info->buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO; inode_info->buf.st_uid = getuid(); inode_info->buf.st_gid = getgid(); inode_info->buf.st_mtime = time(NULL); } else if(lstat(pathname, &inode_info->buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; caseSQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } #define VERSION() \ printf("mksquashfs version 3.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -2.0 options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); TRACE("sBlk->inode_table_start 0x%x\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%x\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%x\n", sBlk.fragment_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; sBlk.unused = SQUASHFS_INVALID_BLK; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.0-e2100/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.0-e2100/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i, start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i, start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid SQUASHFS superblock on %s.\n", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.0-e2100/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.0-e2100/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; generate_file_priorities(dir, 0, &dir->dir_ent->inode->buf); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.0-e2100/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; struct inode_info *next; }; #endif ================================================ FILE: src/others/squashfs-3.0-e2100/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) #define SQUASHFS_CACHED_FRAGMENTS 3 /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long unused; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->unused, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.0-e2100/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE; char **created_inode; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(set_mode && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } return TRUE; } void read_uids_guids(squashfs_super_block *sBlk) { if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk->no_uids; if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table(squashfs_super_block *sBlk) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { long long start = sBlk->inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(geteuid() == 0) { if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk->inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk->directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { struct dir *dir = squashfs_openddir(start_block, offset, sBlk); unsigned int type; char *name, pathname[1024]; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, sBlk); else if(!lsonly) create_inode(pathname, start_block, offset, sBlk); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(squashfs_super_block *sBlk, char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk->s_major, sBlk->s_minor); ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source); #else TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk->block_size); TRACE("\tNumber of fragments %d\n", sBlk->fragments); TRACE("\tNumber of inodes %d\n", sBlk->inodes); TRACE("\tNumber of uids %d\n", sBlk->no_uids); TRACE("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start); TRACE("\n"); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { squashfs_super_block sBlk; char *dest = "squashfs-root"; int i, version = FALSE; for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0) { if(++i == argc) goto options; dest = argv[i]; } } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [-ls | -dest] filesystem\n", argv[0]); ERROR("\t-version\t\tprint version, licence and copyright information\n"); ERROR("\t-info\t\t\tprint files as they are unsquashed\n"); ERROR("\t-ls\t\t\tlist filesystem only\n"); ERROR("\t-dest \tunsquash to , default \"squashfs-root\"\n"); } exit(1); } if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(&sBlk, argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(&sBlk); read_fragment_table(&sBlk); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } } ================================================ FILE: src/others/squashfs-3.2-r2/Makefile ================================================ CC := gcc CXX := g++ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 LZMAPATH = ../../lzma/C/7zip/Compress/LZMA_Lib all: mksquashfs unsquashfs # mksquashfs-lzma unsquashfs-lzma mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lpthread -lz -lm -o $@ #mksquashfs-lzma: mksquashfs.o read_fs.o sort.o # make -C $(LZMAPATH) # $(CXX) -O3 mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -lpthread -lm -llzma -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs-lzma: unsquashfs.o make -C $(LZMAPATH) $(CXX) -O3 unsquashfs.o -L$(LZMAPATH) -llzma -o $@ unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h clean: rm -f *.o rm -f mksquashfs rm -f unsquashfs rm -f mksquashfs-lzma rm -f unsquashfs-lzma rm -f mksquashfs.exe rm -f unsquashfs.exe rm -f mksquashfs-lzma.exe rm -f unsquashfs-lzma.exe make -C $(LZMAPATH) clean ================================================ FILE: src/others/squashfs-3.2-r2/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.2-r2/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { char buffer2[SQUASHFS_FILE_MAX_SIZE]; long long dup_start = dupl_ptr->start; char *buffer; int block; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else buffer = read_from_disk(b->start, b->size); read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf; int count; int blocks = (buf->st_size + block_size - 1) >> block_log; int frag_block = !no_fragments && (always_use_fragments || (buf->st_size < block_size)) ? buf->st_size >> block_log : -1; int file; static int block_order = 0; struct file_buffer *file_buffer; if(buf->st_size == 0 || dir_ent->inode->read) return; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; for(count = 0; count < blocks; count ++) { file_buffer = alloc_get(reader_buffer); if((file_buffer->size = read(file, file_buffer->data, block_size)) == -1) { close(file); goto read_err2; } file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; if(file_buffer->fragment = count == frag_block) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); } close(file); dir_ent->inode->read = TRUE; return; read_err: file_buffer = alloc_get(reader_buffer); read_err2: file_buffer->block_order = block_order ++; file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } int write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } int write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; struct file_buffer *file_buffer = get_file_buffer(from_deflate); if(file_buffer->error) { alloc_free(file_buffer); return FALSE; } checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) return write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size) { int block, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return FALSE; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, int *duplicate_file) { int block, status, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return FALSE; } int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", dir_ent->pathname, SQUASHFS_MAX_FILE_SIZE); if(read_size == 0) return write_file_empty(inode, dir_ent, duplicate_file); if(!no_fragments && (read_size < block_size)) return write_file_frag(inode, dir_ent, read_size, duplicate_file); if(pre_duplicate(read_size)) return write_file_blocks_dup(inode, dir_ent, read_size, duplicate_file); *duplicate_file = FALSE; return write_file_blocks(inode, dir_ent, read_size); } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, reader_buffer_size); writer_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, writer_buffer_size); fragment_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } #define VERSION() \ printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.2-r2/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.2-r2/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); int (*create_inode)(char *pathname, unsigned int start_block, unsigned int offset); } squashfs_operations; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } int create_inode_2(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header_2 header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, sBlk.mkfs_time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header_2 header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } int matches(char *targname, char *name) { if(*targname == '\0' || strcmp(targname, name) == 0) return TRUE; return FALSE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, char *target) { struct dir *dir = s_ops.squashfs_opendir(start_block, offset); unsigned int type; char *name, pathname[1024]; char targname[1024]; target = get_component(target, targname); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(targname, name)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, target); else if(!lsonly) s_ops.create_inode(pathname, start_block, offset); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk.s_magic != SQUASHFS_MAGIC) { if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.create_inode = create_inode_2; } else if(sBlk.s_major == 3 && sBlk.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.create_inode = create_inode; } else { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk.s_major, sBlk.s_minor); ERROR("I support Squashfs 2.x and 3.0 filesystems!\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk.block_size); TRACE("\tNumber of fragments %d\n", sBlk.fragments); TRACE("\tNumber of inodes %d\n", sBlk.inodes); TRACE("\tNumber of uids %d\n", sBlk.no_uids); TRACE("\tNumber of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.3 (2007/01/02)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; if(root_process = geteuid() == 0) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) goto options; dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directory or file to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-l[s]\t\t\tlist filesystem only\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); } exit(1); } if((i + 1) < argc) target = argv[i + 1]; if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), target); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/Makefile ================================================ # Copyright (C) 2006, 2007 Junjiro Okajima # Copyright (C) 2006, 2007 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: Makefile,v 1.2 2007-11-22 06:13:08 steven Exp $ # paths Sqlzma = ${CURDIR} LzmaVer = lzma443 Lzma = ${Sqlzma}/${LzmaVer} SqVer = squashfs3.2-r2 Squashfs = ${Sqlzma}/${SqVer} LzmaC = ${Lzma}/C/7zip/Compress/LZMA_C LzmaAlone = ${Lzma}/C/7zip/Compress/LZMA_Alone SqTools = ${Squashfs}/squashfs-tools # enable it if you want to add -g option when compiling UseDebugFlags = # disable it if you don't want to compile squashfs kernel module here BuildSquashfs = 1 export all: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ @cp squashfs3.2-r2/squashfs-tools/mksquashfs . @cp squashfs3.2-r2/squashfs-tools/unsquashfs . clean: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ ${RM} *~ mksquashfs unsquashfs # install: all # cp squashfs3.2-r2/squashfs-tools/mksquashfs /opt/buildroot-gdb/bin/mksquashfs_lzma-3.2 ######################################## ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/7zC.txt ================================================ 7z ANSI-C Decoder 4.43 ---------------------- 7z ANSI-C Decoder 4.43 Copyright (C) 1999-2006 Igor Pavlov 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- Read lzma.txt for information about license. Files --------------------- 7zAlloc.* - Allocate and Free 7zBuffer.* - Buffer structure 7zCrc.* - CRC32 code 7zDecode.* - Low level memory->memory decoding 7zExtract.* - High level stream->memory decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application 7zMethodID.* - MethodID structure 7zTypes.h - Base types and constants How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 -mf=off If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K -mf=off In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec : e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- .7z Decoder can be compiled in one of two modes: 1) Default mode. In that mode 7z Decoder will read full compressed block to RAM before decompressing. 2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read compressed block by parts. And you can specify desired buffer size. So memory requirements can be reduced. But decompressing speed will be 5-10% lower and code size is slightly larger. Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ISzInStream interface */ CArchiveDatabaseEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call InitCrcTable(); function to initialize CRC structures. 3) call SzArDbExInit(&db); function to initialize db structures. 4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined) - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for compressed solid block (if _LZMA_IN_CB is not defined) - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. EXIT codes ----------- 7z Decoder functions can return one of the following codes: #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) LZMA Defines ------------ _LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements _SZ_FILE_SIZE_64 - define it if you need support for files larger than 4 GB _SZ_NO_INT_64 - define it if your compiler doesn't support long long int _LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs. _SZ_ONE_DIRECTORY - define it if you want to locate all source files to one directory _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zAlloc.c ================================================ /* 7zAlloc.c */ #include #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include #endif #include int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include #include "7zTypes.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void InitCrcTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCrcPoly; else r >>= 1; g_CrcTable[i] = r; } } void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } void CrcUpdateByte(UInt32 *crc, Byte b) { *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); } void CrcUpdateUInt16(UInt32 *crc, UInt16 v) { CrcUpdateByte(crc, (Byte)v); CrcUpdateByte(crc, (Byte)(v >> 8)); } void CrcUpdateUInt32(UInt32 *crc, UInt32 v) { int i; for (i = 0; i < 4; i++) CrcUpdateByte(crc, (Byte)(v >> (8 * i))); } void CrcUpdateUInt64(UInt32 *crc, UInt64 v) { int i; for (i = 0; i < 8; i++) { CrcUpdateByte(crc, (Byte)(v)); v >>= 8; } } void CrcUpdate(UInt32 *crc, const void *data, size_t size) { UInt32 v = *crc; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); *crc = v; } UInt32 CrcCalculateDigest(const void *data, size_t size) { UInt32 crc; CrcInit(&crc); CrcUpdate(&crc, data, size); return CrcGetDigest(&crc); } int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) { return (CrcCalculateDigest(data, size) == digest); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include #include "7zTypes.h" extern UInt32 g_CrcTable[256]; void InitCrcTable(); void CrcInit(UInt32 *crc); UInt32 CrcGetDigest(UInt32 *crc); void CrcUpdateByte(UInt32 *crc, Byte v); void CrcUpdateUInt16(UInt32 *crc, UInt16 v); void CrcUpdateUInt32(UInt32 *crc, UInt32 v); void CrcUpdateUInt64(UInt32 *crc, UInt64 v); void CrcUpdate(UInt32 *crc, const void *data, size_t size); UInt32 CrcCalculateDigest(const void *data, size_t size); int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zDecode.c ================================================ /* 7zDecode.c */ #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/LZMA_C/LzmaDecode.h" #endif CMethodID k_Copy = { { 0x0 }, 1 }; CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; size_t Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); *size = (SizeT)processedSize; if (processedSize > cb->Size) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; size_t inSize = 0; CCoderInfo *coder; if (folder->NumPackStreams != 1) return SZE_NOTIMPL; if (folder->NumCoders != 1) return SZE_NOTIMPL; coder = folder->Coders; *outSizeProcessed = 0; for (si = 0; si < folder->NumPackStreams; si++) inSize += (size_t)packSizes[si]; if (AreMethodsEqual(&coder->MethodID, &k_Copy)) { size_t i; if (inSize != outSize) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB for (i = 0; i < inSize;) { size_t j; Byte *inBuffer; size_t bufferSize; RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); if (bufferSize == 0) return SZE_DATA_ERROR; if (bufferSize > inSize - i) return SZE_FAIL; *outSizeProcessed += bufferSize; for (j = 0; j < bufferSize && i < inSize; j++, i++) outBuffer[i] = inBuffer[j]; } #else for (i = 0; i < inSize; i++) outBuffer[i] = inBuffer[i]; *outSizeProcessed = inSize; #endif return SZ_OK; } if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); *outSizeProcessed = (size_t)outSizeProcessedLoc; allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return SZ_OK; } return SZE_NOTIMPL; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSize = SzFolderGetUnPackSize(folder); #ifndef _LZMA_IN_CB CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); Byte *inBuffer = 0; size_t processedSize; #endif *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); if (res == SZ_OK && processedSize != (size_t)packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = (size_t)unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { size_t outRealSize; res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) { if (outRealSize == (size_t)unPackSize) { if (folder->UnPackCRCDefined) { if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) res = SZE_FAIL; } } else res = SZE_FAIL; } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) res = SZE_FAIL; } } } return res; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "7zTypes.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zCrc.h" #include "7zDecode.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ while(1) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) size += db->Database.PackSizes[packStreamIndex + i]; return size; } /* SZ_RESULT SzReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { Byte *inBuffer; size_t processedSize; RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); MY_ALLOC(UInt32, *digests, numItems, allocFunc); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { RINOK(SzReadByte(sd, &mainByte)); coder->MethodID.IDSize = (Byte)(mainByte & 0xF); RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; while(1) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; while(1) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, allocFunc); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); while(1) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; size_t outRealSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, &outRealSize, allocTemp); RINOK(res) if (outRealSize != (UInt32)unPackSize) return SZE_FAIL; if (folder->UnPackCRCDefined) if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); CrcInit(&crc); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); CrcUpdateUInt64(&crc, nextHeaderOffset); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); CrcUpdateUInt64(&crc, nextHeaderSize); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); CrcUpdateUInt32(&crc, nextHeaderCRC); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CrcGetDigest(&crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) { while (1) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); /* #define CArchiveFileTime UInt64 */ typedef struct _CFileItem { /* CArchiveFileTime LastWriteTime; CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04) */ #include #include #include #include "7zCrc.h" #include "7zIn.h" #include "7zExtract.h" typedef struct _CFileInStream { ISzInStream InStream; FILE *File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = fread(buffer, 1, size, s->File); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04\n"); if (numargs == 1) { printf( "\nUsage: 7zDec \n\n" "\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; InitCrcTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { FILE *outputHandle; UInt32 processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = fopen(fileName, "wb+"); if (outputHandle == 0) { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (fclose(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); fclose(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { int i; if (a1->IDSize != a2->IDSize) return 0; for (i = 0; i < a1->IDSize; i++) if (a1->ID[i] != a2->ID[i]) return 0; return 1; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "7zTypes.h" #define kMethodIDSize 15 typedef struct _CMethodID { Byte ID[kMethodIDSize]; Byte IDSize; } CMethodID; int AreMethodsEqual(CMethodID *a1, CMethodID *a2); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7zTypes.h ================================================ /* 7zTypes.h */ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #ifdef _MSC_VER typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _SZ_FILE_SIZE_64 */ /* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_64 typedef UInt64 CFileSize; #else typedef UInt32 CFileSize; #endif #endif #define SZ_RESULT int #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaTypes.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zCrc.c # End Source File # Begin Source File SOURCE=.\7zCrc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # Begin Source File SOURCE=.\7zTypes.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/makefile ================================================ PROG = 7zDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zCrc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Archive/7z_C/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: 7zCrc.c $(CXX) $(CFLAGS) 7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { // return result ? S_OK: E_FAIL; #ifdef _WIN32 return result ? S_OK: (::GetLastError()); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef _WIN32 #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream bool COutFileStream::Create(LPCTSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #ifdef _WIN32 #ifndef _UNICODE bool COutFileStream::Create(LPCWSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #endif #endif STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef _WIN32 UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef _WIN32 #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways); #ifdef _WIN32 #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways); #endif #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" #include "../../Common/Alloc.h" CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS class CInBufferException { public: HRESULT ErrorCode; CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" #include "../../Common/Alloc.h" bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = FlushPart(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS struct COutBufferException { HRESULT ErrorCode; COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) break; } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" #include "BranchARM.c" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" #include "BranchARMThumb.c" UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchARM.c ================================================ /* BranchARM.c */ #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (dest >> 16); data[i + 1] = (dest >> 8); data[i + 0] = dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchARM.h ================================================ // BranchARM.h #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "BranchTypes.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchARMThumb.c ================================================ /* BranchARMThumb.c */ #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; UInt32 dest; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = 0xF0 | ((dest >> 19) & 0x7); data[i + 0] = (dest >> 11); data[i + 3] = 0xF8 | ((dest >> 8) & 0x7); data[i + 2] = (dest); i += 2; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchARMThumb.h ================================================ // BranchARMThumb.h #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "BranchTypes.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "Common/Alloc.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClass2b(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClassA(Name, id, subId) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderA(Name ## _Encoder) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchIA64.c ================================================ /* BranchIA64.c */ #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; for (int slot = 0; slot < 3; slot++, bitPos += 41) { if (((mask >> slot) & 1) == 0) continue; UInt32 bytePos = (bitPos >> 3); UInt32 bitRes = bitPos & 0x7; UInt64 instruction = 0; int j; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); UInt64 instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 /* && (instNorm & 0x3F)== 0 */ ) { UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF); src |= ((instNorm >> 36) & 1) << 20; src <<= 4; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~(UInt64(0x8FFFFF) << 13); instNorm |= (UInt64(dest & 0xFFFFF) << 13); instNorm |= (UInt64(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = Byte(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchIA64.h ================================================ // BranchIA64.h #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "BranchTypes.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchPPC.c ================================================ /* BranchPPC.c */ #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */ if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 /* || (data[i+3] & 3) == 3 */ ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = 0x48 | ((dest >> 24) & 0x3); data[i + 1] = (dest >> 16); data[i + 2] = (dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchPPC.h ================================================ // BranchPPC.h #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "BranchTypes.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchSPARC.c ================================================ /* BranchSPARC.c */ #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchSPARC.h ================================================ // BranchSPARC.h #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "BranchTypes.h" UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchTypes.h ================================================ /* BranchTypes.h */ #ifndef __BRANCHTYPES_H #define __BRANCHTYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" /* static int inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } */ #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; /* void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos) { *prevMask = 0; *prevPos = (UInt32)(-5); } */ UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding) { UInt32 bufferPos = 0; UInt32 limit; if (endPos < 5) return 0; if (nowPos - *prevPos > 5) *prevPos = nowPos - 5; limit = endPos - 5; while(bufferPos <= limit) { Byte b = buffer[bufferPos]; UInt32 offset; if (b != 0xE8 && b != 0xE9) { bufferPos++; continue; } offset = (nowPos + bufferPos - *prevPos); *prevPos = (nowPos + bufferPos); if (offset > 5) *prevMask = 0; else { UInt32 i; for (i = 0; i < offset; i++) { *prevMask &= 0x77; *prevMask <<= 1; } } b = buffer[bufferPos + 4]; if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] && (*prevMask >> 1) < 0x10) { UInt32 src = ((UInt32)(b) << 24) | ((UInt32)(buffer[bufferPos + 3]) << 16) | ((UInt32)(buffer[bufferPos + 2]) << 8) | (buffer[bufferPos + 1]); UInt32 dest; while(1) { UInt32 index; if (encoding) dest = (nowPos + bufferPos + 5) + src; else dest = src - (nowPos + bufferPos + 5); if (*prevMask == 0) break; index = kMaskToBitNumber[*prevMask >> 1]; b = (Byte)(dest >> (24 - index * 8)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index * 8)) - 1); } buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1)); buffer[bufferPos + 3] = (Byte)(dest >> 16); buffer[bufferPos + 2] = (Byte)(dest >> 8); buffer[bufferPos + 1] = (Byte)dest; bufferPos += 5; *prevMask = 0; } else { bufferPos++; *prevMask |= 1; if (Test86MSByte(b)) *prevMask |= 0x10; } } return bufferPos; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #include "BranchTypes.h" #define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); } UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" #include "BranchIA64.c" UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" #include "Windows/Defs.h" #include "BranchPPC.c" UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" #include "Windows/Defs.h" #include "BranchSPARC.c" UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" #include "Windows/Defs.h" #include "BranchX86.c" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" #include "BranchX86.h" struct CBranch86 { UInt32 _prevMask; UInt32 _prevPos; void x86Init() { x86_Convert_Init(_prevMask, _prevPos); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" #include "../../../Common/Alloc.h" static const int kBufferSize = 1 << 17; inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } #ifndef EXTRACT_ONLY static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CBCJ2_x86_Encoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder() { ::MidFree(_buffer); } HRESULT CBCJ2_x86_Encoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256; i++) _statusE8Encoder[i].Init(); _statusE9Encoder.Init(); _statusJccEncoder.Init(); CCoderReleaser releaser(this); CMyComPtr getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; while(true) { UInt32 processedSize = 0; while(true) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else if (IsJcc(prevByte, b)) _statusJccEncoder.Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); if (convert) { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 1); else _statusJccEncoder.Encode(&_rangeEncoder, 1); bufferPos += 5; if (b == 0xE8) { _callStream.WriteByte((Byte)(dest >> 24)); _callStream.WriteByte((Byte)(dest >> 16)); _callStream.WriteByte((Byte)(dest >> 8)); _callStream.WriteByte((Byte)(dest)); } else { _jumpStream.WriteByte((Byte)(dest >> 24)); _jumpStream.WriteByte((Byte)(dest >> 16)); _jumpStream.WriteByte((Byte)(dest >> 8)); _jumpStream.WriteByte((Byte)(dest)); } prevByte = nextByte; } else { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else _statusJccEncoder.Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256; i++) _statusE8Decoder[i].Init(); _statusE9Decoder.Init(); _statusJccDecoder.Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; while(true) { if (processedBytes > (1 << 20) && progress != NULL) { UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } processedBytes++; Byte b; if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { prevByte = b; continue; } bool status; if (b == 0xE8) status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1); else if (b == 0xE9) status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1); else status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1); if (status) { UInt32 src; if (b == 0xE8) { Byte b0; if(!_callStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } else { Byte b0; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" // {23170F69-40C1-278B-0303-010100000100} #define MyClass2_a(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClass_a(Name, id, subId) \ MyClass2_a(Name ## _Encoder, id, subId, 0x01) \ MyClass2_a(Name ## _Decoder, id, subId, 0x00) MyClass_a(BCJ2_x86, 0x01, 0x1B) const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CBCJ2_x86_Encoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CBCJ2_x86_Encoder(): _buffer(0) {}; ~CBCJ2_x86_Encoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder _statusE8Encoder[256]; NCompress::NRangeCoder::CBitEncoder _statusE9Encoder; NCompress::NRangeCoder::CBitEncoder _statusJccEncoder; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CBCJ2_x86_Encoder *_coder; public: CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CBCJ2_x86_Decoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder _statusE8Decoder[256]; NCompress::NRangeCoder::CBitDecoder _statusE9Decoder; NCompress::NRangeCoder::CBitDecoder _statusJccDecoder; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CBCJ2_x86_Decoder *_coder; public: CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTree.h ================================================ // BinTree.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace BT_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinder: public IMatchFinder, public CLZInWindow, public CMyUnknownImp, public IMatchFinderSetNumPasses { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; CIndex *_son; UInt32 _hashMask; UInt32 _cutValue; UInt32 _hashSizeSum; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP STDMETHOD(SetStream)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(Init)(); HRESULT MovePos(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes); STDMETHOD_(void, ChangeBufferPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD(GetMatches)(UInt32 *distances); STDMETHOD(Skip)(UInt32 num); public: CMatchFinder(); virtual ~CMatchFinder(); virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; } }; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTree2.h ================================================ // BinTree2.h #ifndef __BINTREE2_H #define __BINTREE2_H #define BT_NAMESPACE NBT2 #include "BinTreeMain.h" #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTree3.h ================================================ // BinTree3.h #ifndef __BINTREE3_H #define __BINTREE3_H #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTree3Z.h ================================================ // BinTree3Z.h #ifndef __BINTREE3Z_H #define __BINTREE3Z_H #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTreeMain.h" #undef HASH_ZIP #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTree4.h ================================================ // BinTree4.h #ifndef __BINTREE4_H #define __BINTREE4_H #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/BinTree/BinTreeMain.h ================================================ // BinTreeMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" #include "BinTree.h" // #include // It's for prefetch // But prefetch doesn't give big gain in K8. namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #define kNumHashDirectBytes 0 #ifdef HASH_ARRAY_3 static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 16; #else static const UInt32 kNumHashBytes = 3; #endif static const UInt32 kHashSize = 0; static const UInt32 kMinMatchCheck = kNumHashBytes; static const UInt32 kStartMaxLen = 1; #else #ifdef HASH_ZIP #define kNumHashDirectBytes 0 static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; static const UInt32 kMinMatchCheck = kNumHashBytes; static const UInt32 kStartMaxLen = 1; #else #define kNumHashDirectBytes 2 static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kMinMatchCheck = kNumHashBytes + 1; static const UInt32 kStartMaxLen = 1; #endif #endif #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHash2Size; #endif #endif static const UInt32 kFixHashSize = 0 #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; CMatchFinder::CMatchFinder(): _hash(0) { } void CMatchFinder::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinder::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinder::~CMatchFinder() { FreeMemory(); } STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) { FreeMemory(); return E_INVALIDARG; } _cutValue = #ifdef _HASH_CHAIN 8 + (matchMaxLen >> 2); #else 16 + (matchMaxLen >> 1); #endif UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it UInt32 hs = kHashSize; #ifdef HASH_ARRAY_2 hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) { #ifdef HASH_ARRAY_3 hs >>= 1; #else hs = (1 << 24) - 1; #endif } _hashMask = hs; hs++; #endif _hashSizeSum = hs + kFixHashSize; UInt32 numItems = _hashSizeSum + _cyclicBufferSize #ifndef _HASH_CHAIN * 2 #endif ; size_t sizeInBytes = (size_t)numItems * sizeof(CIndex); if (sizeInBytes / sizeof(CIndex) != numItems) return E_OUTOFMEMORY; _hash = (CIndex *)BigAlloc(sizeInBytes); _son = _hash + _hashSizeSum; if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream) { CLZInWindow::SetStream(stream); return S_OK; } STDMETHODIMP CMatchFinder::Init() { RINOK(CLZInWindow::Init()); for(UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinder::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 #define HASH_CALC { \ UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; } #else // no HASH_ARRAY_3 #define HASH_CALC { \ UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kMinMatchCheck) { distances[0] = 0; return MovePos(); } } int offset = 1; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; const Byte *cur = _buffer + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; #endif UInt32 hashValue; HASH_CALC; #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[kFixHashSize + hashValue]; #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[hash2Value]; #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; #endif _hash[hash2Value] = _pos; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } #ifdef HASH_ARRAY_3 _hash[kHash3Offset + hash3Value] = _pos; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } #endif if (offset != 1 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } #endif _hash[kFixHashSize + hashValue] = _pos; CIndex *son = _son; #ifdef _HASH_CHAIN son[_cyclicBufferPos] = curMatch; #else CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; #endif #if kNumHashDirectBytes != 0 if(curMatch > matchMinPos) { if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } #endif UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { #ifndef _HASH_CHAIN *ptr0 = *ptr1 = kEmptyHashValue; #endif break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + #ifdef _HASH_CHAIN cyclicPos; #else (cyclicPos << 1); #endif // _mm_prefetch((const char *)pair, _MM_HINT_T0); const Byte *pb = _buffer + curMatch; UInt32 len = #ifdef _HASH_CHAIN kNumHashDirectBytes; if (pb[maxLen] == cur[maxLen]) #else MyMin(len0, len1); #endif if (pb[len] == cur[len]) { while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { #ifndef _HASH_CHAIN *ptr1 = pair[0]; *ptr0 = pair[1]; #endif break; } } } #ifdef _HASH_CHAIN curMatch = *pair; #else if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } #endif } distances[0] = offset - 1; if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP CMatchFinder::Skip(UInt32 num) { do { #ifdef _HASH_CHAIN if (_streamPos - _pos < kNumHashBytes) { RINOK(MovePos()); continue; } #else UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kMinMatchCheck) { RINOK(MovePos()); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; #endif const Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue; HASH_CALC; _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue; HASH_CALC; #endif _hash[hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; #ifdef _HASH_CHAIN _son[_cyclicBufferPos] = curMatch; #else CIndex *son = _son; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { *ptr0 = *ptr1 = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); // _mm_prefetch((const char *)pair, _MM_HINT_T0); const Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); if (pb[len] == cur[len]) { while(++len != lenLimit) if (pb[len] != cur[len]) break; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } #endif if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); } while(--num != 0); return S_OK; } void CMatchFinder::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = (_hashSizeSum + _cyclicBufferSize #ifndef _HASH_CHAIN * 2 #endif ); for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } HRESULT CMatchFinder::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes) { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; } STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos() { CLZInWindow::MoveBlock();} #undef HASH_CALC #undef kNumHashDirectBytes } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/HashChain/HC2.h ================================================ // HC2.h #ifndef __HC2_H #define __HC2_H #define BT_NAMESPACE NHC2 #include "HCMain.h" #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/HashChain/HC3.h ================================================ // HC3.h #ifndef __HC3_H #define __HC3_H #define BT_NAMESPACE NHC3 #define HASH_ARRAY_2 #include "HCMain.h" #undef HASH_ARRAY_2 #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/HashChain/HC4.h ================================================ // HC4.h #ifndef __HC4_H #define __HC4_H #define BT_NAMESPACE NHC4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef BT_NAMESPACE #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/HashChain/HCMain.h ================================================ // HCMain.h #define _HASH_CHAIN #include "../BinTree/BinTreeMain.h" #undef _HASH_CHAIN ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/IMatchFinder.h ================================================ // MatchFinders/IMatchFinder.h #ifndef __IMATCHFINDER_H #define __IMATCHFINDER_H struct IInWindowStream: public IUnknown { STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE; STDMETHOD_(void, ReleaseStream)() PURE; STDMETHOD(Init)() PURE; STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE; STDMETHOD_(void, ChangeBufferPos)() PURE; }; struct IMatchFinder: public IInWindowStream { STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; STDMETHOD(GetMatches)(UInt32 *distances) PURE; STDMETHOD(Skip)(UInt32 num) PURE; }; struct IMatchFinderSetNumPasses { virtual void SetNumPasses(UInt32 numPasses) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/LZInWindow.cpp ================================================ // LZInWindow.cpp #include "StdAfx.h" #include "LZInWindow.h" #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" void CLZInWindow::Free() { ::BigFree(_bufferBase); _bufferBase = 0; } bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == 0 || _blockSize != blockSize) { Free(); _blockSize = blockSize; if (_blockSize != 0) _bufferBase = (Byte *)::BigAlloc(_blockSize); } _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; if (_blockSize == 0) return true; return (_bufferBase != 0); } void CLZInWindow::SetStream(ISequentialInStream *stream) { _stream = stream; } HRESULT CLZInWindow::Init() { _buffer = _bufferBase; _pos = 0; _streamPos = 0; _streamEndWasReached = false; return ReadBlock(); } /* void CLZInWindow::ReleaseStream() { _stream.Release(); } */ /////////////////////////////////////////// // ReadBlock // In State: // (_buffer + _streamPos) <= (_bufferBase + _blockSize) // Out State: // _posLimit <= _blockSize - _keepSizeAfter; // if(_streamEndWasReached == false): // _streamPos >= _pos + _keepSizeAfter // _posLimit = _streamPos - _keepSizeAfter; // else // HRESULT CLZInWindow::ReadBlock() { if(_streamEndWasReached) return S_OK; while(true) { UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos; if(size == 0) return S_OK; UInt32 numReadBytes; RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; const Byte *pointerToPostion = _buffer + _posLimit; if(pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); _streamEndWasReached = true; return S_OK; } _streamPos += numReadBytes; if(_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; return S_OK; } } } void CLZInWindow::MoveBlock() { UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset; memmove(_bufferBase, _bufferBase + offset, numBytes); _buffer -= offset; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/LZInWindow.h ================================================ // LZInWindow.h #ifndef __LZ_IN_WINDOW_H #define __LZ_IN_WINDOW_H #include "../../IStream.h" class CLZInWindow { Byte *_bufferBase; // pointer to buffer with data ISequentialInStream *_stream; UInt32 _posLimit; // offset (from _buffer) when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream const Byte *_pointerToLastSafePosition; protected: Byte *_buffer; // Pointer to virtual Buffer begin UInt32 _blockSize; // Size of Allocated memory block UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream void MoveBlock(); HRESULT ReadBlock(); void Free(); public: CLZInWindow(): _bufferBase(0) {} virtual ~CLZInWindow() { Free(); } // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G) bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); void SetStream(ISequentialInStream *stream); HRESULT Init(); // void ReleaseStream(); Byte *GetBuffer() const { return _buffer; } const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } HRESULT MovePos() { _pos++; if (_pos > _posLimit) { const Byte *pointerToPostion = _buffer + _pos; if(pointerToPostion > _pointerToLastSafePosition) MoveBlock(); return ReadBlock(); } else return S_OK; } Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; } // index + limit have not to exceed _keepSizeAfter; // -2G <= index < 2G UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const { if(_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; const Byte *pby = _buffer + (size_t)_pos + index; UInt32 i; for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); return i; } UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } void ReduceOffsets(Int32 subValue) { _buffer += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } bool NeedMove(UInt32 numCheckBytes) { UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos); return (reserv <= numCheckBytes); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "../../../Common/Alloc.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS typedef COutBufferException CLZOutWindowException; #endif class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (distance >= _pos) { if (!_overDict || distance >= _bufferSize) return false; pos += _bufferSize; } do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); while (true) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { if (_outSizeDefined = (outSize != NULL)) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifdef _ST_MODE STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifdef _ST_MODE public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifdef _ST_MODE MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifdef _ST_MODE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // for minimal compressing code size define these: // #define COMPRESS_MF_BT // #define COMPRESS_MF_BT4 #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC) #define COMPRESS_MF_BT #define COMPRESS_MF_HC #endif #ifdef COMPRESS_MF_BT #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) #define COMPRESS_MF_BT2 #define COMPRESS_MF_BT3 #define COMPRESS_MF_BT4 #endif #ifdef COMPRESS_MF_BT2 #include "../LZ/BinTree/BinTree2.h" #endif #ifdef COMPRESS_MF_BT3 #include "../LZ/BinTree/BinTree3.h" #endif #ifdef COMPRESS_MF_BT4 #include "../LZ/BinTree/BinTree4.h" #endif #endif #ifdef COMPRESS_MF_HC #include "../LZ/HashChain/HC4.h" #endif #ifdef COMPRESS_MF_MT #include "../LZ/MT/MT.h" #endif namespace NCompress { namespace NLZMA { const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; enum { kBT2, kBT3, kBT4, kHC4 }; static const wchar_t *kMatchFinderIDs[] = { L"BT2", L"BT3", L"BT4", L"HC4" }; Byte g_FastPos[1 << 11]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < kNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < kNumLowSymbols + kNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); } for (; i < numSymbols; i++) prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _dictionarySizePrev(UInt32(-1)), _numFastBytesPrev(UInt32(-1)), _matchFinderCycles(0), _matchFinderIndex(kBT4), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false), setMfPasses(0) { // _maxMode = false; _fastMode = false; } HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_matchFinder) { switch(_matchFinderIndex) { #ifdef COMPRESS_MF_BT #ifdef COMPRESS_MF_BT2 case kBT2: { NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder; setMfPasses = mfSpec; _matchFinder = mfSpec; break; } #endif #ifdef COMPRESS_MF_BT3 case kBT3: { NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder; setMfPasses = mfSpec; _matchFinder = mfSpec; break; } #endif #ifdef COMPRESS_MF_BT4 case kBT4: { NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder; setMfPasses = mfSpec; _matchFinder = mfSpec; break; } #endif #endif #ifdef COMPRESS_MF_HC case kHC4: { NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder; setMfPasses = mfSpec; _matchFinder = mfSpec; break; } #endif } if (_matchFinder == 0) return E_OUTOFMEMORY; #ifdef COMPRESS_MF_MT if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4))) { CMatchFinderMT *mfSpec = new CMatchFinderMT; if (mfSpec == 0) return E_OUTOFMEMORY; CMyComPtr mf = mfSpec; RINOK(mfSpec->SetMatchFinder(_matchFinder)); _matchFinder.Release(); _matchFinder = mf; } #endif } if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return S_OK; RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes if (_matchFinderCycles != 0 && setMfPasses != 0) setMfPasses->SetNumPasses(_matchFinderCycles); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; return S_OK; } static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) { while (true) { wchar_t c = *testString; if (c >= 'a' && c <= 'z') c -= 0x20; if (*base != c) return false; if (c == 0) return true; base++; testString++; } } static int FindMatchFinder(const wchar_t *s) { for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) if (AreStringsEqual(kMatchFinderIDs[m], s)) return m; return -1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kMatchFinderCycles: { if (prop.vt != VT_UI4) return E_INVALIDARG; _matchFinderCycles = prop.ulVal; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); // _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; int matchFinderIndexPrev = _matchFinderIndex; int m = FindMatchFinder(prop.bstrVal); if (m < 0) return E_INVALIDARG; _matchFinderIndex = m; if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) { _dictionarySizePrev = (UInt32)-1; ReleaseMatchFinder(); } break; } #ifdef COMPRESS_MF_MT case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { _dictionarySizePrev = (UInt32)-1; ReleaseMatchFinder(); _multiThread = newMultiThread; } break; } case NCoderPropID::kNumThreads: { if (prop.vt != VT_UI4) return E_INVALIDARG; bool newMultiThread = (prop.ulVal > 1); if (newMultiThread != _multiThread) { _dictionarySizePrev = (UInt32)-1; ReleaseMatchFinder(); _multiThread = newMultiThread; } break; } #endif case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 30; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } HRESULT CEncoder::MovePos(UInt32 num) { if (num == 0) return S_OK; _additionalOffset += num; return _matchFinder->Skip(num); } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return S_OK; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain, numDistancePairs)); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); lenRes = 1; return S_OK; } if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; UInt32 backOffset = reps[i] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) { repLens[i] = 0; continue; } UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } UInt32 *matchDistances = _matchDistances + 1; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)-1; lenRes = 1; return S_OK; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while(--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > matchDistances[offs]) offs += 2; for(; ; len++) { UInt32 distance = matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); COptimal &optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + kNumRepDistances; optimum.Prev1IsChar = false; } if (len == matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } UInt32 newLen, numDistancePairs; RINOK(ReadMatchDistances(newLen, numDistancePairs)); if(newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; const Byte currentByte = *data; const Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } /* if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) // speed optimization { // try Literal + rep0 UInt32 backOffset = reps[0] + 1; UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; for (temp = 1; temp < limit && data[temp] == data[(size_t)temp - backOffset]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 lenTestTemp = lenTest; UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while(startLen > matchDistances[offs]) offs += 2; UInt32 curBack = matchDistances[offs + 1]; UInt32 posSlot = GetPosSlot2(curBack); for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice; UInt32 lenToPosState = GetLenToPosState(lenTest); if (curBack < kNumFullDistances) curAndLenPrice += _distancesPrices[lenToPosState][curBack]; else curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (/*_maxMode && */lenTest == matchDistances[offs]) { // Try Match + Literal + Rep0 UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (posStateNext + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; curBack = matchDistances[offs + 1]; if (curBack >= kNumFullDistances) posSlot = GetPosSlot2(curBack); } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { return ((bigDist >> 7) > smallDist); } HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs) { lenRes = 0; RINOK(_matchFinder->GetMatches(_matchDistances)); numDistancePairs = _matchDistances[0]; if (numDistancePairs > 0) { lenRes = _matchDistances[1 + numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1], kMatchMaxLen - lenRes); } _additionalOffset++; return S_OK; } HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain, numDistancePairs)); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); lenRes = 1; return S_OK; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { UInt32 backOffset = _repDistances[i] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); if(len >= _numFastBytes) { backRes = i; lenRes = len; return MovePos(lenRes - 1); } repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; } UInt32 *matchDistances = _matchDistances + 1; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } UInt32 backMain = 0; // for GCC if (lenMain >= 2) { backMain = matchDistances[numDistancePairs - 1]; while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) { if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) break; numDistancePairs -= 2; lenMain = matchDistances[numDistancePairs - 2]; backMain = matchDistances[numDistancePairs - 1]; } if (lenMain == 2 && backMain >= 0x80) lenMain = 1; } if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } } if (lenMain >= 2 && numAvailableBytes > 2) { RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs)); if (_longestMatchLength >= 2) { UInt32 newDistance = matchDistances[_numDistancePairs - 1]; if (_longestMatchLength >= lenMain && newDistance < backMain || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } } data++; numAvailableBytes--; for(UInt32 i = 0; i < kNumRepDistances; i++) { UInt32 backOffset = _repDistances[i] + 1; if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); if (len + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } } backRes = backMain + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 2); } backRes = UInt32(-1); lenRes = 1; return S_OK; } HRESULT CEncoder::Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { _needReleaseMFStream = false; CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); while(true) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) return S_OK; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; return S_OK; } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { RINOK(_matchFinder->SetStream(_inStream)); RINOK(_matchFinder->Init()); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return S_OK; _finished = true; if (nowPos64 == 0) { if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); UInt32 len, numDistancePairs; RINOK(ReadMatchDistances(len, numDistancePairs)); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } UInt32 nowPos32 = (UInt32)nowPos64; UInt32 progressPosValuePrev = nowPos32; if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(nowPos32); while(true) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos, len; HRESULT result; if (_fastMode) result = GetOptimumFast(nowPos32, pos, len); else result = GetOptimum(nowPos32, pos, len); RINOK(result); UInt32 posState = nowPos32 & _posStateMask; if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); if(_state.IsCharState()) subCoder->Encode(&_rangeEncoder, curByte); else { Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); } else { UInt32 distance = _repDistances[pos]; _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); if (pos == 3) _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; } _repDistances[1] = _repDistances[0]; _repDistances[0] = distance; } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); _state.UpdateRep(); } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); _alignPriceCount++; } } _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; _repDistances[1] = _repDistances[0]; _repDistances[0] = pos; _matchPriceCount++; } _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos32 += len; if (_additionalOffset == 0) { if (!_fastMode) { if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= kAlignTableSize) FillAlignPrices(); } if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(nowPos32); if (nowPos32 - progressPosValuePrev >= (1 << 14)) { nowPos64 += nowPos32 - progressPosValuePrev; *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); _finished = false; *finished = 0; return S_OK; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillDistancesPrices() { UInt32 tempPrices[kNumFullDistances]; for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; NRangeCoder::CBitTreeEncoder &encoder = _posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] = encoder.GetPrice(posSlot); for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); UInt32 *distancesPrices = _distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } }} ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/IMatchFinder.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; extern Byte g_FastPos[1 << 11]; inline UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return g_FastPos[pos >> 10] + 20; return g_FastPos[pos >> 20] + 40; } inline UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 27)) return g_FastPos[pos >> 16] + 32; return g_FastPos[pos >> 26] + 52; } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices[posState]); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) { CEncoder::Encode(rangeEncoder, symbol, posState); if (updatePrice) if (--_counters[posState] == 0) UpdateTable(posState); } }; } class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { COptimal _optimum[kNumOpts]; CMyComPtr _matchFinder; // test it NRangeCoder::CEncoder _rangeEncoder; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; bool _fastMode; // bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _dictionarySizePrev; UInt32 _numFastBytesPrev; UInt32 _matchPriceCount; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; UInt32 _matchFinderCycles; int _matchFinderIndex; #ifdef COMPRESS_MF_MT bool _multiThread; #endif bool _writeEndMark; bool _needReleaseMFStream; IMatchFinderSetNumPasses *setMfPasses; void ReleaseMatchFinder() { setMfPasses = 0; _matchFinder.Release(); } HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs); HRESULT MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const { UInt32 price; if(repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + GetPureRepPrice(repIndex, state, posState); } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseMFStream() { if (_matchFinder && _needReleaseMFStream) { _matchFinder->ReleaseStream(); _needReleaseMFStream = false; } } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Group "BT" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\BinTree\BinTree.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree2.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3Z.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTreeMain.h # End Source File # End Group # Begin Group "HC" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\HashChain\HC4.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HCMain.h # End Source File # End Group # Begin Source File SOURCE=..\LZ\IMatchFinder.h # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.h # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\Branch\BranchX86.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\LZMA_C\LzmaTypes.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\Alloc.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\String.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\String.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include #include #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBench.h" #include "LzmaRam.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kMatchFinderCycles, kLitContext, kLitPos, kPosBits, kMatchFinder, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kSimple, false } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA inputFile outputFile [...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary - [0,30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04\n"); if (n == 1) { PrintHelp(); return 0; } if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = 1 << 21; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 10; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchmark(stderr, numIterations, dictionary); } bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr outStream; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; COutFileStream *outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 2; UInt32 numFastBytes = 128; UInt32 matchFinderCycles = 16 + numFastBytes / 2; bool matchFinderCyclesDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); if (matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs) if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); /* NWindows::NCOM::CPropVariant properties[kNumProps]; properties[0] = UInt32(dictionary); properties[1] = UInt32(posStateBits); properties[2] = UInt32(litContextBits); properties[3] = UInt32(litPosBits); properties[4] = UInt32(algorithm); properties[5] = UInt32(numFastBytes); properties[6] = mf; properties[7] = eos; */ PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[8].vt = VT_UI4; properties[8].ulVal = UInt32(matchFinderCycles); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; int numProps = kNumPropsMax; if (!matchFinderCyclesDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #include #endif #include "../../../Common/CRC.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" static const UInt32 kAdditionalSize = #ifdef _WIN32_WCE (1 << 20); #else (6 << 20); #endif static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public: CRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBitRandomGenerator { CRandomGenerator RG; UInt32 Value; int NumBits; public: void Init() { Value = 0; NumBits = 0; } UInt32 GetRnd(int numBits) { if (NumBits > numBits) { UInt32 result = Value & ((1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; UInt32 result = (Value << numBits); Value = RG.GetRnd(); result |= Value & ((1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG; UInt32 Pos; UInt32 Rep0; public: UInt32 BufferSize; Byte *Buffer; CBenchRandomGenerator(): Buffer(0) {} ~CBenchRandomGenerator() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(UInt32 bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); Pos = 0; BufferSize = bufferSize; return (Buffer != 0); } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd(len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } void Generate() { RG.Init(); Rep0 = 1; while(Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; UInt32 Pos; UInt32 Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, UInt32 size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CMyUnknownImp { UInt32 BufferSize; FILE *_f; public: UInt32 Pos; Byte *Buffer; CBenchmarkOutStream(): _f(0), Buffer(0) {} virtual ~CBenchmarkOutStream() { delete []Buffer; } void Init(FILE *f, UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; _f = f; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < BufferSize; i++) Buffer[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { fprintf(_f, "\nERROR: Buffer is full\n"); return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: CCRC CRC; MY_UNKNOWN_IMP void Init() { CRC.Init(); } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { CRC.Update(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; return GetTickCount(); #else return clock(); #endif } static UInt64 GetFreq() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; return 1000; #else return CLOCKS_PER_SEC; #endif } struct CProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { UInt64 ApprovedStart; UInt64 InSize; UInt64 Time; void Init() { InSize = 0; Time = 0; } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { if (*inSize >= ApprovedStart && InSize == 0) { Time = ::GetTimeCount(); InSize = *inSize; } return S_OK; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = GetFreq(); UInt64 elTime = elapsedTime; while(freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } /* static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } */ static void PrintRating(FILE *f, UInt64 rating) { fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000)); } static void PrintResults( FILE *f, UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024)); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(f, rating); } static void ThrowError(FILE *f, HRESULT result, const char *s) { fprintf(f, "\nError: "); if (result == E_ABORT) fprintf(f, "User break"); if (result == E_OUTOFMEMORY) fprintf(f, "Can not allocate memory"); else fprintf(f, s); fprintf(f, "\n"); } const wchar_t *bt2 = L"BT2"; const wchar_t *bt4 = L"BT4"; int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize) { if (numIterations == 0) return 0; if (dictionarySize < (1 << 18)) { fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n"); return 1; } fprintf(f, "\n Compressing Decompressing\n\n"); NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream; CMyComPtr propStream = propStreamSpec; propStreamSpec->Init(f, kMaxLzmaPropSize); PROPID propIDs[] = { NCoderPropID::kDictionarySize }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = UInt32(dictionarySize); const UInt32 kBufferSize = dictionarySize + kAdditionalSize; const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) { fprintf(f, "\nError: Incorrect command\n"); return 1; } encoderSpec->WriteCoderProperties(propStream); CBenchRandomGenerator rg; if (!rg.Alloc(kBufferSize)) { fprintf(f, "\nError: Can't allocate memory\n"); return 1; } rg.Generate(); CCRC crc; crc.Update(rg.Buffer, rg.BufferSize); CProgressInfo *progressInfoSpec = new CProgressInfo; CMyComPtr progressInfo = progressInfoSpec; progressInfoSpec->ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; for (UInt32 i = 0; i < numIterations; i++) { progressInfoSpec->Init(); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; inStreamSpec->Init(rg.Buffer, rg.BufferSize); CMyComPtr inStream = inStreamSpec; CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream; outStreamSpec->Init(f, kCompressedBufferSize); CMyComPtr outStream = outStreamSpec; HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo); UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time; UInt32 compressedSize = outStreamSpec->Pos; if(result != S_OK) { ThrowError(f, result, "Encoder Error"); return 1; } if (progressInfoSpec->InSize == 0) { fprintf(f, "\nError: Internal ERROR 1282\n"); return 1; } /////////////////////// // Decompressing CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr crcOutStream = crcOutStreamSpec; UInt64 decodeTime; for (int j = 0; j < 2; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK) { fprintf(f, "\nError: Set Decoder Properties Error\n"); return 1; } UInt64 outSize = kBufferSize; UInt64 startTime = ::GetTimeCount(); result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0); decodeTime = ::GetTimeCount() - startTime; if(result != S_OK) { ThrowError(f, result, "Decode Error"); return 1; } if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest()) { fprintf(f, "\nError: CRC Error\n"); return 1; } } UInt64 benchSize = kBufferSize - progressInfoSpec->InSize; PrintResults(f, dictionarySize, encodeTime, benchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, decodeTime, kBufferSize, true, compressedSize); fprintf(f, "\n"); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } fprintf(f, "---------------------------------------------------\n"); PrintResults(f, dictionarySize, totalEncodeTime, totalBenchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, totalDecodeTime, kBufferSize * numIterations, true, totalCompressedSize); fprintf(f, " Average\n"); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LzmaBench_h #define __LzmaBench_h #include #include "../../../Common/Types.h" int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZE_FAIL (1) #define SZE_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZE_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1); } UInt32 minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZE_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZE_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZE_OUTOFMEMORY; } #endif } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../LZMA_C/LzmaDecode.h" #include "../Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/comp.cc ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: comp.cc,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ // extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp #include #include #include #include #include "StdAfx.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/MyWindows.h" #include "../../../Common/StringConvert.h" #include "../LZMA/LZMAEncoder.h" #include #include #include "sqlzma.h" ////////////////////////////////////////////////////////////////////// class CMemoryStream { protected: Bytef *m_data; UInt64 m_limit; UInt64 m_pos; public: CMemoryStream(Bytef *data, UInt64 size) : m_data(data), m_limit(size), m_pos(0) {} virtual ~CMemoryStream() {} }; class CInMemoryStream : public CMemoryStream, public IInStream, public CMyUnknownImp { //protected: CMyComPtr m_stream; public: MY_UNKNOWN_IMP1(IInStream); CInMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~CInMemoryStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { UInt64 room = m_limit - m_pos; if (size > room) size = room; if (size) { memcpy(data, m_data + m_pos, size); m_pos += size; } if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } }; class COutMemoryStream : public CMemoryStream, public IOutStream, public CMyUnknownImp { //protected: CMyComPtr m_stream; public: MY_UNKNOWN_IMP1(IOutStream); COutMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~COutMemoryStream() {} UInt32 GetSize() {return m_pos;} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (m_pos + size > m_limit) return -ENOSPC; memcpy(m_data + m_pos, data, size); m_pos += size; if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } STDMETHOD(SetSize)(Int64 newSize) { assert(0); return E_NOTIMPL; } }; ////////////////////////////////////////////////////////////////////// static int LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, uLong *total_out) { int err; HRESULT res; const Byte a[] = { avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, 0, 0, 0, 0 }; NCompress::NLZMA::CEncoder encoderSpec; CMyComPtr encoder = &encoderSpec; encoder->AddRef(); CInMemoryStream inStreamSpec(next_in, avail_in); CMyComPtr inStream = &inStreamSpec; inStream->AddRef(); COutMemoryStream outStreamSpec(next_out, avail_out); CMyComPtr outStream = &outStreamSpec; outStream->AddRef(); // these values are dpending upon is_lzma() macro in sqlzma.h const UInt32 dictionary = 1 << 23; const UString mf = L"BT4"; const UInt32 posStateBits = 2; const UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data const UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data const UInt32 algorithm = 2; const UInt32 numFastBytes = 128; const UInt32 matchFinderCycles = 16 + numFastBytes / 2; //const bool matchFinderCyclesDefined = false; const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_FALSE; // EOS properties[8].vt = VT_UI4; properties[8].ulVal = UInt32(matchFinderCycles); err = -EINVAL; res = encoderSpec.SetCoderProperties(propIDs, properties, kNumPropsMax - 1); if (res) goto out; res = encoderSpec.WriteCoderProperties(outStream); if (res) goto out; UInt32 r; res = outStream->Write(a, sizeof(a), &r); if (res || r != sizeof(a)) goto out; err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); if (err) goto out; *total_out = outStreamSpec.GetSize(); out: return err; } ////////////////////////////////////////////////////////////////////// #define Failure(p) do { \ fprintf(stderr, "%s:%d: please report to jro " \ "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ __func__, __LINE__, \ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ abort(); \ }while(0) extern "C" int sqlzma_cm(int try_lzma, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out) { int err; Bytef *p = next_out; uInt l = avail_out; stream->next_in = next_in; stream->avail_in = avail_in; stream->next_out = p; stream->avail_out = l; err = deflate(stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) goto out_err; if (avail_in < stream->total_out) return err; if (is_lzma(*p)) Failure(p); if (try_lzma) { unsigned char a[stream->total_out]; uLong processed; memcpy(a, p, stream->total_out); // malloc family in glibc and stdc++ seems to be thread-safe err = LzmaCompress(next_in, avail_in, p, l, &processed); if (!err && processed <= stream->total_out) { if (!is_lzma(*next_out)) Failure(next_out); stream->total_out = processed; err = Z_STREAM_END; } else { //puts("by zlib"); memcpy(p, a, stream->total_out); err = Z_STREAM_END; } } return err; out_err: fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); return err; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) -I ../../../ LIBS = $(LIBS) oleaut32.lib user32.lib !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\Alloc.obj \ $O\CRC.obj \ $O\CommandLineParser.obj \ $O\String.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Vector.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ $O\LZOutWindow.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaRam.o \ LzmaRamDecode.o \ LzmaDecode.o \ BranchX86.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c LzmaDecode.o: ../LZMA_C/LzmaDecode.c $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c BranchX86.o: ../Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_Alone/sqlzma.mk ================================================ # Copyright (C) 2006 Junjiro Okajima # Copyright (C) 2006 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef UseDebugFlags DebugFlags = -Wall -O0 -g -UNDEBUG endif # -pthread CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} Tgt = liblzma_r.a all: ${Tgt} RObjs = LZMAEncoder_r.o Alloc_r.o LZInWindow_r.o CRC_r.o StreamUtils_r.o \ OutBuffer_r.o RangeCoderBit_r.o %_r.cc: ../LZMA/%.cpp ln $< $@ %_r.cc: ../LZ/%.cpp ln $< $@ %_r.cc: ../RangeCoder/%.cpp ln $< $@ %_r.cc: ../../Common/%.cpp ln $< $@ %_r.cc: ../../../Common/%.cpp ln $< $@ LZMAEncoder_r.o: CXXFLAGS += -I../LZMA LZInWindow_r.o: CXXFLAGS += -I../LZ RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder OutBuffer_r.o StreamUtils_r.o: CXXFLAGS += -I../../Common Alloc_r.o CRC_r.o: CXXFLAGS += -I../../../Common comp.o: CXXFLAGS += -I${Sqlzma} comp.o: comp.cc ${Sqlzma}/sqlzma.h liblzma_r.a: ${RObjs} comp.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) comp.o *_r.o ${Tgt} *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaDecode.c ================================================ /* LzmaDecode.c LZMA Decoder (optimized for Speed version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #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; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaDecode.h ================================================ /* LzmaDecode.h LZMA Decoder interface LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 #include "LzmaTypes.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 */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #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 ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; while(1) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H #include "LzmaTypes.h" /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include #include #include #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include #include #include #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/LzmaTypes.h ================================================ /* LzmaTypes.h Types for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.40 (2006-05-01) */ #ifndef __LZMATYPES_H #define __LZMATYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif /* #define _LZMA_SYSTEM_SIZE_T */ /* Use system's size_t. You can use it to enable 64-bit sizes supporting */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_SYSTEM_SIZE_T #include typedef size_t SizeT; #else typedef UInt32 SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/kmod/Makefile ================================================ # Copyright (C) 2006 Junjiro Okajima # Copyright (C) 2006 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: Makefile,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ obj-m += unlzma.o sqlzma.o unlzma-y := module.o sqlzma-y := uncomp.o ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/kmod/module.c ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: module.c,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ #include #include #include "../LzmaDecode.c" EXPORT_SYMBOL(LzmaDecodeProperties); EXPORT_SYMBOL(LzmaDecode); #if 0 static int __init unlzma_init(void) { return 0; } static void __exit unlzma_exit(void) { } module_init(unlzma_init); module_exit(unlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_VERSION("$Id: module.c,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $"); MODULE_DESCRIPTION("LZMA uncompress. " "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/kmod.mk ================================================ # Copyright (C) 2006 Junjiro Okajima # Copyright (C) 2006 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: kmod.mk,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif ifndef KDir $(error KDir is not defined) endif #include makefile.gcc Kmod = kmod EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} # -D_LZMA_PROB32 EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) all: ${Kmod}/uncomp.c ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ -C ${KDir} C=0 V=0 modules ${Kmod}/uncomp.c: uncomp.c ln $< $@ clean: clean_kmod clean_kmod: ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean ${RM} ${Kmod}/*~ -@test -e ${Kmod}/uncomp.c && \ diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/makefile ================================================ PROG = lzmaDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** OBJS = \ $O\LzmaTest.obj \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\LzmaTest.obj: $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/makefile.gcc ================================================ PROG = lzmadec CXX = gcc LIB = RM = rm -f CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 OBJS = LzmaTest.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaTest.o: LzmaTest.c $(CXX) $(CFLAGS) LzmaTest.c LzmaDecode.o: LzmaDecode.c $(CXX) $(CFLAGS) LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/sqlzma.mk ================================================ # Copyright (C) 2006 Junjiro Okajima # Copyright (C) 2006 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef KDir include kmod.mk endif ifdef UseDebugFlags DebugFlags = -O0 -g -UNDEBUG endif CFLAGS += -DNDEBUG ${DebugFlags} Tgt = libunlzma.a libunlzma_r.a all: ${Tgt} %_r.c: %.c ln $< $@ # -pthread %_r.o: CFLAGS += -D_REENTRANT -include pthread.h uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h libunlzma.a: uncomp.o LzmaDecode.o ${AR} cr $@ $^ libunlzma_r.a: uncomp_r.o LzmaDecode_r.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/testflags.c ================================================ #ifdef _LZMA_PROB32 -D_LZMA_PROB32 #else -U_LZMA_PROB32 #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/LZMA_C/uncomp.c ================================================ /* * Copyright (C) 2006, 2007 Junjiro Okajima * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include #include #include #include #include #include #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include #include #include #include #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void*)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (err) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 0; if (un->un_lzma && is_lzma(*src->buf)) { by_lzma = 1; un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (err) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima "); MODULE_VERSION("$Id: uncomp.c,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template class CBitEncoder: public CBitModel { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template class CBitDecoder: public CBitModel { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template class CBitTreeEncoder { CBitEncoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template class CBitTreeDecoder { CBitDecoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template void ReverseBitTreeEncode(CBitEncoder *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template UInt32 ReverseBitTreeDecode(CBitDecoder *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" // "23170F69-40C1-278A-0000-000400xx0000" #define CODER_INTERFACE(i, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ struct i: public IUnknown CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" // "23170F69-40C1-278A-0000-000300xx0000" #define STREAM_INTERFACE_SUB(i, b, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ struct i: public b #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Alloc.cpp ================================================ // Common/Alloc.cpp #include "StdAfx.h" #ifdef _WIN32 #include "MyWindows.h" #else #include #endif #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return ::malloc(size); } void MyFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif ::free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } static SIZE_T g_LargePageSize = #ifdef _WIN64 (1 << 21); #else (1 << 22); #endif typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); bool SetLargePageSize() { GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return false; SIZE_T size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return false; g_LargePageSize = size; return true; } void *BigAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif if (size >= (1 << 18)) { void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Alloc.h ================================================ // Common/Alloc.h #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size) throw(); void MyFree(void *address) throw(); #ifdef _WIN32 bool SetLargePageSize(); void *MidAlloc(size_t size) throw(); void MidFree(void *address) throw(); void *BigAlloc(size_t size) throw(); void BigFree(void *address) throw(); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" #include "CRC.h" static const UInt32 kCRCPoly = 0xEDB88320; UInt32 CCRC::Table[256]; void CCRC::InitTable() { for (UInt32 i = 0; i < 256; i++) { UInt32 r = i; for (int j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCRCPoly; else r >>= 1; CCRC::Table[i] = r; } } class CCRCTableInit { public: CCRCTableInit() { CCRC::InitTable(); } } g_CRCTableInit; void CCRC::UpdateByte(Byte b) { _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); } void CCRC::UpdateUInt16(UInt16 v) { UpdateByte(Byte(v)); UpdateByte(Byte(v >> 8)); } void CCRC::UpdateUInt32(UInt32 v) { for (int i = 0; i < 4; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::UpdateUInt64(UInt64 v) { for (int i = 0; i < 8; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::Update(const void *data, size_t size) { UInt32 v = _value; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); _value = v; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/CRC.h ================================================ // Common/CRC.h #ifndef __COMMON_CRC_H #define __COMMON_CRC_H #include #include "Types.h" class CCRC { UInt32 _value; public: static UInt32 Table[256]; static void InitTable(); CCRC(): _value(0xFFFFFFFF){}; void Init() { _value = 0xFFFFFFFF; } void UpdateByte(Byte v); void UpdateUInt16(UInt16 v); void UpdateUInt32(UInt32 v); void UpdateUInt64(UInt64 v); void Update(const void *data, size_t size); UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } static UInt32 CalculateDigest(const void *data, size_t size) { CCRC crc; crc.Update(data, size); return crc.GetDigest(); } static bool VerifyDigest(UInt32 digest, const void *data, size_t size) { return (CalculateDigest(data, size) == digest); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include #include namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include #include #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); while (true) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) return; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "Common/String.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } template inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } template class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline bool operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return false; return true; } inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include #else #define INITGUID #include "MyGuidDef.h" #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include #else #define MIDL_INTERFACE(x) struct #endif #else #include #endif #include #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include // for wchar_t #include #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; }; typedef IUnknown *LPUNKNOWN; #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/String.cpp ================================================ // Common/String.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include #endif #include "Common/String.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { while (true) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/String.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include // #include #include "Vector.h" #ifdef _WIN32 #include "MyWindows.h" #endif static const char *kTrimDefaultCharSet = " \n\t"; template inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)CharUpperW((LPWSTR)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)CharLowerW((LPWSTR)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; while (true) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; while (true) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase charSet; for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / sizeof(kTrimDefaultCharSet[0])); i++) charSet += (T)kTrimDefaultCharSet[i]; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template CStringBase operator+(const CStringBase& s1, const CStringBase& s2) { CStringBase result(s1); result += s2; return result; } template CStringBase operator+(const CStringBase& s, T c) { CStringBase result(s); result += c; return result; } template CStringBase operator+(T c, const CStringBase& s) { CStringBase result(c); result += s; return result; } template CStringBase operator+(const CStringBase& s, const T * chars) { CStringBase result(s); result += chars; return result; } template CStringBase operator+(const T * chars, const CStringBase& s) { CStringBase result(chars); result += s; return result; } template bool operator==(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) == 0); } template bool operator<(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) < 0); } template bool operator==(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) == 0); } template bool operator==(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) == 0); } template bool operator!=(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) != 0); } template bool operator!=(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) != 0); } template bool operator!=(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase AString; typedef CStringBase UString; typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, NULL, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "Common/String.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT codePage) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; while(true) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_INT16_DEFINED #define _7ZIP_INT16_DEFINED typedef short Int16; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED typedef int Int32; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED typedef unsigned int UInt32; #endif #ifdef _MSC_VER #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef __int64 Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned __int64 UInt64; #endif #else #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef long long int Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned long long int UInt64; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Vector.cpp ================================================ // Common/Vector.cpp #include "StdAfx.h" #include #include "Vector.h" CBaseRecordVector::~CBaseRecordVector() { delete []((unsigned char *)_items); } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if(_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if(newCapacity <= _capacity) return; /* #ifndef _DEBUG static const unsigned int kMaxVectorSize = 0xF0000000; if(newCapacity < _size || ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize) throw 1052354; #endif */ unsigned char *p = new unsigned char[newCapacity * _itemSize]; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Common/Vector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } void Sort(int left, int right) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (operator[](i) < operator[](left)) Swap(++last, i); Swap(left, last); Sort(left, last); Sort(last + 1, right); } void Sort() { Sort(0, Size()); } void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (compare(&operator[](i), &operator[](left), param) < 0) Swap(++last, i); Swap(left, last); Sort(left, last, compare, param); Sort(last + 1, right, compare, param); } void Sort(int (*compare)(const T*, const T*, void *), void *param) { Sort(0, Size(), compare, param); } }; typedef CRecordVector CIntVector; typedef CRecordVector CUIntVector; typedef CRecordVector CBoolVector; typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void *param) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { Close(); _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (g_IsNT) { Close(); _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); } #endif bool CFileBase::Close() { if(!_fileIsOpen) return true; bool result = BOOLToBool(::CloseHandle(_handle)); _fileIsOpen = !result; return result; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCTSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCWSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). static UInt32 kChunkSizeMax = (1 << 24); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: bool _fileIsOpen; HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _fileIsOpen(false){}; virtual ~CFileBase(); virtual bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/C/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CPL.html ================================================ Common Public License - v 1.0

Common Public License - v 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

    a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
    b) in the case of each subsequent Contributor:
    i) changes to the Program, and
    ii) additions to the Program;
    where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

    a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
    b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
    c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
    d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

    a) it complies with the terms and conditions of this Agreement; and
    b) its license agreement:
    i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
    ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
    iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
    iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

    a) it must be made available under this Agreement; and
    b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; } } public void Init(System.IO.Stream stream) { Init(stream, false); } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-15\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[12]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; FileStream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================  Debug AnyCPU 8.0.50727 2.0 {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973} Exe LzmaAlone Lzma# 4 true full false .\bin\Debug\ DEBUG;TRACE false true .\bin\Release\ TRACE AnyCPU Common\CommandLineParser.cs Common\CRC.cs ICoder.cs LZ\IMatchFinder.cs LZ\LzBinTree.cs LZ\LzInWindow.cs LZ\LzOutWindow.cs LZMA\LzmaBase.cs LZMA\LzmaDecoder.cs LZMA\LzmaEncoder.cs RangeCoder\RangeCoder.cs RangeCoder\RangeCoderBit.cs RangeCoder\RangeCoderBitTree.cs Code Code True Settings.settings SettingsSingleFileGenerator Settings.cs ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// /// LZMA Benchmark /// internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// /// The exception that is thrown when an error in input stream occurs during decoding. /// class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// /// The exception that is thrown when the value of an argument is outside the allowable range. /// class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// /// Callback progress. /// /// /// input size. -1 if unknown. /// /// /// output size. -1 if unknown. /// void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// /// Codes streams. /// /// /// input Stream. /// /// /// output Stream. /// /// /// input Size. -1 if unknown. /// /// /// output Size. -1 if unknown. /// /// /// callback progress reference. /// /// /// if input stream is not valid /// void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// /// Provides the fields that represent properties idenitifiers for compressing. /// public enum CoderPropID { /// /// Specifies size of dictionary. /// DictionarySize = 0x400, /// /// Specifies size of memory for PPM*. /// UsedMemorySize, /// /// Specifies order for PPM methods. /// Order, /// /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// PosStateBits = 0x440, /// /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// LitContextBits, /// /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// LitPosBits, /// /// Specifies number of fast bytes for LZ*. /// NumFastBytes = 0x450, /// /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// MatchFinder, /// /// Specifies number of passes. /// NumPasses = 0x460, /// /// Specifies number of algorithm. /// Algorithm = 0x470, /// /// Specifies multithread mode. /// MultiThread = 0x480, /// /// Specifies mode with end marker. /// EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols< 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-15\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/LGPL.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/Methods.txt ================================================ Compression method IDs (4.38) ----------------------------- Each compression method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 15 bytes. If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Use such random ID: 03 E0 ZZ ... ZZ MM ... MM VV ... VV ZZ != 0, MM != 0, VV != 0 03 E0 - Prefix for random IDs ZZ ... ZZ - Developer ID. (length >= 4). Use real random bytes. You can notify 7-Zip developers about your Developer ID. MM ... MM - Method ID (length >= 1) VV ... VV - Version (length >= 1) Note: Use new ID (MM ... MM VV .. VV) only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 01 - Reserved 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 04 Delta (subject to change) 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - BC_PPC_B (Big Endian) 03 - Alpha 01 - BC_Alpha 04 - IA64 01 - BC_IA64 05 - ARM 01 - BC_ARM 06 - M68 05 - BC_M68_B (Big Endian) 07 - ARM Thumb 01 - BC_ARMThumb 08 - SPARC 05 - BC_SPARC 04 - PPMD 01 - Version 80 - reserved for independent developers E0 - Random IDs 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- Version 4.43 2006-06-04 -------------------------------------- - Small changes for more compatibility with some C/C++ compilers. Version 4.42 2006-05-15 -------------------------------------- - Small changes in .h files in ANSI-C version. Version 4.39 beta 2006-04-14 -------------------------------------- - Bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). Version 4.37 beta 2005-04-06 -------------------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. Version 4.35 beta 2005-03-02 -------------------------------------- - Bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. Version 4.34 beta 2006-02-27 -------------------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 Version 4.32 2005-12-09 -------------------------------------- - Java version of LZMA SDK was included Version 4.30 2005-11-20 -------------------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - Bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included Version 4.27 (Updated) 2005-09-21 -------------------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart Version 4.27 2005-08-07 -------------------------------------- - Bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. Version 4.26 2005-08-05 -------------------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 Version 4.23 2005-06-29 -------------------------------------- - Small fixes in C++ code Version 4.22 2005-06-10 -------------------------------------- - Small fixes Version 4.21 2005-06-08 -------------------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB Version 4.17 2005-04-18 -------------------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe Version 4.16 2005-03-29 -------------------------------------- - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included Version 4.06 2004-09-05 -------------------------------------- - Bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. Version 4.05 2004-08-25 -------------------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes Version 4.04 2004-07-28 -------------------------------------- - More compatibility with some C++ compilers Version 4.03 2004-06-18 -------------------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. Version 4.02 2004-06-10 -------------------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. Version 4.01 2004-02-15 -------------------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } Version 4.00 2004-02-13 -------------------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2006: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/lzma.txt ================================================ LZMA SDK 4.43 ------------- LZMA SDK Copyright (C) 1999-2006 Igor Pavlov LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is available under any of the following licenses: 1) GNU Lesser General Public License (GNU LGPL) 2) Common Public License (CPL) 3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 4) Proprietary license It means that you can select one of these four options and follow rules of that license. 1,2) GNU LGPL and CPL licenses are pretty similar and both these licenses are classified as - "Free software licenses" at http://www.gnu.org/ - "OSI-approved" at http://www.opensource.org/ 3) 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 files from LZMA SDK without subjecting your linked code to the terms of the CPL or GNU LGPL. Any modifications or additions to files from LZMA SDK, however, are subject to the GNU LGPL or CPL terms. SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, while you keep LZMA SDK code unmodified. SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits you to use this code under the same terms and conditions contained in the License Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov. SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version of LZMA SDK as update for previous versions. SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits you to use code of the following files: BranchTypes.h, LzmaTypes.h, LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, LzmaAlone.cs, LzmaAlone.java as public domain code. 4) Proprietary license LZMA SDK also can be available under a proprietary license which can include: 1) Right to modify code without subjecting modified code to the terms of the CPL or GNU LGPL 2) Technical support for code To request such proprietary license or any additional consultations, send email message from that page: http://www.7-zip.org/support.html You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You should have received a copy of the Common Public License along with this library. LZMA SDK Contents ----------------- LZMA SDK includes: - C++ source code of LZMA compressing and decompressing - ANSI-C compatible source code for LZMA decompressing - C# source code for LZMA compressing and decompressing - Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system ANSI-C LZMA decompression code was ported from original C++ sources to C. Also it was simplified and optimized for code size. But it is fully compatible with LZMA from 7-Zip. UNIX/Linux version ------------------ To compile C++ version of file->file LZMA, go to directory C/7zip/Compress/LZMA_Alone and type "make" or "make clean all" to recompile all. In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, change string in makefile LIB = -lm to string LIB = -lm -static Files --------------------- C - C / CPP source code CS - C# source code Java - Java source code lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description (this file) methods.txt - Compression method IDs for .7z LGPL.txt - GNU Lesser General Public License CPL.html - Common Public License lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C - C / CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm BinTree - Binary Tree Match Finder for LZ algorithm HashChain - Hash Chain Match Finder for LZ algorithm Patricia - Patricia Match Finder for LZ algorithm RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression LZMA_C - ANSI-C compatible LZMA decompressor LzmaDecode.h - interface for LZMA decoding on ANSI-C LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version) LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version) LzmaTest.c - test application that decodes LZMA encoded file LzmaTypes.h - basic types for LZMA Decoder LzmaStateDecode.h - interface for LZMA decoding (State version) LzmaStateDecode.c - LZMA decoding on ANSI-C (State version) LzmaStateTest.c - test application (State version) Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving 7z_C - 7z ANSI-C Decoder CS - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. You can find ANSI-C LZMA decompressing code at folder C/7zip/Compress/LZMA_C 7-Zip doesn't use that ANSI-C LZMA code and that code was developed specially for this SDK. And files from LZMA_C do not need files from other directories of SDK for compiling. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 1 MB/s on 1 GHz CPU - Estimated decompressing speed: - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (8-32 KB + DictionarySize) - Small code size for decompressing: 2-8 KB (depending from speed optimizations) LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect to speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations Speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA inputFile outputFile [...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with AMD Athlon 64 X2 CPU results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you can change number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Using Filters ------------- You can increase compression ratio for some data types, using special filters before compressing. For example, it's possible to increase compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C/C++ source code of such filters in folder "7zip/Compress/Branch" You can check compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=bc_arm -m1=lzma With filter for big-endian ARM code (using additional Swap4 filter): 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. Source code of these CALL filters is pretty simple (about 20 lines of C++), so you can convert it from C++ version yourself. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties for compressed data 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ To compile ANSI-C LZMA Decoder you can use one of the following files sets: 1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version) 2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version) 3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface) Memory requirements for LZMA decoding ------------------------------------- LZMA decoder doesn't allocate memory itself, so you must allocate memory and send it to LZMA. Stack usage of LZMA decoding function for local variables is not larger than 200 bytes. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 5 interfaces: 1) Single-call Decompressing 2) Single-call Decompressing with input stream callback 3) Multi-call Decompressing with output buffer 4) Multi-call Decompressing with input callback and output buffer 5) Multi-call State Decompressing (zlib-like interface) Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions. Decompressing steps ------------------- 1) read LZMA properties (5 bytes): unsigned char properties[LZMA_PROPERTIES_SIZE]; 2) read uncompressed size (8 bytes, little-endian) 3) Decode properties: CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); 4) Allocate memory block for internal Structures: state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); LZMA decoder uses array of CProb variables as internal structure. By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make it unsigned_int. It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case. 5) Main Decompressing You must use one of the following interfaces: 5.1 Single-call Decompressing ----------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: int res = LzmaDecode(&state, inStream, compressedSize, &inProcessed, outStream, outSize, &outProcessed); 5.2 Single-call Decompressing with input stream callback -------------------------------------------------------- When to use: File->RAM or Flash->RAM decompressing. Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) { CBuffer *bo = (CBuffer *)object; *buffer = bo->Buffer; *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize); return LZMA_RESULT_OK; } CBuffer g_InBuffer; g_InBuffer.File = inFile; g_InBuffer.InCallback.Read = LzmaReadCompressed; int res = LzmaDecode(&state, &g_InBuffer.InCallback, outStream, outSize, &outProcessed); 5.3 Multi-call decompressing with output buffer ----------------------------------------------- When to use: RAM->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_OUT_READ Memory Requirements: - Input buffer: compressed size - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaTest.c for more details. 5.4 Multi-call decompressing with input callback and output buffer ------------------------------------------------------------------ When to use: File->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, &bo.InCallback, g_OutBuffer, outAvail, &outProcessed); } while you need more bytes see LzmaTest.c for more details: 5.5 Multi-call State Decompressing (zlib-like interface) ------------------------------------------------------------------ When to use: file->file decompressing Compile files: LzmaStateDecode.h, LzmaStateDecode.c Compile defines: Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaStateTest.c for more details: 6) Free all allocated blocks Note ---- LzmaDecodeSize.c is size-optimized version of LzmaDecode.c. But compiled code of LzmaDecodeSize.c can be larger than compiled code of LzmaDecode.c. So it's better to use LzmaDecode.c in most cases. EXIT codes ----------- LZMA decoder can return one of the following codes: #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 If you use callback function for input data and you return some error code, LZMA Decoder also returns that code. LZMA Defines ------------ _LZMA_IN_CB - Use callback for input data _LZMA_OUT_READ - Use read function for output data _LZMA_LOC_OPT - Enable local speed optimizations inside code. _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version). _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version) and LzmaStateDecode.c _LZMA_PROB32 - It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t. You can use it to enable 64-bit sizes supporting C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. By default, LZMA Encoder contains all Match Finders. But for compressing it's enough to have just one of them. So for reducing size of compressing code you can define: #define COMPRESS_MF_BT #define COMPRESS_MF_BT4 and it will use only bt4 match finder. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/lzma443/sqlzma1-443.patch ================================================ Index: lzma443/C/7zip/Compress/LZMA_Alone/comp.cc =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_Alone/comp.cc diff -N lzma443/C/7zip/Compress/LZMA_Alone/comp.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_Alone/comp.cc 27 Nov 2006 03:54:58 -0000 1.29 @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2006 Junjiro Okajima + * Copyright (C) 2006 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ + +// extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp + +#include +#include +#include +#include + +#include "StdAfx.h" +#include "../../../Common/MyInitGuid.h" +#include "../../../Common/MyWindows.h" +#include "../../../Common/StringConvert.h" +#include "../LZMA/LZMAEncoder.h" + +#include +#include +#include "sqlzma.h" + +////////////////////////////////////////////////////////////////////// + +class CMemoryStream { +protected: + Bytef *m_data; + UInt64 m_limit; + UInt64 m_pos; + +public: + CMemoryStream(Bytef *data, UInt64 size) + : m_data(data), m_limit(size), m_pos(0) {} + + virtual ~CMemoryStream() {} +}; + +class CInMemoryStream : public CMemoryStream, public IInStream, + public CMyUnknownImp { +//protected: + CMyComPtr m_stream; + +public: + MY_UNKNOWN_IMP1(IInStream); + + CInMemoryStream(Bytef *data, UInt64 size) + : CMemoryStream(data, size), m_stream(this) {} + + virtual ~CInMemoryStream() {} + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) + { + UInt64 room = m_limit - m_pos; + if (size > room) + size = room; + if (size) { + memcpy(data, m_data + m_pos, size); + m_pos += size; + } + if (processedSize) + *processedSize = size; + return S_OK; + } + + // disabled all + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { + assert(0); + return E_NOTIMPL; + } +}; + +class COutMemoryStream : public CMemoryStream, public IOutStream, + public CMyUnknownImp { +//protected: + CMyComPtr m_stream; + +public: + MY_UNKNOWN_IMP1(IOutStream); + + COutMemoryStream(Bytef *data, UInt64 size) + : CMemoryStream(data, size), m_stream(this) {} + + virtual ~COutMemoryStream() {} + + UInt32 GetSize() {return m_pos;} + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { + if (m_pos + size > m_limit) + return -ENOSPC; + memcpy(m_data + m_pos, data, size); + m_pos += size; + if (processedSize) + *processedSize = size; + return S_OK; + } + + // disabled all + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { + assert(0); + return E_NOTIMPL; + } + STDMETHOD(SetSize)(Int64 newSize) { + assert(0); + return E_NOTIMPL; + } +}; + +////////////////////////////////////////////////////////////////////// + +static int +LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, + uLong *total_out) +{ + int err; + HRESULT res; + const Byte a[] = { + avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, + 0, 0, 0, 0 + }; + + NCompress::NLZMA::CEncoder encoderSpec; + CMyComPtr encoder = &encoderSpec; + encoder->AddRef(); + CInMemoryStream inStreamSpec(next_in, avail_in); + CMyComPtr inStream = &inStreamSpec; + inStream->AddRef(); + COutMemoryStream outStreamSpec(next_out, avail_out); + CMyComPtr outStream = &outStreamSpec; + outStream->AddRef(); + + // these values are dpending upon is_lzma() macro in sqlzma.h + const UInt32 dictionary = 1 << 23; + const UString mf = L"BT4"; + const UInt32 posStateBits = 2; + const UInt32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + const UInt32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + const UInt32 algorithm = 2; + const UInt32 numFastBytes = 128; + const UInt32 matchFinderCycles = 16 + numFastBytes / 2; + //const bool matchFinderCyclesDefined = false; + const PROPID propIDs[] = { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker, + NCoderPropID::kMatchFinderCycles + }; + const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT properties[kNumPropsMax]; + for (int p = 0; p < 6; p++) + properties[p].vt = VT_UI4; + properties[0].ulVal = UInt32(dictionary); + properties[1].ulVal = UInt32(posStateBits); + properties[2].ulVal = UInt32(litContextBits); + properties[3].ulVal = UInt32(litPosBits); + properties[4].ulVal = UInt32(algorithm); + properties[5].ulVal = UInt32(numFastBytes); + + properties[6].vt = VT_BSTR; + properties[6].bstrVal = (BSTR)(const wchar_t *)mf; + properties[7].vt = VT_BOOL; + properties[7].boolVal = VARIANT_FALSE; // EOS + properties[8].vt = VT_UI4; + properties[8].ulVal = UInt32(matchFinderCycles); + + err = -EINVAL; + res = encoderSpec.SetCoderProperties(propIDs, properties, + kNumPropsMax - 1); + if (res) + goto out; + res = encoderSpec.WriteCoderProperties(outStream); + if (res) + goto out; + + UInt32 r; + res = outStream->Write(a, sizeof(a), &r); + if (res || r != sizeof(a)) + goto out; + + err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); + if (err) + goto out; + *total_out = outStreamSpec.GetSize(); + + out: + return err; +} + +////////////////////////////////////////////////////////////////////// + +#define Failure(p) do { \ + fprintf(stderr, "%s:%d: please report to jro " \ + "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ + __func__, __LINE__, \ + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ + abort(); \ +}while(0) + +extern "C" int +sqlzma_cm(int try_lzma, z_stream *stream, Bytef *next_in, uInt avail_in, + Bytef *next_out, uInt avail_out) +{ + int err; + Bytef *p = next_out; + uInt l = avail_out; + + stream->next_in = next_in; + stream->avail_in = avail_in; + stream->next_out = p; + stream->avail_out = l; + err = deflate(stream, Z_FINISH); + if (err != Z_STREAM_END && err != Z_OK) + goto out_err; + if (avail_in < stream->total_out) + return err; + if (is_lzma(*p)) + Failure(p); + + if (try_lzma) { + unsigned char a[stream->total_out]; + uLong processed; + + memcpy(a, p, stream->total_out); + + // malloc family in glibc and stdc++ seems to be thread-safe + err = LzmaCompress(next_in, avail_in, p, l, &processed); + if (!err && processed <= stream->total_out) { + if (!is_lzma(*next_out)) + Failure(next_out); + stream->total_out = processed; + err = Z_STREAM_END; + } else { + //puts("by zlib"); + memcpy(p, a, stream->total_out); + err = Z_STREAM_END; + } + } + return err; + + out_err: + fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); + return err; +} Index: lzma443/C/7zip/Compress/LZMA_Alone/sqlzma.mk =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_Alone/sqlzma.mk diff -N lzma443/C/7zip/Compress/LZMA_Alone/sqlzma.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_Alone/sqlzma.mk 27 Nov 2006 03:54:58 -0000 1.23 @@ -0,0 +1,54 @@ + +# Copyright (C) 2006 Junjiro Okajima +# Copyright (C) 2006 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + +include makefile.gcc + +ifdef UseDebugFlags +DebugFlags = -Wall -O0 -g -UNDEBUG +endif +# -pthread +CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} +Tgt = liblzma_r.a + +all: ${Tgt} + +RObjs = LZMAEncoder_r.o Alloc_r.o LZInWindow_r.o CRC_r.o StreamUtils_r.o \ + OutBuffer_r.o RangeCoderBit_r.o +%_r.cc: ../LZMA/%.cpp + ln $< $@ +%_r.cc: ../LZ/%.cpp + ln $< $@ +%_r.cc: ../RangeCoder/%.cpp + ln $< $@ +%_r.cc: ../../Common/%.cpp + ln $< $@ +%_r.cc: ../../../Common/%.cpp + ln $< $@ +LZMAEncoder_r.o: CXXFLAGS += -I../LZMA +LZInWindow_r.o: CXXFLAGS += -I../LZ +RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder +OutBuffer_r.o StreamUtils_r.o: CXXFLAGS += -I../../Common +Alloc_r.o CRC_r.o: CXXFLAGS += -I../../../Common + +comp.o: CXXFLAGS += -I${Sqlzma} +comp.o: comp.cc ${Sqlzma}/sqlzma.h + +liblzma_r.a: ${RObjs} comp.o + ${AR} cr $@ $^ + +clean: clean_sqlzma +clean_sqlzma: + $(RM) comp.o *_r.o ${Tgt} *~ + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: lzma443/C/7zip/Compress/LZMA_C/kmod.mk =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/kmod.mk diff -N lzma443/C/7zip/Compress/LZMA_C/kmod.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/kmod.mk 7 Jan 2007 15:12:48 -0000 1.9 @@ -0,0 +1,40 @@ + +# Copyright (C) 2006 Junjiro Okajima +# Copyright (C) 2006 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif +ifndef KDir +$(error KDir is not defined) +endif + +#include makefile.gcc + +Kmod = kmod +EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} +# -D_LZMA_PROB32 +EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) + +all: ${Kmod}/uncomp.c + ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ + -C ${KDir} C=0 V=0 modules + +${Kmod}/uncomp.c: uncomp.c + ln $< $@ + +clean: clean_kmod +clean_kmod: + ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean + ${RM} ${Kmod}/*~ + -@test -e ${Kmod}/uncomp.c && \ + diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ + find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: lzma443/C/7zip/Compress/LZMA_C/sqlzma.mk =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/sqlzma.mk diff -N lzma443/C/7zip/Compress/LZMA_C/sqlzma.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/sqlzma.mk 7 Jan 2007 15:12:48 -0000 1.20 @@ -0,0 +1,45 @@ + +# Copyright (C) 2006 Junjiro Okajima +# Copyright (C) 2006 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + +include makefile.gcc +ifdef KDir +include kmod.mk +endif + +ifdef UseDebugFlags +DebugFlags = -O0 -g -UNDEBUG +endif +CFLAGS += -DNDEBUG ${DebugFlags} +Tgt = libunlzma.a libunlzma_r.a + +all: ${Tgt} + +%_r.c: %.c + ln $< $@ +# -pthread +%_r.o: CFLAGS += -D_REENTRANT -include pthread.h + +uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} +uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h + +libunlzma.a: uncomp.o LzmaDecode.o + ${AR} cr $@ $^ +libunlzma_r.a: uncomp_r.o LzmaDecode_r.o + ${AR} cr $@ $^ + +clean: clean_sqlzma +clean_sqlzma: + $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o *~ + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: lzma443/C/7zip/Compress/LZMA_C/testflags.c =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/testflags.c diff -N lzma443/C/7zip/Compress/LZMA_C/testflags.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/testflags.c 6 Nov 2006 06:33:10 -0000 1.1 @@ -0,0 +1,5 @@ +#ifdef _LZMA_PROB32 +-D_LZMA_PROB32 +#else +-U_LZMA_PROB32 +#endif Index: lzma443/C/7zip/Compress/LZMA_C/uncomp.c =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/uncomp.c diff -N lzma443/C/7zip/Compress/LZMA_C/uncomp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/uncomp.c 4 Mar 2007 12:45:53 -0000 1.30 @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2006, 2007 Junjiro Okajima + * Copyright (C) 2006, 2007 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ + +/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ + +#ifndef __KERNEL__ +#include +#include +#include +#include +#include +#include +#define unlikely(x) __builtin_expect(!!(x), 0) +#define BUG_ON(x) assert(!(x)) +/* sqlzma buffers are always larger than a page. true? */ +#define kmalloc(sz,gfp) malloc(sz) +#define kfree(p) free(p) +#define zlib_inflate(s, f) inflate(s, f) +#define zlib_inflateInit(s) inflateInit(s) +#define zlib_inflateReset(s) inflateReset(s) +#define zlib_inflateEnd(s) inflateEnd(s) +#else +#include +#include +#include +#include +#ifndef WARN_ON_ONCE +#define WARN_ON_ONCE(b) WARN_ON(b) +#endif +#endif /* __KERNEL__ */ + +#include "sqlzma.h" +#include "LzmaDecode.h" + +static int LzmaUncompress(struct sqlzma_un *un) +{ + int err, i, ret; + SizeT outSize, inProcessed, outProcessed, srclen; + /* it's about 24-80 bytes structure, if int is 32-bit */ + CLzmaDecoderState state; + unsigned char *dst, *src, a[8]; + struct sized_buf *sbuf; + + /* Decode LZMA properties and allocate memory */ + err = -EINVAL; + src = un->un_cmbuf; + ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); + src += LZMA_PROPERTIES_SIZE; + if (unlikely(ret != LZMA_RESULT_OK)) + goto out; + i = LzmaGetNumProbs(&state.Properties); + if (unlikely(i <= 0)) + i = 1; + i *= sizeof(CProb); + sbuf = un->un_a + SQUN_PROB; + if (unlikely(sbuf->sz < i)) { + if (sbuf->buf && sbuf->buf != un->un_prob) + kfree(sbuf->buf); +#ifdef __KERNEL__ + printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); +#else + printf("%d --> %d\n", sbuf->sz, i); +#endif + err = -ENOMEM; + sbuf->sz = 0; + sbuf->buf = kmalloc(i, GFP_ATOMIC); + if (unlikely(!sbuf->buf)) + goto out; + sbuf->sz = i; + } + state.Probs = (void*)sbuf->buf; + + /* Read uncompressed size */ + memcpy(a, src, sizeof(a)); + src += sizeof(a); + outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); + + err = -EINVAL; + dst = un->un_resbuf; + if (unlikely(!dst || outSize > un->un_reslen)) + goto out; + un->un_reslen = outSize; + srclen = un->un_cmlen - (src - un->un_cmbuf); + + /* Decompress */ + err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, + &outProcessed); + if (err) + err = -EINVAL; + + out: +#ifndef __KERNEL__ + if (err) + fprintf(stderr, "err %d\n", err); +#endif + return err; +} + +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, + struct sized_buf *dst) +{ + int err, by_lzma = 0; + if (un->un_lzma && is_lzma(*src->buf)) { + by_lzma = 1; + un->un_cmbuf = src->buf; + un->un_cmlen = src->sz; + un->un_resbuf = dst->buf; + un->un_reslen = dst->sz; + + /* this library is thread-safe */ + err = LzmaUncompress(un); + goto out; + } + + err = zlib_inflateReset(&un->un_stream); + if (unlikely(err != Z_OK)) + goto out; + un->un_stream.next_in = src->buf; + un->un_stream.avail_in = src->sz; + un->un_stream.next_out = dst->buf; + un->un_stream.avail_out = dst->sz; + err = zlib_inflate(&un->un_stream, Z_FINISH); + if (err == Z_STREAM_END) + err = 0; + + out: + if (err) { +#ifdef __KERNEL__ + WARN_ON_ONCE(1); +#else + char a[64] = "ZLIB "; + if (by_lzma) { + strcpy(a, "LZMA "); +#ifdef _REENTRANT + strerror_r(err, a + 5, sizeof(a) - 5); +#else + strncat(a, strerror(err), sizeof(a) - 5); +#endif + } else + strncat(a, zError(err), sizeof(a) - 5); + fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); +#endif + } + return err; +} + +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) +{ + int err; + + err = -ENOMEM; + un->un_lzma = do_lzma; + memset(un->un_a, 0, sizeof(un->un_a)); + un->un_a[SQUN_PROB].buf = un->un_prob; + un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); + if (res_sz) { + un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); + if (unlikely(!un->un_a[SQUN_RESULT].buf)) + return err; + un->un_a[SQUN_RESULT].sz = res_sz; + } + + un->un_stream.next_in = NULL; + un->un_stream.avail_in = 0; +#ifdef __KERNEL__ + un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); + if (unlikely(!un->un_stream.workspace)) + return err; +#else + un->un_stream.opaque = NULL; + un->un_stream.zalloc = Z_NULL; + un->un_stream.zfree = Z_NULL; +#endif + err = zlib_inflateInit(&un->un_stream); + if (unlikely(err == Z_MEM_ERROR)) + return -ENOMEM; + BUG_ON(err); + return err; +} + +void sqlzma_fin(struct sqlzma_un *un) +{ + int i; + for (i = 0; i < SQUN_LAST; i++) + if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) + kfree(un->un_a[i].buf); + BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(sqlzma_un); +EXPORT_SYMBOL(sqlzma_init); +EXPORT_SYMBOL(sqlzma_fin); + +#if 0 +static int __init sqlzma_init(void) +{ + return 0; +} + +static void __exit sqlzma_exit(void) +{ +} + +module_init(sqlzma_init); +module_exit(sqlzma_exit); +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junjiro Okajima "); +MODULE_VERSION("$Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $"); +MODULE_DESCRIPTION("LZMA uncompress for squashfs. " + "Some functions for squashfs to support LZMA and " + "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); +#endif Index: lzma443/C/7zip/Compress/LZMA_C/kmod/Makefile =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/kmod/Makefile diff -N lzma443/C/7zip/Compress/LZMA_C/kmod/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/kmod/Makefile 27 Nov 2006 03:54:58 -0000 1.3 @@ -0,0 +1,11 @@ + +# Copyright (C) 2006 Junjiro Okajima +# Copyright (C) 2006 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ + +obj-m += unlzma.o sqlzma.o +unlzma-y := module.o +sqlzma-y := uncomp.o Index: lzma443/C/7zip/Compress/LZMA_C/kmod/module.c =================================================================== RCS file: lzma443/C/7zip/Compress/LZMA_C/kmod/module.c diff -N lzma443/C/7zip/Compress/LZMA_C/kmod/module.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma443/C/7zip/Compress/LZMA_C/kmod/module.c 27 Nov 2006 03:54:58 -0000 1.5 @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2006 Junjiro Okajima + * Copyright (C) 2006 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ + +#include +#include + +#include "../LzmaDecode.c" + +EXPORT_SYMBOL(LzmaDecodeProperties); +EXPORT_SYMBOL(LzmaDecode); + +#if 0 +static int __init unlzma_init(void) +{ + return 0; +} + +static void __exit unlzma_exit(void) +{ +} + +module_init(unlzma_init); +module_exit(unlzma_exit); +#endif + +MODULE_LICENSE("GPL"); +MODULE_VERSION("$Id: sqlzma1-443.patch,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $"); +MODULE_DESCRIPTION("LZMA uncompress. " + "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/sqlzma.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma. */ /* $Id: sqlzma.h,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include #include #include #ifdef _REENTRANT #include #endif #else #include #endif #define _7ZIP_BYTE_DEFINED /* * detect the compression method automatically by the first byte of compressed * data. * according to rfc1950, the first byte of zlib compression must be 0x?8. */ #define is_lzma(c) (c == 0x5d) /* ---------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif #ifndef __KERNEL__ /* for mksquashfs only */ int sqlzma_cm(int lzma, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out); #endif /* ---------------------------------------------------------------------- */ /* * Three patterns for sqlzma uncompression. very dirty code. * - kernel space (squashfs kernel module) * - user space with pthread (mksquashfs) * - user space without pthread (unsquashfs) */ struct sized_buf { unsigned int sz; unsigned char *buf; }; enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST}; struct sqlzma_un { int un_lzma; struct sized_buf un_a[SQUN_LAST]; unsigned char un_prob[31960]; /* unlzma 64KB */ z_stream un_stream; #define un_cmbuf un_stream.next_in #define un_cmlen un_stream.avail_in #define un_resbuf un_stream.next_out #define un_resroom un_stream.avail_out #define un_reslen un_stream.total_out }; int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz); int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst); void sqlzma_fin(struct sqlzma_un *un); /* ---------------------------------------------------------------------- */ #ifdef __cplusplus }; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.1.1.1 2007-11-22 06:05:47 steven Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/ACKNOWLEDGEMENTS ================================================ ACKNOWLEDGEMENTS Thanks to everyone who have download squashfs. I appreciate people using it, and any feedback you have. The following have provided useful feedback, which has guided some of the extra features in squashfs. This is a randomly ordered (roughly in chronological order) list, which is updated when I remember... Acknowledgements for Squashfs-3.2-r2 ------------------------------------ Junjiro Okajima discovered a couple of SMP issues, thanks. Junjiro Okajima and Tomas Matejicek have produced some good LZMA patches for Squashfs. Acknowledgements for Squashfs-3.2 --------------------------------- Peter Korsgaard sent a patch updating Squashfs to changes in the VFS interface in Linux 2.6.20. Acknowledgements for Squashfs-3.1 --------------------------------- Kenneth Duda and Ed Swierk of Arastra Inc. identified numerous bugs with Squashfs, and provided patches which were the basis for some of the fixes. In particular they identified the fragment rounding bug, the NFS bug, the initrd bug, and helped identify the 4K stack overflow bug. Scott James Remnant (Ubuntu) also identified the fragment rounding bug, and he also provided a patch. Ming Zhang identified the Lseek bug in Mksquashfs. His tests on the performance of Mksquashfs on SMP systems encouraged the rewrite of Mksquashfs. Peter Korsgaard, Daniel Olivera and Zilvinas Valinskas noticed Squashfs 3.0 didn't compile on Linux-2.6.18-rc[1-4] due to changes in the Linux VFS interfaces, and provided patches. Tomas Matejicek (SLAX) suggested the -force option on Unsquashfs, and noticed Unsquashfs didn't return the correct exit status. Yann Le Doare reported a kernel oops and provided a Qemu image that led to the identification of the simultaneously accessing multiply mounted Squashfs filesystems bug. Older acknowledgements ---------------------- Mark Robson - pointed out early on that initrds didn't work Adam Warner - pointed out that greater than 2GB filesystems didn't work. John Sutton - raised the problem when archiving the entire filesystem (/) there was no way to prevent /proc being archived. This prompted exclude files. Martin Mueller (LinuxTV) - noticed that the filesystem length in the superblock doesn't match the output filesystem length. This is due to padding to a 4K boundary. This prompted the addition of the -nopad option. He also reported a problem where 32K block filesystems hung when used as initrds. Arkadiusz Patyk (Polish Linux Distribution - PLD) reported a problem where 32K block filesystems hung when used as a root filesystem mounted as a loopback device. Joe Blow emailed me that I'd forgotten to put anything in the README about mounting the squashfs filesystem. David Fox (Lindows) noticed that the exit codes returned by Mksquashfs were wrong. He also noticed that a lot of time was spent in the duplicate scan routine. Cameron Rich complained that Squashfs did not support FIFOs or sockets. Steve Chadsey and Thomas Weissmuller noticed that files larger than the available memory could not be compressed by Mksquashfs. "Ptwahyu" and "Hoan" (I have no full names and I don't like giving people's email addresses), noticed that Mksquashfs 1.3 SEGV'd occasionally. Even though I had already noticed this bug, it is useful to be informed by other people. Don Elwell, Murray Jensen and Cameron Rich, have all sent in patches. Thanks, I have not had time to do anything about them yet... Drew Scott Daniels has been a good advocate for Squashfs. Erik Andersen has made some nice suggestions, unfortunately, I have not had time to implement anything. Artemiy I. Pavlov has written a useful LDP mini-howto for Squashfs (http://linuxdoc.artemio.net/squashfs). Yves Combe reported the Apple G5 bug, when using Squashfs for his PPC Knoppix-mib livecd project. Jaco Greeff (mklivecd project, and maintainer of the Mandrake squashfs-tools package) suggested the new mksquashfs -ef option, and the standalone build for mksquashfs. Mike Schaudies made a donation. Arkadiusz Patyk from the Polish Linux Distribution reported that Squashfs didn't work on amd64 machines. He gave me an account on a PLD amd64 machine which allowed myself to track down these bugs. Miles Roper, Peter Kjellerstedt and Willy Tarreau reported that release 2.1 did not compile with gcc < 3.x. Marcel J.E. Mol reported lack of kernel memory issues when using Squashfs on small memory embedded systems. This prompted the addition of the embedded system kernel configuration options. Era Scarecrow noticed that Mksquashfs had not been updated to reflect that smaller than 4K blocks are no longer supported. Kenichi Shima reported the Kconfig file had not been updated to 2.2. Aaron Ten Clay made a donation! Tomas Matejicek (SLAX) made a donation! ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/CHANGES ================================================ SQUASHFS CHANGE LOG 3.2-r2 15 JAN 2007 Kernel patch update and progress bar bug fix 1. Kernel patches 2.6.19/2.6.20 have been updated to use const structures and mutexes rather than older semaphores. 2. Minor SMP bug fixes. 3. Progress bar broken on x86-64. Fixed. 3.2 2 JAN 2007 NFS support, improvements to the Squashfs-tools, major bug fixes, lots of small improvements/bug fixes, and new kernel patches. Improvements: 1. Squashfs filesystems can now be exported via NFS. 2. Unsquashfs now supports 2.x filesystems. 3. Mksquashfs now displays a progress bar. 4. Squashfs kernel code has been hardened against accidently or maliciously corrupted Squashfs filesystems. Bug fixes: 5. Race condition occurring on S390 in readpage() fixed. 6. Odd behaviour of MIPS memcpy in read_data() routine worked-around. 7. Missing cache_flush in Squashfs symlink_readpage() added. 3.1-r2 30 AUG 2006 Mksquashfs -sort bug fix A code optimisation after testing unfortunately broke sorting in Mksquashfs. This has been fixed. 3.1 19 AUG 2006 This release has some major improvements to the squashfs-tools, a couple of major bug fixes, lots of small improvements/bug fixes, and new kernel patches. 1. Mksquashfs has been rewritten to be multi-threaded. It has the following improvements 1.1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 1.2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 1.3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 1.4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 1.5 The use of swap memory was found to significantly impact performance. The amount of memory used to cache files is now a command line option, by default this is 512 Mbytes. 2. Unsquashfs has the following improvements 2.1 Unsquashfs now allows you to specify the filename or the directory within the Squashfs filesystem that is to be extracted, rather than always extracting the entire filesystem. 2.2 A new -force option has been added which forces Unsquashfs to output to the destination directory even if files and directories already exist in the destination directory. This allows you to update an already existing directory tree, or to Unsquashfs to a partially filled directory tree. Without the -force option Unsquashfs will refuse to output. 3. The following major bug fixes have been made 3.1 A fragment table rounding bug has been fixed in Mksquashfs. Previously if the number of fragments in the filesystem were a multiple of 512, Mksquashfs would generate an incorrect filesystem. 3.2 A rare SMP bug which occurred when simultaneously acccessing multiply mounted Squashfs filesystems has been fixed. 4. Miscellaneous improvements/bug fixes 4.1 Kernel code stack usage has been reduced. This is to ensure Squashfs works with 4K stacks. 4.2 Readdir (Squashfs kernel code) has been fixed to always return 0, rather than the number of directories read. Squashfs should now interact better with NFS. 4.3 Lseek bug in Mksquashfs when appending to larger than 4GB filesystems fixed. 4.4 Squashfs 2.x initrds can now been mounted. 4.5 Unsquashfs exit status fixed. 4.6 New patches for linux-2.6.18 and linux-2.4.33. 3.0 15 MAR 2006 Major filesystem improvements 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). 2.2-r2 8 SEPT 2005 Second release of 2.2, this release fixes a couple of small bugs, a couple of small documentation mistakes, and adds a patch for kernel 2.6.13. 1. Mksquashfs now deletes the output filesystem image file if an error occurs whilst generating the filesystem. Previously on error the image file was left empty or partially written. 2. Updated mksquashfs so that it doesn't allow you to generate filesystems with block sizes smaller than 4K. Squashfs hasn't supported block sizes less than 4K since 2.0-alpha. 3. Mksquashfs now ignores missing files/directories in sort files. This was the original behaviour before 2.2. 4. Fixed small mistake in fs/Kconfig where the version was still listed as 2.0. 5. Updated ACKNOWLEDGEMENTS file. 2.2 3 JUL 2005 This release has some small improvements, bug fixes and patches for new kernels. 1. Sort routine re-worked and debugged from release 2.1. It now allows you to give Mkisofs style sort files and checks for filenames that don't match anything. Sort priority has also been changed to conform to Mkisofs usage, highest priority files are now placed at the start of the filesystem (this means they will be on the inside of a CD or DVD). 2. New Configure options for embedded systems (memory constrained systems). See INSTALL file for further details. 3. Directory index bug fixed where chars were treated as signed on some architectures. A file would not be found in the rare case that the filename started with a chracter greater than 127. 4. Bug introduced into the read_data() routine when sped up to use data block queueing fixed. If the second or later block resulted in an I/O error this was not checked. 5. Append bug introduced in 2.1 fixed. The code to compute the new compressed and uncompressed directory parts after appending was wrong. 6. Metadata block length read routine altered to not perform a misaligned short read. This was to fix reading on an ARM7 running uCLinux without a misaligned read interrupt handler. 7. Checkdata bug introduced in 2.1 fixed. 2.1-r2 15 DEC 2004 Code changed so it can be compiled with gcc 2.x 1. In some of the code added for release 2.1 I unknowingly used some gcc extensions only supported by 3.x compilers. I have received a couple of reports that the 2.1 release doesn't build on 2.x and so people are clearly still using gcc 2.x. The code has been rewritten to remove these extensions. 2.1 10 DEC 2004 Significantly improved directory handling plus numerous other smaller improvements 1. Fast indexed directories implemented. These speed up directory operations (ls, file lookup etc.) significantly for directories larger than 8 KB. 2. All directories are now sorted in alphabetical order. This again speeds up directory operations, and in some cases it also results in a small compression improvement (greater data similarity between files with alphabetically similar names). 3. Maximum directory size increased from 512 KB to 128 MB. 4. Duplicate fragment checking and appending optimised in mksquashfs, depending on filesystem, this is now up to 25% faster. 5. Mksquashfs help information reformatted and reorganised. 6. The Squashfs version and release date is now printed at kernel boot-time or module insertion. This addition will hopefully help to reduce the growing problem where the Squashfs version supported by a kernel is unknown and the kernel source is unavailable. 7. New PERFORMANCE.README file. 8. New -2.0 mksquashfs option. 9. CHANGES file reorganised. 10. README file reorganised, clarified and updated to include the 2.0 mksquashfs options. 11. New patch for Linux 2.6.9. 12. New patch for Linux 2.4.28. 2.0r2 29 AUG 2004 Workaround for kernel bug in kernels 2.6.8 and newer added 1. New patch for kernel 2.6.8.1. This includes a workaround for a kernel bug introduced in 2.6.7bk14, which is present in all later versions of the kernel. If you're using a 2.6.8 kernel or later then you must use this 2.6.8.1 patch. If you've experienced hangs or oopses using Squashfs with a 2.6.8 or later kernel then you've hit this bug, and this patch will fix it. It is worth mentioning that this kernel bug potentially affects other filesystems. If you receive odd results with other filesystems you may be experiencing this bug with that filesystem. I submitted a patch but this has not yet gone into the kernel, hopefully the bug will be fixed in later kernels. 2.0 13 JULY 2004 A couple of new options, and some bug fixes 1. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 2. Initrds are now supported for kernels 2.6.x. 3. amd64 bug fixes. If you use an amd64, please read the README-AMD64 file. 4. Check-data and gid bug fixes. With 2.0-alpha when mounting 1.x filesystems in certain cases file gids were corrupted. 5. New patch for Linux 2.6.7. 2.0-ALPHA 21 MAY 2004 Filesystem changes and compression improvements 1. Squashfs 2.0 has added the concept of fragment blocks. Files smaller than the file block size and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K (in the ALPHA version of Squashfs 2.0). 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 6. Numerous small bug fixes have been made. 1.3r3 18 JAN 2004 Third release of 1.3, this adds a new mksquashfs option, some bug fixes, and extra patches for new kernels 1. New mksquashfs -ef exclude option. This option reads the exclude dirs/files from an exclude file, one exclude dir/file per line. This avoids the command line size limit when using the -e exclude option, 2. When appending to existing filesystems, if mksquashfs experiences a fatal error (e.g. out of space when adding to the destination), the original filesystem is restored, 3. Mksquashfs now builds standalone, without the kernel needing to be patched. 4. Bug fix in the kernel squashfs filesystem, where the pages being filled were not kmapped. This seems to only have caused problems on an Apple G5, 5. New patch for Linux 2.4.24, 6. New patch for Linux 2.6.1, this replaces the patch for 2.6.0-test7. 1.3r2 14 OCT 2003 Second release of 1.3, bug fixes and extra patches for new kernels 1. Bug fix in routine that adds files to the filesystem being generated in mksquashfs. This bug was introduced in 1.3 (not enough testing...) when I rewrote it to handle files larger than available memory. This bug caused a SEGV, so if you've ever got that, it is now fixed, 2. Long running bug where ls -s and du reported wrong block size fixed. I'm pretty sure this used to work many kernel versions ago (2.4.7) but it broke somewhere along the line since then, 3. New patch for Linux 2.4.22, 4. New patch for 2.6.0-test7, this replaces the patch for 2.6.0-test1. 1.3 29 JUL 2003 FIFO/Socket support added plus optimisations and improvements 1. FIFOs and Socket inodes are now supported, 2. Mksquashfs can now compress files larger than available memory, 3. File duplicate check routine optimised, 4. Exit codes fixed in Mksquashfs, 5. Patch for Linux 2.4.21, 6. Patch for Linux 2.6.0-test1. Hopefully, this will work for the next few releases of 2.6.0-testx, otherwise, I'll be releasing a lot of updates to the 2.6.0 patch... 1.2 13 MAR 2003 Append feature and new mksquashfs options added Mksquashfs can now add to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. See the README file for usage changes. 1.1b 16 JAN 2003 Bug fix release Fixed readpage deadlock bug. This was a rare deadlock bug that happened when pushing pages into the page cache when using greater than 4K blocks. I never got this bug when I tested the filesystem, but two people emailed me on the same day about the problem! I fixed it by using a page cache function that wasn't there when I originally did the work, which was nice :-) 1.1 8 JAN 2003 Added features 1. Kernel squashfs can now mount different byte order filesystems. 2. Additional features added to mksquashfs. Mksquashfs now supports exclude files and multiple source files/directories can be specified. A nopad option has also been added, which informs mksquashfs not to pad filesystems to a multiple of 4K. See README for mksquashfs usage changes. 3. Greater than 2GB filesystems bug fix. Filesystems greater than 2GB can now be created. 1.0c 14 NOV 2002 Bug fix release Fixed bugs with initrds and device nodes 1.0 23 OCT 2002 Initial release ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/INSTALL ================================================ INSTALLING SQUASHFS The squashfs3.2-r2.tar.gz file contains this file, a README-3.2 file, another README file, an ACKNOWLEDGEMENTS file, a CHANGES file, the kernel-patches directory containing the squashfs patches, and the squashfs-tools directory (mksquashfs and unsquashfs). 1. Patching the kernel ---------------------- There are eleven kernel patch directories depending on your linux kernel version. If your kernel version isn't listed then try the patch for the nearest kernel listed. To patch your kernel, cd into the top level directory, and run the "patch" command, e.g. assuming linux-2.6.20 %cd /usr/src/linux-2.6.20 %patch -p1 < location-of-squashfs/kernel-patches/linux-2.6.20/squashfs3.2-patch Where "location-of-squashfs" is the path to the squashfs3.2 source directory. The squashfs patches patch the relevant kernel files to add configure support, initrd support, include files, and the squashfs directory under linux/fs/. Once patched, the kernel must be reconfigured, with squashfs support turned on (either Y/M) to ensure that inflate support is built into the kernel. The squashfs kernel option can be found in the miscellaneous filesystems submenu near the bottom of the filesystems submenu. There are a set of options which are intended for use by embedded systems with low memory. At the "Additional options for memory-constrained systems" prompt, please say NO unless you're using an embedded system! Saying Y here allows you to specify cache sizes and how Squashfs allocates memory. The "Number of fragments cached" prompt allows the number of fragments cached to be controlled. By default SquashFS caches the last 3 fragments read from the filesystem. Increasing this amount may mean SquashFS has to re-read fragments less often from disk, at the expense of extra system memory. Decreasing this amount will mean SquashFS uses less memory at the expense of extra reads from disk. Note there must be at least one cached fragment. Anything much more than three will probably not make much difference. The "Use Vmalloc rather than Kmalloc" prompt allows you to tell SquashFS to use Vmalloc. By default SquashFS uses kmalloc to obtain fragment cache memory. Kmalloc memory is the standard kernel allocator, but it can fail on memory constrained systems. Because of the way Vmalloc works, Vmalloc can succeed when kmalloc fails. Specifying this option will make SquashFS always use Vmalloc to allocate the fragment cache memory. 2. Building squashfs tools -------------------------- The squashfs-tools directory contains the mksquashfs and unsquashfs programs. These can be made by typing make. The source files use a local copy of squashfs_fs.h (included in the kernel patches) allowing the tools to be made without needing to patch the kernel. ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/PERFORMANCE.README ================================================ GENERAL INFORMATION ON PERFORMANCE TESTS ---------------------------------------- The following performance tests were based on two file sets: the liveCD filesystem from the Ubuntu liveCD (Warty release), and the liveCD filesystem from the Damn Small Linux liveCD (release 0.8.4). The Ubuntu liveCD filesystem was used to test filesystem performance from CDROM and hard disk for Zisofs, Cloop, Squashfs 2.0 and Squashfs2.1. CRAMFS filesystem performance could not be tested for this filesystem bacause it exceeds the maximum supported size of CRAMFS. To test CRAMFS performance against Squashfs, the liveCD filesystem from Damn Small Linux was used. NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 1. Ubuntu liveCD performance tests ext3 uncompressed size 1.4 GB Zisofs compressed size 589.81 MB Cloop compressed size 471.89 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB 1.1 Performance tests from CDROM 1.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM Zisofs 49.88 seconds (User 2.60 secs, Sys 11.19 secs) Cloop 20.80 seconds (User 2.71 secs, Sys 13.50 secs) Squashfs2.0 16.56 seconds (User 2.42 secs, Sys 10.37 secs) Squashfs2.1 10.14 seconds (User 2.48 secs, Sys 4.44 secs) 1.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM Zisofs 27 minutes 28.54 seconds (User 3.00 secs, Sys 1 min 4.80 secs) Cloop 5 minutes 55.72 seconds (User 2.90 secs, Sys 3 min 37.90 secs) Squashfs2.0 5 minutes 20.87 seconds (User 2.33 secs, Sys 56.98 secs) Squashfs2.1 5 minutes 15.46 seconds (user 2.28 secs, Sys 51.12 secs) 1.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM Zisofs 101 minutes 29.65 seconds (User 5.33 secs, Sys 1 min 17.20 secs) Cloop 35 minutes 27.51 seconds (user 5.93 secs, Sys 4 mins 30.23 secs) Squashfs2.0 21 minutes 53.05 seconds (user 5.71 secs, Sys 2 mins 36.59 secs) Squashfs2.1 21 minutes 46.99 seconds (User 5.80 secs, Sys 2 mins 31.88 secs) 1.2 Performance tests from Hard disk 1.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 17.29 seconds (User 2.62 secs, Sys 11.08 secs) Cloop 16.46 seconds (User 2.63 secs, Sys 13.41 secs) Squashfs2.0 13.75 seconds (User 2.44 secs, Sys 11.00 secs) Squashfs2.1 6.94 seconds (User 2.44 secs, Sys 4.48 secs) 1.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 1 minute 21.47 seconds (User 2.73 secs, Sys 54.44 secs) Cloop 1 minute 34.06 seconds (user 2.85 secs, Sys 1 min 12.13 secs) Squashfs2.0 1 minute 21.22 seconds (User 2.42 secs, Sys 56.21 secs) Squashfs2.1 1 minute 15.46 seconds (User 2.36 secs, Sys 49.78 secs) 1.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk Zisofs 11 minutes 13.64 seconds (User 5.08 secs, Sys 52.62 secs) Cloop 5 minutes 37.93 seconds (user 6 secs, Sys 2 mins 22.38 secs) Squashfs2.0 5 minutes 7.11 seconds (user 5.63 secs, Sys 2 mins 35.23 secs) Squashfs2.1 5 minutes 1.87 seconds (User 5.71 secs, Sys 2 mins 29.98 secs) 2. Damn Small Linux liveCD performance tests ext3 uncompressed size 126 MB CRAMFS compressed size 52.19 MB Squashfs2.0 compressed size 46.52 MB Squashfs2.1 compressed size 46.52 MB 2.1 Performance tests from CDROM 2.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 10.85 seconds (User 0.39 secs, Sys 0.98 secs) Squashfs2.0 2.97 seconds (User 0.36 secs, Sys 2.15 secs) Squashfs2.1 2.43 seconds (User 0.40 secs, Sys 1.42 secs) 2.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 55.38 seconds (User 0.34 secs, Sys 6.98 secs) Squashfs2.0 35.99 seconds (User 0.30 secs, Sys 6.35 secs) Squashfs2.1 33.83 seconds (User 0.26 secs, Sys 5.56 secs) 2.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM CRAMFS 3 minutes 1.68 seconds (User 0.54 secs, Sys 9.51 secs) Squashfs2.0 1 minute 39.45 seconds (User 0.57 secs, Sys 13.14 secs) Squashfs2.1 1 minute 38.41 seconds (User 0.58 secs, Sys 13.08 secs) 2.2 Performance tests from Hard disk 2.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 1.77 seconds (User 0.53 secs, Sys 1.21 secs) Squashfs2.0 2.67 seconds (User 0.41 secs, Sys 2.25 secs) Squashfs2.1 1.87 seconds (User 0.41 secs, Sys 1.46 secs) 2.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 6.80 seconds (User 0.36 secs, Sys 6.02 secs) Squashfs2.0 7.23 seconds (User 0.29 secs, Sys 6.62 secs) Squashfs2.1 6.53 seconds (User 0.31 secs, Sys 5.82 secs) 2.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk CRAMFS 28.55 seconds (User 0.49 secs, Sys 6.49 secs) Squashfs2.0 25.44 seconds (User 0.58 secs, Sys 13.17 secs) Squashfs2.1 24.72 seconds (User 0.56 secs, Sys 13.15 secs) ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/README ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Please read the README-3.2 and CHANGES files for details of changes. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. 1. SQUASHFS OVERVIEW -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. In theory files up to 2^64 bytes are supported. In theory filesystems can be up to 2^64 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 64K (the default size is 64K). Using 64K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 7. Both big and little endian architectures are supported. Squashfs can mount filesystems created on different byte order machines. 2. USING SQUASHFS ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 3. MKSQUASHFS ------------- 3.1 Mksquashfs options and overview. ------------------------------------ As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. SYNTAX:mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Options are -version print version, licence and copyright message -info print files written to filesystem -b set data block to . Default 65536 bytes -processors Use processors. By default will use number of processors available -read-queue Set input queue to Mbytes. Default 64 Mbytes -write-queue Set output queue to Mbytes. Default 512 Mbytes -noI do not compress inode table -noD do not compress data blocks -noF do not compress fragment blocks -no-fragments do not use fragments -always-use-fragments use fragment blocks for files larger than block size -no-duplicates do not perform duplicate checking -noappend do not append to existing filesystem -keep-as-directory if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory -root-becomes when appending source files/directories, make the original root become a subdirectory in the new root called , rather than adding the new source items to the original root -all-root make all files owned by root -force-uid uid set all file uids to uid -force-gid gid set all file gids to gid -le create a little endian filesystem -be create a big endian filesystem -nopad do not pad filesystem to a multiple of 4K -check_data add checkdata for greater filesystem checks -root-owned alternative name for -all-root -noInodeCompression alternative name for -noI -noDataCompression alternative name for -noD -noFragmentCompression alternative name for -noF -sort sort files according to priorities in . One file or dir with priority per line. Priority -32768 to 32767, default priority 0 -ef list of exclude dirs/files. One per line Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. 3.2 Changing compression defaults used in mksquashfs ---------------------------------------------------- There are a large number of options that can be used to control the compression in mksquashfs. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances! The -noI, -noD and -noF options (also -noInodeCompression, -noDataCompression and -noFragmentCompression) can be used to force mksquashfs to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. The -no-fragments tells mksquashfs to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. The -always-use-fragments option tells mksquashfs to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. The -no-duplicates option tells mksquashfs to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. The -b option allows the block size to be selected, this can be either 4096, 8192, 16384, 32768 or 65536 bytes. 3.3 Specifying the UIDs/GIDs used in the filesystem --------------------------------------------------- By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, mksquashfs provides a number of options which can be used to override the ownership. The options -all-root and -root-owned (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The "-force-uid uid" option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. The "-force-gid gid" option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. 3.4 Excluding files from the filesystem --------------------------------------- The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. 3.5 Appending to squashfs filesystems ------------------------------------- Running squashfs with the destination directory containing an existing filesystem will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3.6 Miscellaneous options ------------------------- The -info option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The -le and -be options can be used to force mksquashfs to generate a little endian or big endian filesystem. Normally mksquashfs will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 4. UNSQUASHFS ------------- Unsquashfs allows you to decompress and extract a Squashfs filesystem without mounting it. It can extract the entire filesystem, or a specific file or directory. The Unsquashfs usage info is: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] unsquash to , default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. The "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. Unsquashfs can decompress 2.x and 3.x filesystems. Support for 1.x filesystems will be added in the future. 5. FILESYSTEM LAYOUT -------------------- Brief filesystem design notes follow for the original 1.x filesystem layout. A description of the 2.x and 3.x filesystem layouts will be written sometime! A squashfs filesystem consists of five parts, packed together on a byte alignment: --------------- | superblock | |---------------| | data | | blocks | |---------------| | inodes | |---------------| | directories | |---------------| | uid/gid | | lookup table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory and uid/gid lookup tables are written. 5.1 Metadata ------------ Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. An inode is identified by a two field tuple . Inode contents vary depending on the file type. The base inode consists of: base inode: Inode type Mode uid index gid index The inode type is 4 bits in size, and the mode is 12 bits. The uid and gid indexes are 4 bits in length. Ordinarily, this will allow 16 unique indexes into the uid table. To minimise overhead, the uid index is used in conjunction with the spare bit in the file type to form a 48 entry index as follows: inode type 1 - 5: uid index = uid inode type 5 -10: uid index = 16 + uid inode type 11 - 15: uid index = 32 + uid In this way 48 unique uids are supported using 4 bits, minimising data inode overhead. The 4 bit gid index is used to index into a 15 entry gid table. Gid index 15 is used to indicate that the gid is the same as the uid. This prevents the 15 entry gid table filling up with the common case where the uid/gid is the same. The data contents of symbolic links are stored immediately after the symbolic link inode, inside the inode table. This allows the normally small symbolic link to be compressed as part of the inode table, achieving much greater compression than if the symbolic link was compressed individually. Similarly, the block index for regular files is stored immediately after the regular file inode. The block index is a list of block lengths (two bytes each), rather than block addresses, saving two bytes per block. The block address for a given block is computed by the summation of the previous block lengths. This takes advantage of the fact that the blocks making up a file are stored contiguously in the filesystem. The top bit of each block length is set if the block is uncompressed, either because the -noD option is set, or if the compressed block was larger than the uncompressed block. 5.2 Directories --------------- Like inodes, directories are packed into the metadata blocks, and are not aligned on block boundaries, therefore directories can overlap compressed blocks. A directory is, again, identified by a two field tuple . Directories are organised in a slightly complex way, and are not simply a list of file names and inode tuples. The organisation takes advantage of the observation that in most cases, the inodes of the files in the directory will be in the same compressed metadata block, and therefore, the inode tuples will have the same start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. The organisation is as follows: directory_header: count (8 bits) inode start block (24 bits) directory entry: * count inode offset (13 bits) inode type (3 bits) filename size (8 bits) filename This organisation saves on average 3 bytes per filename. 5.3 File data ------------- File data is compressed on a block by block basis and written to the filesystem. The filesystem supports up to 32K blocks, which achieves greater compression ratios than the Linux 4K page size. The disadvantage with using greater than 4K blocks (and the reason why most filesystems do not), is that the VFS reads data in 4K pages. The filesystem reads and decompresses a larger block containing that page (e.g. 32K). However, only 4K can be returned to the VFS, resulting in a very inefficient filesystem, as 28K must be thrown away. Squashfs, solves this problem by explicitly pushing the extra pages into the page cache. 6. AUTHOR INFO -------------- Squashfs was written by Phillip Lougher, email phillip@lougher.org.uk, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback! ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/README-3.2 ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Squashfs 3.2 has support for NFS exporting, some improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- New command line options: -no-exports Squashfs now supports NFS exports. By default the additional information necessary is added to the filesystem by Mksquashfs. If you do not wish this extra information, then this option can be specified. This will save a couple of bytes per file, and the filesystem will be identical to Squashfs 3.1. -no-progress Mksquashfs by default now displays a progress bar. This option disables it. 2. UNSQUASHFS ------------- Unsquashfs now supports Squashfs 2.x filesystems. ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/sqlzma2u-3.2-r2.patch ================================================ Index: squashfs3.2-r2/squashfs-tools/Makefile =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/Makefile 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/Makefile 16 Jan 2007 05:08:17 -0000 1.2 @@ -1,19 +1,44 @@ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 +ifdef UseDebugFlags +DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG +endif +CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} +LDLIBS += -lz -L${LzmaAlone} -L${LzmaC} +Tgt = mksquashfs unsquashfs -all: mksquashfs unsquashfs +all: ${Tgt} -mksquashfs: mksquashfs.o read_fs.o sort.o - $(CC) mksquashfs.o read_fs.o sort.o -lz -lpthread -lm -o $@ +read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h -mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h +sort.o: sort.c squashfs_fs.h global.h sort.h -read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h +mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ + ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a -sort.o: sort.c squashfs_fs.h global.h sort.h +mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ +mksquashfs: mksquashfs.o read_fs.o sort.o + +unsquashfs.o: CFLAGS += -U_REENTRANT +unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a +unsquashfs: LDLIBS += -lunlzma unsquashfs: unsquashfs.o - $(CC) unsquashfs.o -lz -o $@ -unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h +clean: + ${RM} *~ *.o ${Tgt} + +-include test.mk + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: squashfs3.2-r2/squashfs-tools/mksquashfs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/mksquashfs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/mksquashfs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/mksquashfs.c 16 Jan 2007 05:08:17 -0000 1.2 @@ -59,6 +59,8 @@ #include "mksquashfs.h" #include "global.h" #include "sort.h" +#include "sqlzma.h" +#include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ @@ -107,6 +109,7 @@ unsigned short uid_count = 0, guid_count squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; +struct sqlzma_un un; /* write position within data section */ long long bytes = 0, total_bytes = 0; @@ -326,6 +329,7 @@ struct dir_info *dir_scan1(char *, int ( struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; +int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) @@ -593,21 +597,7 @@ unsigned int mangle2(z_stream **strm, ch BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } - stream->next_in = (unsigned char *) s; - stream->avail_in = size; - stream->next_out = (unsigned char *) d; - stream->avail_out = block_size; - - res = deflate(stream, Z_FINISH); - if(res != Z_STREAM_END && res != Z_OK) { - if(res == Z_STREAM_ERROR) - BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::compress failed, no progress possible\n"); - else - BAD_ERROR("zlib::compress failed, unknown error %d\n", res); - } - + res = sqlzma_cm(un.un_lzma, stream, s, size, d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { @@ -706,6 +696,7 @@ void write_bytes(int fd, long long byte, EXIT_MKSQUASHFS(); } + //printf("%d bytes at %Ld\n", bytes, off); if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); @@ -1220,17 +1211,17 @@ char *get_fragment(char *buffer, struct int res; unsigned long bytes = block_size; char cbuffer[block_size]; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = cbuffer, .sz = size}, + {.buf = buffer, .sz = bytes} + }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); - - if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { - if(res == Z_MEM_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); - } + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); + bytes = un.un_reslen; } else read_bytes(fd, disk_fragment->start_block, size, buffer); @@ -1623,7 +1614,7 @@ void reader_read_file(struct dir_ent *di file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; - if(file_buffer->fragment = count == frag_block) + if((file_buffer->fragment = (count == frag_block))) //?? queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); @@ -1682,6 +1673,7 @@ void *reader(void *arg) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } + return NULL; } @@ -1711,6 +1703,7 @@ void *writer(void *arg) write_error = TRUE; } + //printf("%d bytes at %Ld\n", file_buffer->size, off); if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; @@ -1830,7 +1823,7 @@ int progress_bar(long long current, long int spaces = columns - used - hashes; if(!progress || columns - used < 0) - return; + return 0; printf("\r["); @@ -1843,6 +1836,7 @@ int progress_bar(long long current, long printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); + return 0; } @@ -2479,7 +2473,7 @@ error: int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { - int squashfs_type; + int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; @@ -2774,7 +2768,8 @@ skip_inode_hash_table: printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n"); \ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; @@ -2792,6 +2787,7 @@ int main(int argc, char *argv[]) be = FALSE; #endif + un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); @@ -2947,6 +2943,8 @@ int main(int argc, char *argv[]) exit(1); } root_name = argv[i]; + } else if(strcmp(argv[i], "-nolzma") == 0) { + un.un_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { @@ -3125,8 +3123,8 @@ printOptions: printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); - compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); - uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); + compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); //?? + uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); //?? /* save original filesystem state for restoring ... */ sfragments = fragments; @@ -3193,6 +3191,11 @@ printOptions: #endif block_offset = check_data ? 3 : 2; + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + ERROR("%s:%d: %d\n", __func__, __LINE__, i); + EXIT_MKSQUASHFS(); + } if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { @@ -3211,7 +3214,9 @@ printOptions: dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; - sBlk.s_magic = SQUASHFS_MAGIC; + sBlk.s_magic = SQUASHFS_MAGIC_LZMA; + if (!un.un_lzma) + sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; Index: squashfs3.2-r2/squashfs-tools/read_fs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/read_fs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/read_fs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/read_fs.c 16 Jan 2007 05:08:17 -0000 1.2 @@ -46,6 +46,8 @@ extern int add_file(long long, long long #include #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include @@ -62,6 +64,7 @@ extern int add_file(long long, long long } while(0) int swap; +extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { @@ -81,19 +84,20 @@ int read_block(int fd, long long start, char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = buffer}, + {.buf = block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); - if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -351,18 +355,30 @@ int read_super(int fd, squashfs_super_bl /* Check it is a SQUASHFS superblock */ swap = 0; - if(sBlk->s_magic != SQUASHFS_MAGIC) { - if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); - memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } - } + switch (sBlk->s_magic) { + squashfs_super_block sblk; + + case SQUASHFS_MAGIC_LZMA: + if (!un.un_lzma) + goto bad; + break; + case SQUASHFS_MAGIC: + break; + case SQUASHFS_MAGIC_LZMA_SWAP: + if (!un.un_lzma) + goto bad; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); + memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + break; + bad: + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; + } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { @@ -416,7 +432,8 @@ unsigned char *squashfs_readdir(int fd, squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; - long long start = sBlk->directory_table_start + directory_start_block, last_start_block; + long long start = sBlk->directory_table_start + directory_start_block, + last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) Index: squashfs3.2-r2/squashfs-tools/unsquashfs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/unsquashfs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/unsquashfs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/unsquashfs.c 16 Jan 2007 05:08:18 -0000 1.2 @@ -46,6 +46,8 @@ #include #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include @@ -97,6 +99,7 @@ unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; +struct sqlzma_un un; #define CALCULATE_HASH(start) (start & 0xffff) @@ -144,6 +147,7 @@ int read_bytes(long long byte, int bytes return FALSE; } + /* printf("%d bytes at %Ld\n", bytes, off); */ if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; @@ -175,21 +179,21 @@ int read_block(long long start, long lon char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = buffer}, + {.buf = block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - goto failed; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -216,20 +220,19 @@ int read_data_block(long long start, uns TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = data, .sz = c_byte}, + {.buf = block, .sz = bytes} + }; + if(read_bytes(start, c_byte, data) == FALSE) return 0; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) data, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } - + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) @@ -660,7 +663,7 @@ int create_inode(char *pathname, unsigne set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else - ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", + ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; @@ -818,7 +821,7 @@ int create_inode_2(char *pathname, unsig set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else - ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", + ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; @@ -1225,18 +1228,26 @@ int read_super(char *source) read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ + un.un_lzma = 1; swap = 0; - if(sBlk.s_magic != SQUASHFS_MAGIC) { - if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); - memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } + switch (sBlk.s_magic) { + squashfs_super_block sblk; + case SQUASHFS_MAGIC: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA: + break; + case SQUASHFS_MAGIC_SWAP: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); + memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; } /* Check the MAJOR & MINOR versions */ @@ -1305,14 +1316,15 @@ failed_mount: printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n"); \ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; - if(root_process = geteuid() == 0) + if((root_process = (geteuid() == 0))) //?? umask(0); for(i = 1; i < argc; i++) { @@ -1371,6 +1383,11 @@ options: EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + fputs("sqlzma_init failed", stderr); + abort(); + } read_uids_guids(); s_ops.read_fragment_table(); ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/Makefile ================================================ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 ifdef UseDebugFlags DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG endif CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} LDLIBS += -L${LzmaAlone} -L${LzmaC} Tgt = mksquashfs unsquashfs all: ${Tgt} read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a mksquashfs: LDLIBS += -lpthread -lm -lunlzma_r -llzma_r -lstdc++ -lz mksquashfs: mksquashfs.o read_fs.o sort.o unsquashfs.o: CFLAGS += -U_REENTRANT unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a unsquashfs: LDLIBS += -lunlzma -lz unsquashfs: unsquashfs.o clean: ${RM} *~ *.o ${Tgt} -include test.mk # Local variables: ; # compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "sqlzma.h" #include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; struct sqlzma_un un; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } res = sqlzma_cm(un.un_lzma, stream, s, size, d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } //printf("%d bytes at %Ld\n", bytes, off); if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = cbuffer, .sz = size}, {.buf = buffer, .sz = bytes} }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); bytes = un.un_reslen; } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { char buffer2[SQUASHFS_FILE_MAX_SIZE]; long long dup_start = dupl_ptr->start; char *buffer; int block; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else buffer = read_from_disk(b->start, b->size); read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf; int count; int blocks = (buf->st_size + block_size - 1) >> block_log; int frag_block = !no_fragments && (always_use_fragments || (buf->st_size < block_size)) ? buf->st_size >> block_log : -1; int file; static int block_order = 0; struct file_buffer *file_buffer; if(buf->st_size == 0 || dir_ent->inode->read) return; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; for(count = 0; count < blocks; count ++) { file_buffer = alloc_get(reader_buffer); if((file_buffer->size = read(file, file_buffer->data, block_size)) == -1) { close(file); goto read_err2; } file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; if((file_buffer->fragment = (count == frag_block))) //?? queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); } close(file); dir_ent->inode->read = TRUE; return; read_err: file_buffer = alloc_get(reader_buffer); read_err2: file_buffer->block_order = block_order ++; file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } return NULL; } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } //printf("%d bytes at %Ld\n", file_buffer->size, off); if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } int write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } int write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; struct file_buffer *file_buffer = get_file_buffer(from_deflate); if(file_buffer->error) { alloc_free(file_buffer); return FALSE; } checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) return write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size) { int block, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return FALSE; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, int *duplicate_file) { int block, status, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return FALSE; } int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", dir_ent->pathname, SQUASHFS_MAX_FILE_SIZE); if(read_size == 0) return write_file_empty(inode, dir_ent, duplicate_file); if(!no_fragments && (read_size < block_size)) return write_file_frag(inode, dir_ent, read_size, duplicate_file); if(pre_duplicate(read_size)) return write_file_blocks_dup(inode, dir_ent, read_size, duplicate_file); *duplicate_file = FALSE; return write_file_blocks(inode, dir_ent, read_size); } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, reader_buffer_size); writer_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, writer_buffer_size); fragment_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } #define VERSION() \ printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); \ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { un.un_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); //?? uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); //?? /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { ERROR("%s:%d: %d\n", __func__, __LINE__, i); EXIT_MKSQUASHFS(); } if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC_LZMA; if (!un.un_lzma) sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = buffer}, {.buf = block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC_LZMA: if (!un.un_lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_LZMA_SWAP: if (!un.un_lzma) goto bad; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-hg612-lzma/squashfs3.2-r2/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); int (*create_inode)(char *pathname, unsigned int start_block, unsigned int offset); } squashfs_operations; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; struct sqlzma_un un; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } /* printf("%d bytes at %Ld\n", bytes, off); */ if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = buffer}, {.buf = block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = data, .sz = c_byte}, {.buf = block, .sz = bytes} }; if(read_bytes(start, c_byte, data) == FALSE) return 0; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } int create_inode_2(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header_2 header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, sBlk.mkfs_time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header_2 header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } int matches(char *targname, char *name) { if(*targname == '\0' || strcmp(targname, name) == 0) return TRUE; return FALSE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, char *target) { struct dir *dir = s_ops.squashfs_opendir(start_block, offset); unsigned int type; char *name, pathname[1024]; char targname[1024]; target = get_component(target, targname); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(targname, name)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, target); else if(!lsonly) s_ops.create_inode(pathname, start_block, offset); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ un.un_lzma = 1; swap = 0; switch (sBlk.s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; // how on earth did this bug survive for so long?! MGM default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.create_inode = create_inode_2; } else if(sBlk.s_major == 3 && sBlk.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.create_inode = create_inode; } else { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk.s_major, sBlk.s_minor); ERROR("I support Squashfs 2.x and 3.0 filesystems!\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk.block_size); TRACE("\tNumber of fragments %d\n", sBlk.fragments); TRACE("\tNumber of inodes %d\n", sBlk.inodes); TRACE("\tNumber of uids %d\n", sBlk.no_uids); TRACE("\tNumber of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.3 (2007/01/02)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); \ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; if((root_process = (geteuid() == 0))) //?? umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) goto options; dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directory or file to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-l[s]\t\t\tlist filesystem only\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); } exit(1); } if((i + 1) < argc) target = argv[i + 1]; if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { fputs("sqlzma_init failed", stderr); abort(); } read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), target); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/7zCrcT8.c ================================================ /* 7zCrcT8.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 #define CRC_NUM_TABLES 8 UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; void MY_FAST_CALL CrcGenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } #if CRC_NUM_TABLES > 1 for (; i < 256 * CRC_NUM_TABLES; i++) { UInt32 r = g_CrcTable[i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } #endif } UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { return CrcUpdateT8(v, data, size, g_CrcTable); } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Alloc.c ================================================ /* Alloc.c */ #ifdef _WIN32 #include #endif #include #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return malloc(size); } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Alloc.h ================================================ /* Alloc.h */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c */ #include #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include #endif #include int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include #include "../../Types.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c */ #include #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/Lzma/LzmaDecode.h" #include "../../Compress/Branch/BranchX86.h" #include "../../Compress/Branch/BranchX86_2.h" #endif #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; CFileSize Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; size_t curSize = (1 << 20); if (curSize > cb->Size) curSize = (size_t)cb->Size; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize); *size = (SizeT)processedSize; if (processedSize > curSize) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR; } #ifdef _LZMA_IN_CB SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuffer; size_t processedSize, curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)(inSize); RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize)); if (processedSize == 0) return SZE_DATA_ERROR; if (processedSize > curSize) return SZE_FAIL; memcpy(outBuffer, inBuffer, processedSize); outBuffer += processedSize; inSize -= processedSize; } return SZ_OK; } #endif #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SZ_RESULT CheckSupportedFolder(const CFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZE_NOTIMPL; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZE_NOTIMPL; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZE_NOTIMPL; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZE_NOTIMPL; return SZ_OK; } return SZE_NOTIMPL; } CFileSize GetSum(const CFileSize *values, UInt32 index) { CFileSize sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; size_t tempSizes[3] = { 0, 0, 0}; size_t tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; CFileSize offset; CFileSize inSize; Byte *outBufCur = outBuffer; size_t outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; CFileSize unpackSize = folder->UnPackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (size_t)unpackSize; if (outSizeCur != unpackSize) return SZE_OUTOFMEMORY; temp = (Byte *)allocMain->Alloc(outSizeCur); if (temp == 0 && outSizeCur != 0) return SZE_OUTOFMEMORY; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) return SZE_OUTOFMEMORY; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (size_t)unpackSize; } else return SZE_NOTIMPL; } offset = GetSum(packSizes, si); inSize = packSizes[si]; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); #endif if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); #else memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize); #endif } else { SZ_RESULT res = SzDecodeLzma(coder, inSize, #ifdef _LZMA_IN_CB inStream, #else inBuffer + (size_t)offset, #endif outBufCur, outSizeCur, allocMain); RINOK(res) } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZE_NOTIMPL; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { CFileSize offset = GetSum(packSizes, 1); CFileSize s3Size = packSizes[1]; SZ_RESULT res; if (ci != 3) return SZE_NOTIMPL; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); tempSizes[2] = (size_t)s3Size; if (tempSizes[2] != s3Size) return SZE_OUTOFMEMORY; tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZE_OUTOFMEMORY; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) #endif res = x86_2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], #ifdef _LZMA_IN_CB tempBuf[2], tempSizes[2], #else inBuffer + (size_t)offset, (size_t)s3Size, #endif outBuffer, outSize); RINOK(res) } else return SZE_NOTIMPL; } return SZ_OK; } SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SZ_RESULT res = SzDecode2(packSizes, folder, #ifdef _LZMA_IN_CB inStream, startPos, #else inBuffer, #endif outBuffer, outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) allocMain->Free(tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "../../7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder); size_t unPackSize = (size_t)unPackSizeSpec; CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0); #ifndef _LZMA_IN_CB Byte *inBuffer = 0; size_t processedSize; CFileSize packSizeSpec; size_t packSize; RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec)); packSize = (size_t)packSizeSpec; if (packSize != packSizeSpec) return SZE_OUTOFMEMORY; #endif if (unPackSize != unPackSizeSpec) return SZE_OUTOFMEMORY; *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, startOffset)); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc(packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, packSize, &processedSize); if (res == SZ_OK && processedSize != packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc(unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, startOffset, #else inBuffer, #endif *outBuffer, unPackSize, allocTemp); if (res == SZ_OK) { if (folder->UnPackCRCDefined) { if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC) res = SZE_CRC_ERROR; } } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZE_CRC_ERROR; } } } return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zDecode.h" #include "../../7zCrc.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { CFileSize t = size + db->Database.PackSizes[packStreamIndex + i]; if (t < size) return SZE_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SZ_RESULT SzReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { void *inBufferSpec; size_t processedSize; const Byte *inBuffer; RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize)); inBuffer = (const Byte *)inBufferSpec; if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt64)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, allocFunc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); MY_ALLOC(UInt32, *digests, numItems, allocFunc); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZE_NOTIMPL; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, allocFunc); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } case k7zIdLastWriteTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp->Alloc)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->IsLastWriteTimeDefined = defined; f->LastWriteTime.Low = f->LastWriteTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->LastWriteTime.Low)); RINOK(SzReadUInt32(sd, &f->LastWriteTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); allocTemp->Free(lwtVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, dataStartPos, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, allocTemp); RINOK(res) if (folder->UnPackCRCDefined) if (CrcCalc(outBuffer->Items, (size_t)unPackSize) != folder->UnPackCRC) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc = 0; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc)); crc = CRC_INIT_VAL; RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc)); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc)); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc)); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CRC_GET_DIGEST(crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { res = SZE_ARCHIVE_ERROR; if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC) { for (;;) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->IsLastWriteTimeDefined = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); typedef struct _CArchiveFileTime { UInt32 Low; UInt32 High; } CArchiveFileTime; typedef struct _CFileItem { CArchiveFileTime LastWriteTime; /* CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; Byte IsLastWriteTimeDefined; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04) */ #include #include #include #ifdef _WIN32 #define USE_WINDOWS_FUNCTIONS #endif #ifdef USE_WINDOWS_FUNCTIONS #include #endif #include "7zIn.h" #include "7zExtract.h" #include "../../7zCrc.h" #ifdef USE_WINDOWS_FUNCTIONS typedef HANDLE MY_FILE_HANDLE; #else typedef FILE *MY_FILE_HANDLE; #endif void ConvertNumberToString(CFileSize value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) void ConvertFileTimeToString(CArchiveFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } #ifdef USE_WINDOWS_FUNCTIONS /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). */ #define kChunkSizeMax (1 << 24) #endif size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res || processedLoc == 0) break; } while (size > 0); return processedSize; } #else return fread(data, 1, size, file); #endif } size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res) break; } while (size > 0); return processedSize; } #else return fwrite(data, 1, size, file); #endif } int MyCloseFile(MY_FILE_HANDLE file) { #ifdef USE_WINDOWS_FUNCTIONS return (CloseHandle(file) != FALSE) ? 0 : 1; #else return fclose(file); #endif } typedef struct _CFileInStream { ISzInStream InStream; MY_FILE_HANDLE File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = MyReadFile(s->File, buffer, size); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; #ifdef USE_WINDOWS_FUNCTIONS { LARGE_INTEGER value; value.LowPart = (DWORD)pos; value.HighPart = (LONG)((UInt64)pos >> 32); #ifdef _SZ_FILE_SIZE_32 /* VC 6.0 has bug with >> 32 shifts. */ value.HighPart = 0; #endif value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN); if (value.LowPart == 0xFFFFFFFF) if(GetLastError() != NO_ERROR) return SZE_FAIL; return SZ_OK; } #else int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; #endif } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n"); if (numargs == 1) { printf( "\nUsage: 7zDec \n\n" "\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (archiveStream.File == INVALID_HANDLE_VALUE) #else archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) #endif { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->IsLastWriteTimeDefined) ConvertFileTimeToString(&f->LastWriteTime, t); else strcpy(t, " "); printf("%10s %s %s\n", s, t, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { MY_FILE_HANDLE outputHandle; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (outputHandle == INVALID_HANDLE_VALUE) #else fopen(fileName, "wb+"); if (outputHandle == 0) #endif { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (MyCloseFile(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); MyCloseFile(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == (SZ_RESULT)SZE_NOTIMPL) PrintError("decoder doesn't support this archive"); else if (res == (SZ_RESULT)SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else if (res == (SZ_RESULT)SZE_CRC_ERROR) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" /* int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { return (*a1 == *a2) ? 1 : 0; } */ ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Types.h" typedef UInt64 CMethodID; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/makefile ================================================ PROG = 7zDec.exe !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4 !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** C_OBJS = \ $O\7zCrc.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ $O\BranchX86.obj \ $O\BranchX86_2.obj \ $(C_OBJS) \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c $(COMPL_O2) $O\BranchX86.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c BranchX86.o: ../../Compress/Branch/BranchX86.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchARM.c ================================================ /* BranchARM.c */ #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchARM.h ================================================ /* BranchARM.h */ #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "BranchTypes.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchARMThumb.c ================================================ /* BranchARMThumb.c */ #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchARMThumb.h ================================================ /* BranchARMThumb.h */ #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "BranchTypes.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchIA64.c ================================================ /* BranchIA64.c */ #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 /* && (instNorm & 0x3F)== 0 */ ) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchIA64.h ================================================ /* BranchIA64.h */ #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "BranchTypes.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchPPC.c ================================================ /* BranchPPC.c */ #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */ if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 /* || (data[i+3] & 3) == 3 */ ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchPPC.h ================================================ /* BranchPPC.h */ #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "BranchTypes.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchSPARC.c ================================================ /* BranchSPARC.c */ #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchSPARC.h ================================================ /* BranchSPARC.h */ #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "BranchTypes.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchTypes.h ================================================ /* BranchTypes.h */ #ifndef __BRANCHTYPES_H #define __BRANCHTYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *prevMaskMix & 0x7; if (endPos < 5) return 0; nowPos += 5; prevPosT = (SizeT)0 - 1; for(;;) { Byte *p = buffer + bufferPos; Byte *limit = buffer + endPos - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - buffer); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (nowPos + (UInt32)bufferPos) + src; else dest = src - (nowPos + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #include "BranchTypes.h" #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchX86_2.c ================================================ // BranchX86_2.c #include "BranchX86_2.h" #include "../../Alloc.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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; }} #define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; } #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 #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 UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits)); // #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits)); int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *Buffer, *BufferLim; UInt32 Range, Code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; RC_INIT(buf3, size3); if (outSize == 0) return BCJ2_RESULT_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IfBit0(prob) { UpdateBit0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UpdateBit1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return BCJ2_RESULT_DATA_ERROR; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return BCJ2_RESULT_DATA_ERROR; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Branch/BranchX86_2.h ================================================ // BranchX86_2.h #ifndef __BRANCHX86_2_H #define __BRANCHX86_2_H #include "BranchTypes.h" #define BCJ2_RESULT_OK 0 #define BCJ2_RESULT_DATA_ERROR 1 /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). */ int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Huffman/HuffmanEncode.c ================================================ /* Compress/HuffmanEncode.c */ #include "HuffmanEncode.h" #include "../../Sort.h" #define kMaxLen 16 #define NUM_BITS 10 #define MASK ((1 << NUM_BITS) - 1) #define NUM_COUNTERS 64 /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */ #define HUFFMAN_SPEED_OPT void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) { UInt32 num = 0; /* if (maxLen > 10) maxLen = 10; */ { UInt32 i; #ifdef HUFFMAN_SPEED_OPT UInt32 counters[NUM_COUNTERS]; for (i = 0; i < NUM_COUNTERS; i++) counters[i] = 0; for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; } for (i = 1; i < NUM_COUNTERS; i++) { UInt32 temp = counters[i]; counters[i] = num; num += temp; } for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); } counters[0] = 0; HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); #else for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[num++] = i | (freq << NUM_BITS); } HeapSort(p, num); #endif } if (num < 2) { int minCode = 0; int maxCode = 1; if (num == 1) { maxCode = p[0] & MASK; if (maxCode == 0) maxCode++; } p[minCode] = 0; p[maxCode] = 1; lens[minCode] = lens[maxCode] = 1; return; } { UInt32 b, e, i; i = b = e = 0; do { UInt32 n, m, freq; n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq = (p[n] & ~MASK); p[n] = (p[n] & MASK) | (e << NUM_BITS); m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq += (p[m] & ~MASK); p[m] = (p[m] & MASK) | (e << NUM_BITS); p[e] = (p[e] & MASK) | freq; e++; } while (num - e > 1); { UInt32 lenCounters[kMaxLen + 1]; for (i = 0; i <= kMaxLen; i++) lenCounters[i] = 0; p[--e] &= MASK; lenCounters[1] = 2; while (e > 0) { UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; p[e] = (p[e] & MASK) | (len << NUM_BITS); if (len >= maxLen) for (len = maxLen - 1; lenCounters[len] == 0; len--); lenCounters[len]--; lenCounters[len + 1] += 2; } { UInt32 len; i = 0; for (len = maxLen; len != 0; len--) { UInt32 num; for (num = lenCounters[len]; num != 0; num--) lens[p[i++] & MASK] = (Byte)len; } } { UInt32 nextCodes[kMaxLen + 1]; { UInt32 code = 0; UInt32 len; for (len = 1; len <= kMaxLen; len++) nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; } /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ { UInt32 i; for (i = 0; i < numSymbols; i++) p[i] = nextCodes[lens[i]]++; } } } } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Huffman/HuffmanEncode.h ================================================ /* Compress/HuffmanEncode.h */ #ifndef __COMPRESS_HUFFMANENCODE_H #define __COMPRESS_HUFFMANENCODE_H #include "../../Types.h" /* Conditions: num <= 1024 = 2 ^ NUM_BITS Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) maxLen <= 16 = kMaxLen Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) */ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lz/LzHash.h ================================================ /* LzHash.h */ #ifndef __C_LZHASH_H #define __C_LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \ hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lz/MatchFinder.c ================================================ /* MatchFinder.c */ /* Please call InitCrcTable before */ #include #include "MatchFinder.h" #include "LzHash.h" #include "../../7zCrc.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); UInt32 numReadBytes; UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, size, &numReadBytes); if (p->result != SZ_OK) return; if (numReadBytes == 0) { p->streamEndWasReached = 1; return; } p->streamPos += numReadBytes; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, p->streamPos - p->pos + p->keepSizeBefore); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } void MatchFinder_Construct(CMatchFinder *p) { p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); } void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for(i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while(++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lz/MatchFinder.h ================================================ /* MatchFinder.h */ #ifndef __MATCHFINDER_H #define __MATCHFINDER_H #include "../../IStream.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; HRes result; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lz/MatchFinderMt.c ================================================ /* MatchFinderMt.c */ #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include #else #include #endif #endif #include "../../7zCrc.h" #include "LzHash.h" #include "MatchFinderMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { HRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads(name, v) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \ for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask) DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #if _MSC_VER >= 1300 #define NO_INLINE __declspec(noinline) __fastcall #else #ifdef _MSC_VER #define NO_INLINE __fastcall #endif #endif Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned StdCall BtThreadFunc2(void *p) { #ifdef USE_ALLOCA alloca(0x180); #endif BtThreadFunc((CMatchFinderMt *)p); return 0; } HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return E_INVALIDARG; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZE_OUTOFMEMORY; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZE_OUTOFMEMORY; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lz/MatchFinderMt.h ================================================ /* MatchFinderMt.h */ #ifndef __MATCHFINDERMT_H #define __MATCHFINDERMT_H #include "../../Threads.h" #include "MatchFinder.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaDecode.c ================================================ /* LzmaDecode.c LZMA Decoder (optimized for Speed version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #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; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaDecode.h ================================================ /* LzmaDecode.h LZMA Decoder interface LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 #include "LzmaTypes.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 */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #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 ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; for (;;) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H #include "LzmaTypes.h" /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include #include #include #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include #include #include #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/LzmaTypes.h ================================================ /* LzmaTypes.h Types for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.40 (2006-05-01) */ #ifndef __LZMATYPES_H #define __LZMATYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/kmod/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include #include #include #include #include #include #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include #include #include #include #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (unlikely(err)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima "); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/kmod.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: kmod.mk,v 1.1 2007-11-05 05:43:35 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif ifndef KDir $(error KDir is not defined) endif #include makefile.gcc Kmod = kmod EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} # -D_LZMA_PROB32 EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) all: ${Kmod}/uncomp.c ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ -C ${KDir} C=0 V=0 modules ${Kmod}/uncomp.c: uncomp.c ln $< $@ clean: clean_kmod clean_kmod: ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean ${RM} ${Kmod}/*~ -@test -e ${Kmod}/uncomp.c && \ diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif #include makefile.gcc CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 ifdef KDir include kmod.mk endif ifdef UseDebugFlags DebugFlags = -O0 -g -UNDEBUG endif CFLAGS += -DNDEBUG ${DebugFlags} Tgt = libunlzma.a libunlzma_r.a all: ${Tgt} %_r.c: %.c ln $< $@ # -pthread %_r.o: CFLAGS += -D_REENTRANT -include pthread.h uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h libunlzma.a: uncomp.o LzmaDecode.o ${AR} cr $@ $^ libunlzma_r.a: uncomp_r.o LzmaDecode_r.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o LzmaDecode.o *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/testflags.c ================================================ #ifdef _LZMA_PROB32 -D_LZMA_PROB32 #else -U_LZMA_PROB32 #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Compress/Lzma/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include #include #include #include #include #include #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include #include #include #include #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (unlikely(err)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima "); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/CpuArch.h ================================================ /* CpuArch.h */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/IStream.h ================================================ /* IStream.h */ #ifndef __C_ISTREAM_H #define __C_ISTREAM_H #include "Types.h" typedef struct _ISeqInStream { HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize); } ISeqInStream; typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Sort.c ================================================ /* Sort.c */ #include "Sort.h" #define HeapSortDown(p, k, size, temp) \ { for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && p[s + 1] > p[s]) s++; \ if (temp >= p[s]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSort(UInt32 *p, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; UInt32 k = i; HeapSortDown(p, k, size, temp) } while(--i != 0); } /* do { UInt32 k = 1; UInt32 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) } while (size > 1); */ while (size > 3) { UInt32 temp = p[size]; UInt32 k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) } { UInt32 temp = p[size]; p[size] = p[1]; if (size > 2 && p[2] < temp) { p[1] = p[2]; p[2] = temp; } else p[1] = temp; } } /* #define HeapSortRefDown(p, vals, n, size, temp) \ { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ if (val >= vals[p[s]]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; HeapSortRefDown(p, vals, i, size, temp); } while(--i != 0); } do { UInt32 temp = p[size]; p[size--] = p[1]; HeapSortRefDown(p, vals, 1, size, temp); } while (size > 1); } */ ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Sort.h ================================================ /* Sort.h */ #ifndef __7Z_Sort_H #define __7Z_Sort_H #include "Types.h" void HeapSort(UInt32 *p, UInt32 size); /* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Threads.c ================================================ /* Threads.c */ #include "Threads.h" #include HRes GetError() { DWORD res = GetLastError(); return (res) ? (HRes)(res) : SZE_FAIL; } HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); } HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); } HRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return SZ_OK; } HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return BoolToHRes(thread->handle != 0); } HRes WaitObject(HANDLE h) { return (HRes)WaitForSingleObject(h, INFINITE); } HRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } HRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } HRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return BoolToHRes(p->handle != 0); } HRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); } HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); } HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return BoolToHRes(p->handle != 0); } HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } HRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } HRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; } return SZ_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Threads.h ================================================ /* Threads.h */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE StdCall #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); HRes Thread_Wait(CThread *thread); HRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) HRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); HRes Event_Set(CEvent *event); HRes Event_Reset(CEvent *event); HRes Event_Wait(CEvent *event); HRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); HRes Semaphore_Release1(CSemaphore *p); HRes Semaphore_Wait(CSemaphore *p); HRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; HRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/C/Types.h ================================================ /* 7zTypes.h */ #ifndef __C_TYPES_H #define __C_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED #ifdef _LZMA_INT32_IS_ULONG typedef long Int32; #else typedef int Int32; #endif #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _SZ_FILE_SIZE_32 */ /* You can define _SZ_FILE_SIZE_32, if you don't need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_32 typedef UInt32 CFileSize; #else typedef UInt64 CFileSize; #endif #endif #define SZ_RESULT int typedef int HRes; #define RES_OK (0) #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_CRC_ERROR (3) #define SZE_ARCHIVE_ERROR (6) #define SZE_OUTOFMEMORY (0x8007000EL) #define SZE_NOTIMPL (0x80004001L) #define SZE_FAIL (0x80004005L) #define SZE_INVALIDARG (0x80070057L) #ifndef RINOK #define RINOK(x) { HRes __result_ = (x); if(__result_ != 0) return __result_; } #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #define StdCall __stdcall #else #define StdCall #endif #if _MSC_VER >= 1300 #define MY_FAST_CALL __declspec(noinline) __fastcall #elif defined( _MSC_VER) #define MY_FAST_CALL __fastcall #else #define MY_FAST_CALL #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector Methods; CRecordVector Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "7zDecode.h" #include "../../IPassword.h" #include "../../Common/LockedStream.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { CObjectVector< CMyComPtr > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr decoder; CMyComPtr decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unPackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr &decoder = _decoders[coderIndex]; { CMyComPtr setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &properties = coderInfo.Properties; size_t size = properties.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); CByteBuffer buffer; UString unicodePassword(password); const UInt32 sizeInBytes = unicodePassword.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < unicodePassword.Length(); i++) { wchar_t c = unicodePassword[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword( (const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector packSizesPointers; CRecordVector unPackSizesPointers; packSizesPointers.Reserve(numInStreams); unPackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unPackStreamIndex++) unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unPackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr _mixerCoder; CObjectVector > _decoders; // CObjectVector > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr encoder; CMyComPtr encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector inOutTempBuffers; CObjectVector tempBufferSpecs; CObjectVector > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector inStreamPointers; CRecordVector outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Properties.SetCapacity(size); memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnPackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr _mixerCoder; CObjectVector _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnPackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnPackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr extractCallback = extractCallbackSpec; UInt64 importantTotalUnPacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _database.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &database = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &database = _database; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = database.Folders[folderIndex]; UInt64 unPackSize = folderInfo.GetUnPackSize(); importantTotalUnPacked += unPackSize; extractFolderInfoVector.Back().UnPackSize = unPackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = database.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize; // Count partial_folder_size // efi.UnPackSize += unPackSize; // importantTotalUnPacked += unPackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnPacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnPacked = 0; UInt64 totalFolderUnPacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnPacked += totalFolderUnPacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnPacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnPacked = efi.UnPackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; #else const CArchiveDatabaseEx &database = _database; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = database.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&database, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = database.Folders[folderIndex]; totalFolderPacked = _database.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &database.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr _inStreamWithHash; CMyComPtr _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector Processed; CRecordVector CRCs; CRecordVector Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; UInt64 fileSize = fileInfo.UnPackSize; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fileInfo.IsFileCRCDefined && _checkCrc) digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zProperties.h" #include "../../../Common/IntToString.h" #include "../../../Common/ComTry.h" #include "../../../Windows/Defs.h" #include "../Common/ItemNameUtils.h" #ifdef _7Z_VOL #include "../Common/MultiStream.h" #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = #ifdef _7Z_VOL _refs.Size(); #else *numItems = _database.Files.Size(); #endif return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector ids; int i; for (i = 0; i < _database.Folders.Size(); i++) { const CFolder &f = _database.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _database.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop) { if (timeDefined) prop = unixTime; } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; #ifndef _SFX static inline UInt32 GetUInt32FromMemLE(const Byte *p) { return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); } #endif bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ #ifdef _7Z_VOL const CRef &ref = _refs[index]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &_database = volume.Database; UInt32 index2 = ref.ItemIndex; const CFileItem &item = _database.Files[index2]; #else const CFileItem &item = _database.Files[index]; UInt32 index2 = index; #endif switch(propID) { case kpidPath: { if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; } case kpidIsFolder: prop = item.IsDirectory; break; case kpidSize: { prop = item.UnPackSize; // prop = ref2.UnPackSize; break; } case kpidPosition: { /* if (ref2.Refs.Size() > 1) prop = ref2.StartPos; else */ if (item.IsStartPosDefined) prop = item.StartPos; break; } case kpidPackedSize: { // prop = ref2.PackSize; { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _database.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidLastAccessTime: MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop); break; case kpidCreationTime: MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop); break; case kpidLastWriteTime: MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop); break; case kpidAttributes: if (item.AreAttributesDefined) prop = item.Attributes; break; case kpidCRC: if (item.IsFileCRCDefined) prop = item.FileCRC; break; case kpidEncrypted: { prop = IsEncrypted(index2); break; } #ifndef _SFX case kpidMethod: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Properties.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Properties.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Properties; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Properties.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Properties; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Properties.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Properties.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Properties[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif case kpidIsAnti: prop = item.IsAnti; break; } prop.Detach(value); return S_OK; COM_TRY_END } #ifdef _7Z_VOL static const wchar_t *kExt = L"7z"; static const wchar_t *kAfterPart = L".7z"; class CVolumeName { bool _first; UString _unchangedPart; UString _changedPart; UString _afterPart; public: bool InitName(const UString &name) { _first = true; int dotPos = name.ReverseFind('.'); UString basePart = name; if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (ext.CompareNoCase(kExt)==0 || ext.CompareNoCase(L"EXE") == 0) { _afterPart = kAfterPart; basePart = name.Left(dotPos); } } int numLetters = 1; bool splitStyle = false; if (basePart.Right(numLetters) == L"1") { while (numLetters < basePart.Length()) { if (basePart[basePart.Length() - numLetters - 1] != '0') break; numLetters++; } } else return false; _unchangedPart = basePart.Left(basePart.Length() - numLetters); _changedPart = basePart.Right(numLetters); return true; } UString GetNextName() { UString newName; // if (_newStyle || !_first) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = UString(c) + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } _changedPart = newName; } _first = false; return _unchangedPart + _changedPart + _afterPart; } }; #endif STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr openArchiveCallbackTemp = openArchiveCallback; #ifdef _7Z_VOL CVolumeName seqName; CMyComPtr openVolumeCallback; #endif #ifndef _NO_CRYPTO CMyComPtr getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif #ifdef _7Z_VOL if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); } for (;;) { CMyComPtr inStream; if (!_volumes.IsEmpty()) { if (!openVolumeCallback) break; if(_volumes.Size() == 1) { UString baseName; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; baseName = prop.bstrVal; } seqName.InitName(baseName); } UString fullName = seqName.GetNextName(); HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; } else inStream = stream; CInArchive archive; RINOK(archive.Open(inStream, maxCheckStartPosition)); _volumes.Add(CVolume()); CVolume &volume = _volumes.Back(); CArchiveDatabaseEx &database = volume.Database; volume.Stream = inStream; volume.StartRef2Index = _refs.Size(); HRESULT result = archive.ReadDatabase(database #ifndef _NO_CRYPTO , getTextPassword #endif ); if (result != S_OK) { _volumes.Clear(); return result; } database.Fill(); for(int i = 0; i < database.Files.Size(); i++) { CRef refNew; refNew.VolumeIndex = _volumes.Size() - 1; refNew.ItemIndex = i; _refs.Add(refNew); /* const CFileItem &file = database.Files[i]; int j; */ /* for (j = _refs.Size() - 1; j >= 0; j--) { CRef2 &ref2 = _refs[j]; const CRef &ref = ref2.Refs.Back(); const CVolume &volume2 = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database2 = volume2.Database; const CFileItem &file2 = database2.Files[ref.ItemIndex]; if (file2.Name.CompareNoCase(file.Name) == 0) { if (!file.IsStartPosDefined) continue; if (file.StartPos != ref2.StartPos + ref2.UnPackSize) continue; ref2.Refs.Add(refNew); break; } } */ /* j = -1; if (j < 0) { CRef2 ref2New; ref2New.Refs.Add(refNew); j = _refs.Add(ref2New); } CRef2 &ref2 = _refs[j]; ref2.UnPackSize += file.UnPackSize; ref2.PackSize += database.GetFilePackSize(i); if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) ref2.StartPos = file.StartPos; */ } if (database.Files.Size() != 1) break; const CFileItem &file = database.Files.Front(); if (!file.IsStartPosDefined) break; } #else CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _database #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); _database.Fill(); _inStream = stream; #endif } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN #ifdef _7Z_VOL _volumes.Clear(); _refs.Clear(); #else _inStream.Release(); _database.Clear(); #endif return S_OK; COM_TRY_END } #ifdef _7Z_VOL STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr streamTemp = streamSpec; UInt64 pos = 0; const UString *fileName; for (int i = 0; i < _refs.Size(); i++) { const CRef &ref = _refs[i]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; const CFileItem &file = database.Files[ref.ItemIndex]; if (i == 0) fileName = &file.Name; else if (fileName->Compare(file.Name) != 0) return S_FALSE; if (!file.IsStartPosDefined) return S_FALSE; if (file.StartPos != pos) return S_FALSE; CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; if (folderIndex == kNumNoIndex) { if (file.UnPackSize != 0) return E_FAIL; continue; } if (database.NumUnPackStreamsVector[folderIndex] != 1) return S_FALSE; const CFolder &folder = database.Folders[folderIndex]; if (folder.Coders.Size() != 1) return S_FALSE; const CCoderInfo &coder = folder.Coders.Front(); if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) return S_FALSE; if (coder.MethodID != k_Copy) return S_FALSE; pos += file.UnPackSize; CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = volume.Stream; subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); subStreamInfo.Size = file.UnPackSize; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifdef _7Z_VOL struct CRef { int VolumeIndex; int ItemIndex; }; struct CVolume { int StartRef2Index; CMyComPtr Stream; CArchiveDatabaseEx Database; }; #endif #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef _7Z_VOL public IInArchiveGetStream, #endif #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef _7Z_VOL MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) #endif #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef _7Z_VOL STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); #endif #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: #ifdef _7Z_VOL CObjectVector _volumes; CObjectVector _refs; #else CMyComPtr _inStream; NArchive::N7z::CArchiveDatabaseEx _database; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector _fileInfoPopIDs; void FillPopIDs(); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr getTextPassword; if (!getTextPassword) { CMyComPtr udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = UInt32(kNumFastBytesForHeaders); oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = UInt32(kDictionaryForHeaders); oneMethodInfo.Properties.Add(property); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Properties = oneMethodInfo.Properties; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Properties.Size(); j++) { const CProp &prop = methodFull.Properties[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(index, propID, &propVariant)); if (propVariant.vt == VT_FILETIME) { filetime = propVariant.filetime; filetimeIsDefined = true; } else if (propVariant.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *database = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); database = &volume->Database; } #else if (_inStream != 0) database = &_database; #endif // CRecordVector compressStatuses; CObjectVector updateItems; // CRecordVector copyIndices; // CMyComPtr updateCallback2; // updateCallback->QueryInterface(&updateCallback2); for(UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem updateItem; updateItem.NewProperties = IntToBool(newProperties); updateItem.NewData = IntToBool(newData); updateItem.IndexInArchive = indexInArchive; updateItem.IndexInClient = i; updateItem.IsAnti = false; updateItem.Size = 0; if (updateItem.IndexInArchive != -1) { const CFileItem &fileItem = database->Files[updateItem.IndexInArchive]; updateItem.Name = fileItem.Name; updateItem.IsDirectory = fileItem.IsDirectory; updateItem.Size = fileItem.UnPackSize; updateItem.IsAnti = fileItem.IsAnti; updateItem.CreationTime = fileItem.CreationTime; updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined; updateItem.LastWriteTime = fileItem.LastWriteTime; updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined; updateItem.LastAccessTime = fileItem.LastAccessTime; updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined; } if (updateItem.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.AttributesAreDefined = false; else if (propVariant.vt != VT_UI4) return E_INVALIDARG; else { updateItem.Attributes = propVariant.ulVal; updateItem.AttributesAreDefined = true; } } RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined)); { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant)); if (propVariant.vt == VT_EMPTY) nameIsDefined = false; else if (propVariant.vt != VT_BSTR) return E_INVALIDARG; else { updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant)); if (propVariant.vt == VT_EMPTY) folderStatusIsDefined = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else { updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.IsAnti = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE); } if (updateItem.IsAnti) { updateItem.AttributesAreDefined = false; updateItem.IsCreationTimeDefined = false; updateItem.IsLastWriteTimeDefined = false; updateItem.IsLastAccessTimeDefined = false; updateItem.Size = 0; } if (!folderStatusIsDefined && updateItem.AttributesAreDefined) updateItem.SetDirectoryStatusFromAttributes(); } if (updateItem.NewData) { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant)); if (propVariant.vt != VT_UI8) return E_INVALIDARG; updateItem.Size = (UInt64)propVariant.uhVal.QuadPart; if (updateItem.Size != 0 && updateItem.IsAnti) return E_INVALIDARG; } updateItems.Add(updateItem); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it if (methodMode.PasswordIsDefined) { compressMainHeader = true; if(_encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || (methodMode.PasswordIsDefined && _encryptHeaders)) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteModified = WriteModified; options.HeaderOptions.WriteCreated = WriteCreated; options.HeaderOptions.WriteAccessed = WriteAccessed; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; return Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? database: 0, #else _inStream, database, #endif updateItems, outStream, updateCallback, options); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnPackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnPackSize, kNumUnPackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCreationTime, kLastAccessTime, kLastWriteTime, kWinAttributes, kComment, kEncodedHeader, kStartPos }; } }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" #include "7zIn.h" #include "7zDecode.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" extern "C" { #include "../../../../C/7zCrc.h" } // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define SZ_LITTLE_ENDIAN_UNALIGN #endif #ifdef SZ_LITTLE_ENDIAN_UNALIGN static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; } static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; } static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; } #else static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); } static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); } static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); } #endif Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = GetUInt32FromMem(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = GetUInt64FromMem(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)GetUInt16FromMem(buf); p[i] = 0; s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { UInt32 processedSize; RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize)); if (processedSize != kHeaderSize) return S_FALSE; if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; UInt32 numReadBytes = kBufferSize - numPrevBytes; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); UInt32 numBytesInBuffer = numPrevBytes + processedSize; if (numBytesInBuffer < kHeaderSize) break; UInt32 numTests = numBytesInBuffer - kHeaderSize + 1; for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) { if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } numPrevBytes = numBytesInBuffer - numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propertiesSize = ReadNum(); coder.Properties.SetCapacity((size_t)propertiesSize); ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs; numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bindPair; bindPair.InIndex = ReadNum(); bindPair.OutIndex = ReadNum(); folder.BindPairs.Add(bindPair); } CNum numPackedStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackedStreams); if (numPackedStreams == 1) { for (CNum j = 0; j < numInStreams; j++) if (folder.FindBindPairForInStream(j) < 0) { folder.PackStreams.Add(j); break; } } else for(i = 0; i < numPackedStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CRecordVector &digestsDefined, CRecordVector &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for(int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector &packSizes, CRecordVector &packCRCsDefined, CRecordVector &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { packCRCsDefined.Reserve(numPackStreams); packCRCsDefined.Clear(); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for(CNum i = 0; i < numPackStreams; i++) { packCRCsDefined.Add(false); packCRCs.Add(0); } } } void CInArchive::ReadUnPackInfo( const CObjectVector *dataVector, CObjectVector &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for(CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnPackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnPackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnPackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CRecordVector crcsDefined; CRecordVector crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for(i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnPackCRCDefined = crcsDefined[i]; folder.UnPackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector &folders, CRecordVector &numUnPackStreamsInFolders, CRecordVector &unPackSizes, CRecordVector &digestsDefined, CRecordVector &digests) { numUnPackStreamsInFolders.Clear(); numUnPackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnPackStream) { for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnPackStreamsInFolders.IsEmpty()) for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(1); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unPackSizes.Add(size); sum += size; } unPackSizes.Add(folders[i].GetUnPackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for(i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CRecordVector digestsDefined2; CRecordVector digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnPackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnPackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { digestsDefined.Clear(); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) { digestsDefined.Add(false); digests.Add(0); } } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, CRecordVector &packSizes, CRecordVector &packCRCsDefined, CRecordVector &packCRCs, CObjectVector &folders, CRecordVector &numUnPackStreamsInFolders, CRecordVector &unPackSizes, CRecordVector &digestsDefined, CRecordVector &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnPackInfo: { ReadUnPackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for(int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt32 type) { CBoolVector boolVector; ReadBoolVector2(files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; fileTime.dwLowDateTime = 0; fileTime.dwHighDateTime = 0; bool defined = boolVector[i]; if (defined) { fileTime.dwLowDateTime = ReadUInt32(); fileTime.dwHighDateTime = ReadUInt32(); } switch(type) { case NID::kCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case NID::kLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case NID::kLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { CRecordVector packSizes; CRecordVector packCRCsDefined; CRecordVector packCRCs; CObjectVector folders; CRecordVector numUnPackStreamsInFolders; CRecordVector unPackSizes; CRecordVector digestsDefined; CRecordVector digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for(int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unPackSize64 = folder.GetUnPackSize(); size_t unPackSize = (size_t)unPackSize64; if (unPackSize != unPackSize64) ThrowUnsupported(); data.SetCapacity(unPackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr outStream = outStreamSpec; outStreamSpec->Init(data, unPackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnPackCRCDefined) if (CrcCalc(data, unPackSize) != folder.UnPackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) dataStartPos += packSizes[packIndex++]; } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(database.ArchiveInfo); type = ReadID(); } CObjectVector dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector unPackSizes; CRecordVector digestsDefined; CRecordVector digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, database.ArchiveInfo.DataStartPosition, database.PackSizes, database.PackCRCsDefined, database.PackCRCs, database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests); database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for(int i = 0; i < database.Folders.Size(); i++) { database.NumUnPackStreamsVector.Add(1); CFolder &folder = database.Folders[i]; unPackSizes.Add(folder.GetUnPackSize()); digestsDefined.Add(folder.UnPackCRCDefined); digests.Add(folder.UnPackCRC); } } database.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); database.Files.Reserve(numFiles); CNum i; for(i = 0; i < numFiles; i++) database.Files.Add(CFileItem()); database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!database.PackSizes.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; emptyStreamVector.Reserve((int)numFiles); for(i = 0; i < numFiles; i++) emptyStreamVector.Add(false); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < database.Files.Size(); i++) _inByteBack->ReadString(database.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.AreAttributesDefined = boolVector[i]; if (file.AreAttributesDefined) file.Attributes = ReadUInt32(); } break; } case NID::kStartPos: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.IsStartPosDefined = boolVector[i]; if (file.IsStartPosDefined) file.StartPos = ReadUInt64(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; emptyFileVector.Reserve(numEmptyStreams); antiFileVector.Reserve(numEmptyStreams); for (i = 0; i < numEmptyStreams; i++) { emptyFileVector.Add(false); antiFileVector.Add(false); } break; } case NID::kEmptyFile: { ReadBoolVector(numEmptyStreams, emptyFileVector); break; } case NID::kAnti: { ReadBoolVector(numEmptyStreams, antiFileVector); break; } case NID::kCreationTime: case NID::kLastWriteTime: case NID::kLastAccessTime: { ReadTime(dataVector, database.Files, (UInt32)type); break; } default: isKnownType = false; } if (isKnownType) database.ArchiveInfo.FileInfoPopIDs.Add(type); else SkeepData(size); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.HasStream = !emptyStreamVector[i]; if(file.HasStream) { file.IsDirectory = false; file.IsAnti = false; file.UnPackSize = unPackSizes[sizeIndex]; file.FileCRC = digests[sizeIndex]; file.IsFileCRCDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDirectory = !emptyFileVector[emptyFileIndex]; file.IsAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.UnPackSize = 0; file.IsFileCRCDefined = false; } } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for(int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for(int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnPackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnPackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { database.Clear(); database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; database.ArchiveInfo.Version.Major = _header[6]; database.ArchiveInfo.Version.Minor = _header[7]; if (database.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = GetUInt32FromMem(_header + 8); UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC); UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14); UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); UInt32 realProcessedSize; RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize)); int i; for (i = (int)realProcessedSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = realProcessedSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); UInt32 realProcessedSize; RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize)); if (realProcessedSize != (UInt32)nextHeaderSize) return S_FALSE; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector dataVector; for (;;) { UInt64 type = ReadID(); if (type == NID::kHeader) break; if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); } return ReadHeader( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../IPassword.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector PackStreamStartPositions; CRecordVector FolderStartPackStreamIndex; CRecordVector FolderStartFileIndex; CRecordVector FileIndexToFolderIndexMap; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; size_t _pos; public: void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr _stream; CObjectVector _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CRecordVector &digestsDefined, CRecordVector &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector &packSizes, CRecordVector &packCRCsDefined, CRecordVector &packCRCs); void ReadUnPackInfo( const CObjectVector *dataVector, CObjectVector &folders); void ReadSubStreamsInfo( const CObjectVector &folders, CRecordVector &numUnPackStreamsInFolders, CRecordVector &unPackSizes, CRecordVector &digestsDefined, CRecordVector &digests); void ReadStreamsInfo( const CObjectVector *dataVector, UInt64 &dataOffset, CRecordVector &packSizes, CRecordVector &packCRCsDefined, CRecordVector &packCRCs, CObjectVector &folders, CRecordVector &numUnPackStreamsInFolders, CRecordVector &unPackSizes, CRecordVector &digestsDefined, CRecordVector &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadTime(const CObjectVector &dataVector, CObjectVector &files, UInt32 type); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Properties; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector Coders; CRecordVector BindPairs; CRecordVector PackStreams; CRecordVector UnPackSizes; UInt32 UnPackCRC; bool UnPackCRCDefined; CFolder(): UnPackCRCDefined(false) {} UInt64 GetUnPackSize() const // test it { if (UnPackSizes.IsEmpty()) return 0; for (int i = UnPackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnPackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } }; typedef FILETIME CArchiveFileTime; class CFileItem { public: CArchiveFileTime CreationTime; CArchiveFileTime LastWriteTime; CArchiveFileTime LastAccessTime; UInt64 UnPackSize; UInt64 StartPos; UInt32 Attributes; UInt32 FileCRC; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDirectory; bool IsAnti; bool IsFileCRCDefined; bool AreAttributesDefined; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsStartPosDefined; /* const bool HasStream() const { return !IsDirectory && !IsAnti && UnPackSize != 0; } */ CFileItem(): HasStream(true), IsDirectory(false), IsAnti(false), IsFileCRCDefined(false), AreAttributesDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false), IsStartPosDefined(false) {} void SetAttributes(UInt32 attributes) { AreAttributesDefined = true; Attributes = attributes; } void SetCreationTime(const CArchiveFileTime &creationTime) { IsCreationTimeDefined = true; CreationTime = creationTime; } void SetLastWriteTime(const CArchiveFileTime &lastWriteTime) { IsLastWriteTimeDefined = true; LastWriteTime = lastWriteTime; } void SetLastAccessTime(const CArchiveFileTime &lastAccessTime) { IsLastAccessTimeDefined = true; LastAccessTime = lastAccessTime; } }; struct CArchiveDatabase { CRecordVector PackSizes; CRecordVector PackCRCsDefined; CRecordVector PackCRCs; CObjectVector Folders; CRecordVector NumUnPackStreamsVector; CObjectVector Files; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnPackStreamsVector.Clear(); Files.Clear(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnPackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool IsSolid() const { for (int i = 0; i < NumUnPackStreamsVector.Size(); i++) if (NumUnPackStreamsVector[i] > 1) return true; return false; } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if(processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 value) { for (int i = 0; i < 4; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } UInt32 CrcUpdateUInt64(UInt32 crc, UInt64 value) { for (int i = 0; i < 8; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } HRESULT COutArchive::WriteDirectUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteDirectUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteSignature() { RINOK(WriteDirect(kSignature, kSignatureSize)); RINOK(WriteDirectByte(kMajorVersion)); return WriteDirectByte(2); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { UInt32 crc = CRC_INIT_VAL; crc = CrcUpdateUInt64(crc, h.NextHeaderOffset); crc = CrcUpdateUInt64(crc, h.NextHeaderSize); crc = CrcUpdateUInt32(crc, h.NextHeaderCRC); RINOK(WriteDirectUInt32(CRC_GET_DIGEST(crc))); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); return WriteDirectUInt32(h.NextHeaderCRC); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } HRESULT COutArchive::WriteBytes(const void *data, size_t size) { if (_mainMode) { if (_dynamicMode) _dynamicBuffer.Write(data, size); else _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else { if (_countMode) _countSize += size; else RINOK(_outByte2.Write(data, size)); } return S_OK; } HRESULT COutArchive::WriteBytes(const CByteBuffer &data) { return WriteBytes(data, data.GetCapacity()); } HRESULT COutArchive::WriteByte(Byte b) { return WriteBytes(&b, 1); } HRESULT COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } RINOK(WriteByte(firstByte)); for (;i > 0; i--) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } #ifdef _7Z_VOL static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 0; i < 8; i++) if (value < ((UInt64(1) << ( 7 * (i + 1))))) break; return 1 + i; } UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif HRESULT COutArchive::WriteFolder(const CFolder &folder) { RINOK(WriteNumber(folder.Coders.Size())); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propertiesSize = coder.Properties.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propertiesSize != 0) ? 0x20 : 0 ); RINOK(WriteByte(b)); RINOK(WriteBytes(longID, idSize)); if (isComplex) { RINOK(WriteNumber(coder.NumInStreams)); RINOK(WriteNumber(coder.NumOutStreams)); } if (propertiesSize == 0) continue; RINOK(WriteNumber(propertiesSize)); RINOK(WriteBytes(coder.Properties, propertiesSize)); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; RINOK(WriteNumber(bindPair.InIndex)); RINOK(WriteNumber(bindPair.OutIndex)); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { RINOK(WriteNumber(folder.PackStreams[i])); } return S_OK; } HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for(int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { RINOK(WriteByte(b)); mask = 0x80; b = 0; } } if (mask != 0x80) { RINOK(WriteByte(b)); } return S_OK; } HRESULT COutArchive::WriteHashDigests( const CRecordVector &digestsDefined, const CRecordVector &digests) { int numDefined = 0; int i; for(i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return S_OK; RINOK(WriteByte(NID::kCRC)); if (numDefined == digestsDefined.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(digestsDefined)); } for(i = 0; i < digests.Size(); i++) { if(digestsDefined[i]) RINOK(WriteUInt32(digests[i])); } return S_OK; } HRESULT COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CRecordVector &packCRCsDefined, const CRecordVector &packCRCs) { if (packSizes.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kPackInfo)); RINOK(WriteNumber(dataOffset)); RINOK(WriteNumber(packSizes.Size())); RINOK(WriteByte(NID::kSize)); for(int i = 0; i < packSizes.Size(); i++) RINOK(WriteNumber(packSizes[i])); RINOK(WriteHashDigests(packCRCsDefined, packCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteUnPackInfo(const CObjectVector &folders) { if (folders.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kUnPackInfo)); RINOK(WriteByte(NID::kFolder)); RINOK(WriteNumber(folders.Size())); { RINOK(WriteByte(0)); for(int i = 0; i < folders.Size(); i++) RINOK(WriteFolder(folders[i])); } RINOK(WriteByte(NID::kCodersUnPackSize)); int i; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnPackSizes.Size(); j++) RINOK(WriteNumber(folder.UnPackSizes[j])); } CRecordVector unPackCRCsDefined; CRecordVector unPackCRCs; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unPackCRCsDefined.Add(folder.UnPackCRCDefined); unPackCRCs.Add(folder.UnPackCRC); } RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteSubStreamsInfo( const CObjectVector &folders, const CRecordVector &numUnPackStreamsInFolders, const CRecordVector &unPackSizes, const CRecordVector &digestsDefined, const CRecordVector &digests) { RINOK(WriteByte(NID::kSubStreamsInfo)); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { if (numUnPackStreamsInFolders[i] != 1) { RINOK(WriteByte(NID::kNumUnPackStream)); for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) RINOK(WriteNumber(numUnPackStreamsInFolders[i])); break; } } bool needFlag = true; CNum index = 0; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++) { if (j + 1 != numUnPackStreamsInFolders[i]) { if (needFlag) RINOK(WriteByte(NID::kSize)); needFlag = false; RINOK(WriteNumber(unPackSizes[index])); } index++; } CRecordVector digestsDefined2; CRecordVector digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnPackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnPackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } RINOK(WriteHashDigests(digestsDefined2, digests2)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteTime( const CObjectVector &files, Byte type) { ///////////////////////////////////////////////// // CreationTime CBoolVector boolVector; boolVector.Reserve(files.Size()); bool thereAreDefined = false; bool allDefined = true; int i; for(i = 0; i < files.Size(); i++) { const CFileItem &item = files[i]; bool defined; switch(type) { case NID::kCreationTime: defined = item.IsCreationTimeDefined; break; case NID::kLastWriteTime: defined = item.IsLastWriteTimeDefined; break; case NID::kLastAccessTime: defined = item.IsLastAccessTimeDefined; break; default: throw 1; } boolVector.Add(defined); thereAreDefined = (thereAreDefined || defined); allDefined = (allDefined && defined); } if (!thereAreDefined) return S_OK; RINOK(WriteByte(type)); size_t dataSize = 1 + 1; dataSize += files.Size() * 8; if (allDefined) { RINOK(WriteNumber(dataSize)); WriteByte(1); } else { RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize)); WriteByte(0); RINOK(WriteBoolVector(boolVector)); } RINOK(WriteByte(0)); for(i = 0; i < files.Size(); i++) { if (boolVector[i]) { const CFileItem &item = files[i]; CArchiveFileTime timeValue; timeValue.dwLowDateTime = 0; timeValue.dwHighDateTime = 0; switch(type) { case NID::kCreationTime: timeValue = item.CreationTime; break; case NID::kLastWriteTime: timeValue = item.LastWriteTime; break; case NID::kLastAccessTime: timeValue = item.LastAccessTime; break; } RINOK(WriteUInt32(timeValue.dwLowDateTime)); RINOK(WriteUInt32(timeValue.dwHighDateTime)); } } return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector &packSizes, CObjectVector &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnPackCRCDefined = true; folderItem.UnPackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector &packSizes, CObjectVector &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } static void WriteUInt32ToBuffer(Byte *data, UInt32 value) { for (int i = 0; i < 4; i++) { *data++ = (Byte)value; value >>= 8; } } static void WriteUInt64ToBuffer(Byte *data, UInt64 value) { for (int i = 0; i < 8; i++) { *data++ = (Byte)value; value >>= 8; } } HRESULT COutArchive::WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; ///////////////////////////////// // Names CNum numDefinedNames = 0; size_t namesDataSize = 0; for(i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; if (!name.IsEmpty()) numDefinedNames++; namesDataSize += (name.Length() + 1) * 2; } CByteBuffer namesData; if (numDefinedNames > 0) { namesData.SetCapacity((size_t)namesDataSize); size_t pos = 0; for(int i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; for (int t = 0; t < name.Length(); t++) { wchar_t c = name[t]; namesData[pos++] = Byte(c); namesData[pos++] = Byte(c >> 8); } namesData[pos++] = 0; namesData[pos++] = 0; } } ///////////////////////////////// // Write Attributes CBoolVector attributesBoolVector; attributesBoolVector.Reserve(database.Files.Size()); int numDefinedAttributes = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].AreAttributesDefined; attributesBoolVector.Add(defined); if (defined) numDefinedAttributes++; } CByteBuffer attributesData; if (numDefinedAttributes > 0) { attributesData.SetCapacity(numDefinedAttributes * 4); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.AreAttributesDefined) { WriteUInt32ToBuffer(attributesData + pos, file.Attributes); pos += 4; } } } ///////////////////////////////// // Write StartPos CBoolVector startsBoolVector; startsBoolVector.Reserve(database.Files.Size()); int numDefinedStarts = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].IsStartPosDefined; startsBoolVector.Add(defined); if (defined) numDefinedStarts++; } CByteBuffer startsData; if (numDefinedStarts > 0) { startsData.SetCapacity(numDefinedStarts * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsStartPosDefined) { WriteUInt64ToBuffer(startsData + pos, file.StartPos); pos += 8; } } } ///////////////////////////////// // Write Last Write Time // /* CNum numDefinedLastWriteTimes = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].IsLastWriteTimeDefined) numDefinedLastWriteTimes++; if (numDefinedLastWriteTimes > 0) { CByteBuffer lastWriteTimeData; lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsLastWriteTimeDefined) { WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime); pos += 4; WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime); pos += 4; } } } // */ UInt64 packedSize = 0; for(i = 0; i < database.PackSizes.Size(); i++) packedSize += database.PackSizes[i]; headerOffset = packedSize; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; RINOK(WriteByte(NID::kHeader)); // Archive Properties if (database.Folders.Size() > 0) { RINOK(WriteByte(NID::kMainStreamsInfo)); RINOK(WritePackInfo(0, database.PackSizes, database.PackCRCsDefined, database.PackCRCs)); RINOK(WriteUnPackInfo(database.Folders)); CRecordVector unPackSizes; CRecordVector digestsDefined; CRecordVector digests; for (i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) continue; unPackSizes.Add(file.UnPackSize); digestsDefined.Add(file.IsFileCRCDefined); digests.Add(file.FileCRC); } RINOK(WriteSubStreamsInfo( database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests)); RINOK(WriteByte(NID::kEnd)); } if (database.Files.IsEmpty()) { RINOK(WriteByte(NID::kEnd)); return _outByte.Flush(); } RINOK(WriteByte(NID::kFilesInfo)); RINOK(WriteNumber(database.Files.Size())); CBoolVector emptyStreamVector; emptyStreamVector.Reserve(database.Files.Size()); int numEmptyStreams = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { RINOK(WriteByte(NID::kEmptyStream)); RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyStreamVector)); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDirectory); if (!file.IsDirectory) numEmptyFiles++; antiVector.Add(file.IsAnti); if (file.IsAnti) numAntiItems++; } } if (numEmptyFiles > 0) { RINOK(WriteByte(NID::kEmptyFile)); RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyFileVector)); } if (numAntiItems > 0) { RINOK(WriteByte(NID::kAnti)); RINOK(WriteNumber((antiVector.Size() + 7) / 8)); RINOK(WriteBoolVector(antiVector)); } } if (numDefinedNames > 0) { ///////////////////////////////////////////////// RINOK(WriteByte(NID::kName)); { RINOK(WriteNumber(1 + namesData.GetCapacity())); RINOK(WriteByte(0)); RINOK(WriteBytes(namesData)); } } if (headerOptions.WriteCreated) { RINOK(WriteTime(database.Files, NID::kCreationTime)); } if (headerOptions.WriteModified) { RINOK(WriteTime(database.Files, NID::kLastWriteTime)); } if (headerOptions.WriteAccessed) { RINOK(WriteTime(database.Files, NID::kLastAccessTime)); } if (numDefinedAttributes > 0) { RINOK(WriteByte(NID::kWinAttributes)); size_t size = 2; if (numDefinedAttributes != database.Files.Size()) size += (attributesBoolVector.Size() + 7) / 8 + 1; size += attributesData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedAttributes == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(attributesBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(attributesData)); } } if (numDefinedStarts > 0) { RINOK(WriteByte(NID::kStartPos)); size_t size = 2; if (numDefinedStarts != database.Files.Size()) size += (startsBoolVector.Size() + 7) / 8 + 1; size += startsData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedStarts == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(startsBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(startsData)); } } RINOK(WriteByte(NID::kEnd)); // for files RINOK(WriteByte(NID::kEnd)); // for headers return _outByte.Flush(); } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (database.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { _dynamicBuffer.Init(); _dynamicMode = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) _dynamicMode = true; RINOK(WriteHeader(database, headerOptions, headerOffset)); if (_dynamicMode) { CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector packSizes; CObjectVector folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, _dynamicBuffer, _dynamicBuffer.GetSize(), packSizes, folders)); _dynamicMode = false; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; if (folders.Size() == 0) throw 1; RINOK(WriteID(NID::kEncodedHeader)); RINOK(WritePackInfo(headerOffset, packSizes, CRecordVector(), CRecordVector())); RINOK(WriteUnPackInfo(folders)); RINOK(WriteByte(NID::kEnd)); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; RINOK(_outByte.Flush()); } headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" #include "../../../Common/DynamicBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _pos = 0; _data = data; _size = size; } HRESULT Write(const void *data, size_t size) { if (_pos + size > _size) return E_FAIL; memmove(_data + _pos, data, size); _pos += size; return S_OK; } }; class CWriteDynamicBuffer { CByteDynamicBuffer _buffer; size_t _pos; public: CWriteDynamicBuffer(): _pos(0) {} void Init() { _pos = 0; } void Write(const void *data, size_t size) { if (_pos + size > _buffer.GetCapacity()) _buffer.EnsureCapacity(_pos + size); memmove(((Byte *)_buffer) +_pos, data, size); _pos += size; } operator Byte *() { return (Byte *)_buffer; }; operator const Byte *() const { return (const Byte *)_buffer; }; size_t GetSize() const { return _pos; } }; struct CHeaderOptions { // bool UseAdditionalHeaderStreams; bool CompressMainHeader; bool WriteModified; bool WriteCreated; bool WriteAccessed; CHeaderOptions(): // UseAdditionalHeaderStreams(false), CompressMainHeader(true), WriteModified(true), WriteCreated(false), WriteAccessed(false) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); } HRESULT WriteDirectUInt32(UInt32 value); HRESULT WriteDirectUInt64(UInt64 value); HRESULT WriteBytes(const void *data, size_t size); HRESULT WriteBytes(const CByteBuffer &data); HRESULT WriteByte(Byte b); HRESULT WriteUInt32(UInt32 value); HRESULT WriteNumber(UInt64 value); HRESULT WriteID(UInt64 value) { return WriteNumber(value); } HRESULT WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); HRESULT WriteBoolVector(const CBoolVector &boolVector); HRESULT WriteHashDigests( const CRecordVector &digestsDefined, const CRecordVector &hashDigests); HRESULT WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CRecordVector &packCRCsDefined, const CRecordVector &packCRCs); HRESULT WriteUnPackInfo(const CObjectVector &folders); HRESULT WriteSubStreamsInfo( const CObjectVector &folders, const CRecordVector &numUnPackStreamsInFolders, const CRecordVector &unPackSizes, const CRecordVector &digestsDefined, const CRecordVector &hashDigests); /* HRESULT WriteStreamsInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CRecordVector &packCRCsDefined, const CRecordVector &packCRCs, bool externalFolders, UInt64 externalFoldersStreamIndex, const CObjectVector &folders, const CRecordVector &numUnPackStreamsInFolders, const CRecordVector &unPackSizes, const CRecordVector &digestsDefined, const CRecordVector &hashDigests); */ HRESULT WriteTime(const CObjectVector &files, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector &packSizes, CObjectVector &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector &packSizes, CObjectVector &folders); HRESULT WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _mainMode; bool _dynamicMode; bool _countMode; size_t _countSize; COutBuffer _outByte; CWriteBufferLoc _outByte2; CWriteDynamicBuffer _dynamicBuffer; UInt32 _crc; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME}, { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME}, { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, // { 97, NULL, kpidSolid, VT_BOOL}, #ifndef _SFX { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector &src, CRecordVector &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; #endif CRecordVector fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr _stream; CMyComPtr _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // UpdateMain.cpp #include "StdAfx.h" #include "7zUpdate.h" #include "7zFolderInStream.h" #include "7zEncode.h" #include "7zHandler.h" #include "7zOut.h" #include "../../Compress/Copy/CopyCoder.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h" #include "../Common/ItemNameUtils.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Properties, c2.Properties); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnPackStreamsVector[i1], db.NumUnPackStreamsVector[i2])); if (db.NumUnPackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector &updateItems = *(const CObjectVector *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { UInt32 Index; const CUpdateItem *UpdateItem; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType): Index(index), UpdateItem(&updateItem), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(updateItem.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = updateItem.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = updateItem.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = updateItem.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined) RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kMatchFinderForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = kDictionaryForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Properties.Add(property); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector &updateItems, CObjectVector &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (!updateItem.NewData) continue; if (!updateItem.HasStream()) continue; if (useFilters) { const UString name = updateItem.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &updateItem, CFileItem &file) { file.Name = NItemName::MakeLegalName(updateItem.Name); if (updateItem.AttributesAreDefined) file.SetAttributes(updateItem.Attributes); if (updateItem.IsCreationTimeDefined) file.SetCreationTime(updateItem.CreationTime); if (updateItem.IsLastWriteTimeDefined) file.SetLastWriteTime(updateItem.LastWriteTime); if (updateItem.IsLastAccessTimeDefined) file.SetLastAccessTime(updateItem.LastAccessTime); file.UnPackSize = updateItem.Size; file.IsDirectory = updateItem.IsDirectory; file.IsAnti = updateItem.IsAnti; file.HasStream = updateItem.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = database != 0 ? database->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector fileIndexToUpdateIndexMap; if (database != 0) { fileIndexToUpdateIndexMap.Reserve(database->Files.Size()); for (int i = 0; i < database->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector folderRefs; if (database != 0) { for(i = 0; i < database->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnPackStreams = database->NumUnPackStreamsVector[i]; for (CNum fileIndex = database->FolderStartFileIndex[i]; indexInFolder < numUnPackStreams; fileIndex++) { if (database->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnPackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)database); } CArchiveDatabase newDatabase; //////////////////////////// COutArchive archive; RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += database->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { complexity += updateItem.Size; if (numSolidFiles == 1) { if (updateItem.Size > inSizeForReduce) inSizeForReduce = updateItem.Size; } else inSizeForReduce += updateItem.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = database->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, database->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = database->Folders[folderIndex]; CNum startIndex = database->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex]; newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); CNum indexInFolder = 0; for (CNum fi = database->FolderStartFileIndex[folderIndex]; indexInFolder < numUnPackStreams; fi++) { CFileItem file = database->Files[fi]; if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &updateItem = updateItems[updateIndex]; if (updateItem.NewProperties) { CFileItem file2; FromUpdateItemToFileItem(updateItem, file2); file2.UnPackSize = file.UnPackSize; file2.FileCRC = file.FileCRC; file2.IsFileCRCDefined = file.IsFileCRCDefined; file2.HasStream = file.HasStream; file = file2; } } newDatabase.Files.Add(file); } } } ///////////////////////////////////////// // Compress New Files CObjectVector groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &updateItem = updateItems[index]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database.Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]]; totalSize += updateItem.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = updateItem.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnPackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnPackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &updateItem = updateItems[indices[i + subIndex]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.FileCRC = inStreamSpec->CRCs[subIndex]; file.UnPackSize = inStreamSpec->Sizes[subIndex]; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { file.IsFileCRCDefined = false; file.HasStream = false; } newDatabase.Files.Add(file); } // numUnPackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); i += numSubFiles; } } { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { if (updateItem.HasStream()) continue; } else if (updateItem.IndexInArchive != -1) if (database->Files[updateItem.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for(i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &updateItem = updateItems[emptyRefs[i]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; newDatabase.Files.Add(file); } } /* if (newDatabase.Files.Size() != updateItems.Size()) return E_FAIL; */ return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); } #ifdef _7Z_VOL static const UInt64 k_Copy = 0x0; static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options) { CCoderInfo coder; coder.NumInStreams = coder.NumOutStreams = 1; coder.MethodID = k_Copy; CFolder folder; folder.Coders.Add(coder); folder.PackStreams.Add(0); CNum numUnPackStreams = 0; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { throw 1; file.IsFileCRCDefined = false; file.HasStream = false; } folder.UnPackSizes.Add(file.UnPackSize); CArchiveDatabase newDatabase; newDatabase.Files.Add(file); newDatabase.Folders.Add(folder); newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); newDatabase.PackSizes.Add(file.UnPackSize); newDatabase.PackCRCsDefined.Add(false); newDatabase.PackCRCs.Add(file.FileCRC); return archive.WriteDatabase(newDatabase, options.HeaderMethod, false, false); } HRESULT UpdateVolume( IInStream *inStream, const CArchiveDatabaseEx *database, CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { if (updateItems.Size() != 1) return E_NOTIMPL; CMyComPtr volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; CMyComPtr fileStream; HRESULT result = updateCallback->GetStream(0, &fileStream); if (result != S_OK && result != S_FALSE) return result; if (result == S_FALSE) return E_FAIL; CFileItem file; const CUpdateItem &updateItem = updateItems[0]; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; UInt64 complexity = 0; file.IsStartPosDefined = true; file.StartPos = 0; for (UInt64 volumeIndex = 0; true; volumeIndex++) { UInt64 volSize; RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize)); UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true); CMyComPtr volumeStream; RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream)); COutArchive archive; RINOK(archive.Create(volumeStream, true)); RINOK(archive.SkeepPrefixArchiveHeader()); CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC; CMyComPtr inCrcStream = inCrcStreamSpec; inCrcStreamSpec->Init(fileStream); RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity)); file.UnPackSize = inCrcStreamSpec->GetSize(); if (file.UnPackSize == 0) break; file.FileCRC = inCrcStreamSpec->GetCRC(); RINOK(WriteVolumeHeader(archive, file, options)); file.StartPos += file.UnPackSize; if (file.UnPackSize < pureSize) break; } return S_OK; } class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (!_volumeStream) { RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize)); RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream)); _volIndex++; _curPos = 0; RINOK(_archive.Create(_volumeStream, true)); RINOK(_archive.SkeepPrefixArchiveHeader()); _crc.Init(); continue; } UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length()); UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos); _crc.Update(data, curSize); UInt32 realProcessed; RINOK(_volumeStream->Write(data, curSize, &realProcessed)) data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _curPos += realProcessed; if (realProcessed != curSize && realProcessed == 0) return E_FAIL; if (_curPos == pureSize) { RINOK(Flush()); } } return S_OK; } #endif HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { #ifdef _7Z_VOL if (seqOutStream) #endif return Update2( EXTERNAL_CODECS_LOC_VARS inStream, database, updateItems, seqOutStream, updateCallback, options); #ifdef _7Z_VOL if (options.VolumeMode) return UpdateVolume(inStream, database, updateItems, seqOutStream, updateCallback, options); COutVolumeStream *volStreamSpec = new COutVolumeStream; CMyComPtr volStream = volStreamSpec; CMyComPtr volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; volStreamSpec->Init(volumeCallback, L"a.7z"); volStreamSpec->_options = options; RINOK(Update2(inStream, database, updateItems, volStream, updateCallback, options)); return volStreamSpec->Flush(); #endif } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { bool NewData; bool NewProperties; int IndexInArchive; int IndexInClient; UInt32 Attributes; FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt64 Size; UString Name; bool IsAnti; bool IsDirectory; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool AttributesAreDefined; bool HasStream() const { return !IsDirectory && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), AttributesAreDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false) {} void SetDirectoryStatusFromAttributes() { IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (UInt32 i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, CRecordVector &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector Coders; CRecordVector BindPairs; CRecordVector InStreams; CRecordVector OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector _srcInToDestOutMap; CRecordVector _srcOutToDestInMap; CRecordVector _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr Coder; CMyComPtr Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector InSizes; CRecordVector OutSizes; CRecordVector InSizePointers; CRecordVector OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector &sizes, CRecordVector &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL) return result; } for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr > InStreams; CObjectVector< CMyComPtr > OutStreams; CRecordVector InStreamPointers; CRecordVector OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOutCommon.cpp #include "StdAfx.h" #include "HandlerOut.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ParseProperties.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Properties.Size(); j++) if (oneMethodInfo.Properties[j].Id == propID) return; CProp property; property.Id = propID; property.Value = value; oneMethodInfo.Properties.Add(property); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp property; if ( name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); if (name.CompareNoCase(L"D") == 0) property.Id = NCoderPropID::kDictionarySize; else property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { bool res; if (StringToBool(s, res)) { if (res) InitSolid(); else _numSolidFiles = 1; return S_OK; } UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: InitSolid(); return S_OK; case VT_BSTR: return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeaders = false; WriteModified = true; WriteCreated = false; WriteAccessed = false; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) return SetBoolProperty(_encryptHeaders, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteModified, value); if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCreated, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteAccessed, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp property; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); property.Id = NCoderPropID::kDictionarySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } } return S_OK; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../Common/MethodProps.h" #include "../../Common/CreateCoder.h" namespace NArchive { struct COneMethodInfo { CObjectVector Properties; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeaders; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; DECL_EXTERNAL_CODECS_VARS }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr Stream; UInt64 Pos; UInt64 Size; }; CObjectVector Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr Stream; UInt64 Size; UInt64 Pos; }; CObjectVector Streams; public: CMyComPtr VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUTSTREAMWITHCRC_H #define __OUTSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) PURE; // GetStream OUT: S_OK - OK, S_FALSE - skeep this file STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE; }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, // 1 - new data, 0 - old data Int32 *newProperties, // 1 - new properties, 0 - old properties UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter ) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE; }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.h # End Source File # End Group # Begin Group "Copy" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyRegister.cpp # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMARegister.cpp # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(C_OBJS) \ $(C_BRANCH_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BZIP2_OBJS) \ $(BZIP2_OPT_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(DEFLATE_OPT_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(PPMD_OPT_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &filter, CMyComPtr &coder, CMyComPtr &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &coder, CMyComPtr &coder2, bool encode) { CMyComPtr filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &coder, bool encode) { CMyComPtr filter; CMyComPtr coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &filter, bool encode) { CMyComPtr coder; CMyComPtr coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr _codecsInfo; CObjectVector _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &filter, CMyComPtr &coder, CMyComPtr &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &coder, CMyComPtr &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include #include #include #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return lastError; #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return File.SetTime(creationTime, lastAccessTime, lastWriteTime); } bool SetLastWriteTime(const FILETIME *lastWriteTime) { return File.SetLastWriteTime(lastWriteTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } UInt32 processedSize = 0; RINOK(WriteStream(outStream, _buffer, size, &processedSize)); if (size != processedSize) return E_FAIL; _nowPos64 += processedSize; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { UInt32 processedSize; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize)); UInt32 endPos = bufferPos + processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } UInt32 processedSize; RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize)); if (_bufferPos != processedSize) return E_FAIL; _bufferPos = 0; } CMyComPtr flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; UInt32 processedSizeTemp; UInt32 size0 = kBufferSize - _bufferPos; // Optimize it: RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp)); _bufferPos = _bufferPos + processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr _inStream; CMyComPtr _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr _setPassword; #ifndef EXTRACT_ONLY CMyComPtr _SetCoderProperties; CMyComPtr _writeCoderProperties; // CMyComPtr _CryptoResetSalt; CMyComPtr _CryptoResetInitVector; #endif CMyComPtr _setDecoderProperties; public: CMyComPtr Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "MethodProps.h" #include "../../Common/MyCom.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProperties = method.Properties.Size(); CMyComPtr setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProperties != 0) return E_INVALIDARG; } else { CRecordVector propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties]; HRESULT res = S_OK; try { for (int i = 0; i < numProperties; i++) { const CProp &prop = method.Properties[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "MethodId.h" #include "../../Windows/PropVariant.h" #include "../../Common/MyVector.h" #include "../ICoder.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector Properties; }; struct CMethodsMode { CObjectVector Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr _progress; CMyComPtr _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { MoveMemory(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 numBytesToRead = (UInt32)(MyMin(_pos + size, _size) - _pos); memmove(data, _dataPointer + _pos, numBytesToRead); _pos += numBytesToRead; if(processedSize != NULL) *processedSize = numBytesToRead; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memmove(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 newSize = size; if (_pos + size > _size) newSize = (UInt32)(_size - _pos); memmove(_buffer + _pos, data, newSize); if(processedSize != NULL) *processedSize = newSize; _pos += newSize; if (newSize != size) return E_FAIL; return S_OK; } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } HRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); HRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARM.h" } UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARMThumb.h" } UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86_2.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "PPC.h" #include "IA64.h" #include "ARM.h" #include "ARMThumb.h" #include "SPARC.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC_B) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMThumb) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC_B, 0x02, 0x05, L"BC_PPC_B"), METHOD_ITEM(BC_IA64, 0x04, 1, L"BC_IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"BC_ARM"), METHOD_ITEM(BC_ARMThumb,0x07, 1, L"BC_ARMThumb"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"BC_SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" extern "C" { #include "../../../../C/Compress/Branch/BranchIA64.h" } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchPPC.h" } UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchSPARC.h" } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" extern "C" { #include "../../../../C/Alloc.h" } namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h ================================================ // ByteSwap.h #ifndef __BYTESWAP_H #define __BYTESWAP_H #include "../../ICoder.h" #include "Common/MyCom.h" // {23170F69-40C1-278B-0203-020000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap2, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); // {23170F69-40C1-278B-0203-040000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap4, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00); class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (UInt32 i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/Alloc.h" } #include "CopyCoder.h" #include "../../Common/StreamUtils.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Copy/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPYCODER_H #define __COMPRESS_COPYCODER_H #include "../../ICoder.h" #include "../../../Common/MyCom.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Copy/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/Copy/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS typedef COutBufferException CLZOutWindowException; #endif class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (distance >= _pos) { if (!_overDict || distance >= _bufferSize) return false; pos += _bufferSize; } if (_limitPos - _pos > len && _bufferSize - pos > len) { const Byte *src = _buffer + pos; Byte *dest = _buffer + _pos; _pos += len; do *dest++ = *src++; while(--len != 0); } else do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); for (;;) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" extern "C" { #include "../../../../C/Alloc.h" } #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include #else #include #endif #endif #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // extern "C" { #include "../../../../C/7zCrc.h" } // #define SHOW_STAT namespace NCompress { namespace NLZMA { // struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit; const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = kNumLogBits * 2; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; #endif void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < kNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < kNumLowSymbols + kNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); } for (; i < numSymbols; i++) prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _matchFinderCycles(0), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { MatchFinder_Construct(&_matchFinderBase); // _maxMode = false; _fastMode = false; #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&_matchFinderMt); _matchFinderMt.MatchFinder = &_matchFinderBase; #endif } static void *SzAlloc(size_t size) { return BigAlloc(size); } static void SzFree(void *address) { BigFree(address); } ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::~CEncoder() { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc); #endif MatchFinder_Free(&_matchFinderBase, &g_Alloc); } static const UInt32 kBigHashDicLimit = (UInt32)1 << 24; HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; bool btMode = (_matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT _mtMode = (_multiThread && !_fastMode && btMode); #endif if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit); UInt32 numCycles = 16 + (_numFastBytes >> 1); if (!btMode) numCycles >>= 1; if (_matchFinderCycles != 0) numCycles = _matchFinderCycles; _matchFinderBase.cutValue = numCycles; #ifdef COMPRESS_MF_MT if (_mtMode) { RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)); _matchFinderObj = &_matchFinderMt; MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder); } else #endif { if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)) return E_OUTOFMEMORY; _matchFinderObj = &_matchFinderBase; MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder); } return S_OK; } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); /* int skipModeBitsLoc = 0; if (c == L'D') { skipModeBitsLoc = 2; c = GetUpperChar(*s++); } */ if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; // *skipModeBits = skipModeBitsLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kMatchFinderCycles: { if (prop.vt != VT_UI4) return E_INVALIDARG; _matchFinderCycles = prop.ulVal; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); // _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; } case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kNumThreads: { if (prop.vt != VT_UI4) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.ulVal > 1) ? True : False; if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } #ifdef SHOW_STAT static int ttt = 0; #endif void CEncoder::MovePos(UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { _additionalOffset += num; _matchFinder.Skip(_matchFinderObj, num); } } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; const Byte *data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = *data; Byte matchByte = *(data - (reps[0] + 1)); if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)-1; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while(--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > matchDistances[offs]) offs += 2; for(; ; len++) { UInt32 distance = matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); COptimal &optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + kNumRepDistances; optimum.Prev1IsChar = false; } if (len == matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; for (;;) { cur++; if(cur == lenEnd) { return Backward(backRes, cur); } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 newLen, numDistancePairs; newLen = ReadMatchDistances(numDistancePairs); if(newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; const Byte currentByte = *data; const Byte matchByte = *(data - (reps[0] + 1)); UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } /* if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) // speed optimization { // try Literal + rep0 const Byte *data2 = data - (reps[0] + 1); UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 lenTestTemp = lenTest; UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while(startLen > matchDistances[offs]) offs += 2; UInt32 curBack = matchDistances[offs + 1]; UInt32 posSlot = GetPosSlot2(curBack); for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice; UInt32 lenToPosState = GetLenToPosState(lenTest); if (curBack < kNumFullDistances) curAndLenPrice += _distancesPrices[lenToPosState][curBack]; else curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (/*_maxMode && */lenTest == matchDistances[offs]) { // Try Match + Literal + Rep0 const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (posStateNext + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; curBack = matchDistances[offs + 1]; if (curBack >= kNumFullDistances) posSlot = GetPosSlot2(curBack); } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { return ((bigDist >> 7) > smallDist); } UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs) { UInt32 lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2); if (ttt >= 61994) ttt = ttt; ttt++; for (UInt32 i = 0; i < numDistancePairs; i += 2) printf("%2d %6d | ", _matchDistances[i], _matchDistances[i + 1]); #endif if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) { UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1; const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; UInt32 distance = _matchDistances[numDistancePairs - 1] + 1; if (numAvail > kMatchMaxLen) numAvail = kMatchMaxLen; const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } _additionalOffset++; return lenRes; } UInt32 CEncoder::GetOptimumFast(UInt32 &backRes) { UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if(len >= _numFastBytes) { backRes = i; MovePos(len - 1); return len; } repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } UInt32 backMain = 0; // for GCC if (lenMain >= 2) { backMain = matchDistances[numDistancePairs - 1]; while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) { if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) break; numDistancePairs -= 2; lenMain = matchDistances[numDistancePairs - 2]; backMain = matchDistances[numDistancePairs - 1]; } if (lenMain == 2 && backMain >= 0x80) lenMain = 1; } if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2 && numAvailableBytes > 2) { numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); _longestMatchLength = ReadMatchDistances(_numDistancePairs); if (_longestMatchLength >= 2) { UInt32 newDistance = matchDistances[_numDistancePairs - 1]; if (_longestMatchLength >= lenMain && newDistance < backMain || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[1] != data2[1] || data[2] != data2[2]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if (len + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } backRes = backMain + kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = UInt32(-1); return 1; } HRESULT CEncoder::Flush(UInt32 nowPos) { // ReleaseMFStream(); if (_matchFinderBase.result != SZ_OK) return _matchFinderBase.result; WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { // _needReleaseMFStream = false; #ifdef COMPRESS_MF_MT #ifdef USE_ALLOCA alloca(0x300); #endif #endif CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); for (;;) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) break; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } return S_OK; } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; return S_OK; } static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize) { return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize); } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { _seqInStream.RealStream = _inStream; _seqInStream.SeqInStream.Read = MyRead; _matchFinderBase.stream = &_seqInStream.SeqInStream; _matchFinder.Init(_matchFinderObj); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return _matchFinderBase.result; _finished = true; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush((UInt32)nowPos64); UInt32 len, numDistancePairs; len = ReadMatchDistances(numDistancePairs); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } UInt32 nowPos32 = (UInt32)nowPos64; UInt32 progressPosValuePrev = nowPos32; if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); for (;;) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos, len; if (_fastMode) len = GetOptimumFast(pos); else len = GetOptimum(nowPos32, pos); UInt32 posState = nowPos32 & _posStateMask; if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); if(_state.IsCharState()) subCoder->Encode(&_rangeEncoder, curByte); else { Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); } else { UInt32 distance = _repDistances[pos]; _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); if (pos == 3) _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; } _repDistances[1] = _repDistances[0]; _repDistances[0] = distance; } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); _state.UpdateRep(); } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); _alignPriceCount++; } } _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; _repDistances[1] = _repDistances[0]; _repDistances[0] = pos; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos32 += len; if (_additionalOffset == 0) { if (!_fastMode) { if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= kAlignTableSize) FillAlignPrices(); } if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); if (nowPos32 - progressPosValuePrev >= (1 << 14)) { nowPos64 += nowPos32 - progressPosValuePrev; *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); _finished = false; *finished = 0; return _matchFinderBase.result; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillDistancesPrices() { UInt32 tempPrices[kNumFullDistances]; for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; NRangeCoder::CBitTreeEncoder &encoder = _posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] = encoder.GetPrice(posSlot); for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); UInt32 *distancesPrices = _distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/Compress/Lz/MatchFinder.h" #ifdef COMPRESS_MF_MT #include "../../../../C/Compress/Lz/MatchFinderMt.h" #endif } #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; // #define LZMA_LOG_BRANCH #if _MSC_VER >= 1400 // Must give gain in core 2. but slower ~2% on k8. // #define LZMA_LOG_BSR #endif #ifndef LZMA_LOG_BSR static const int kNumLogBits = 13; // don't change it ! extern Byte g_FastPos[]; #endif inline UInt32 GetPosSlot(UInt32 pos) { #ifdef LZMA_LOG_BSR if (pos < 2) return pos; unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else if (pos < (1 << kNumLogBits)) return g_FastPos[pos]; if (pos < (1 << (kNumLogBits * 2 - 1))) return g_FastPos[pos >> (kNumLogBits - 1)] + (kNumLogBits - 1) * 2; return g_FastPos[pos >> (kNumLogBits - 1) * 2] + (kNumLogBits - 1) * 4; #endif } inline UInt32 GetPosSlot2(UInt32 pos) { #ifdef LZMA_LOG_BSR unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else #ifdef LZMA_LOG_BRANCH if (pos < (1 << (kNumLogBits + 6))) return g_FastPos[pos >> 6] + 12; if (pos < (1 << (kNumLogBits * 2 + 5))) return g_FastPos[pos >> (kNumLogBits + 5)] + (kNumLogBits + 5) * 2; return g_FastPos[pos >> (kNumLogBits * 2 + 4)] + (kNumLogBits * 2 + 4) * 2; #else // it's faster with VC6-32bit. UInt32 s = 6 + ((kNumLogBits - 1) & (UInt32)((Int32)(((1 << (kNumLogBits + 6)) - 1) - pos) >> 31)); return g_FastPos[pos >> s] + (s * 2); #endif #endif } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices[posState]); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) { CEncoder::Encode(rangeEncoder, symbol, posState); if (updatePrice) if (--_counters[posState] == 0) UpdateTable(posState); } }; } typedef struct _CSeqInStream { ISeqInStream SeqInStream; CMyComPtr RealStream; } CSeqInStream; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { NRangeCoder::CEncoder _rangeEncoder; IMatchFinder _matchFinder; void *_matchFinderObj; #ifdef COMPRESS_MF_MT Bool _multiThread; Bool _mtMode; CMatchFinderMt _matchFinderMt; #endif CMatchFinder _matchFinderBase; #ifdef COMPRESS_MF_MT Byte _pad1[kMtCacheLineDummy]; #endif COptimal _optimum[kNumOpts]; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; bool _fastMode; // bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _matchPriceCount; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; CSeqInStream _seqInStream; UInt32 _matchFinderCycles; // int _numSkip bool _writeEndMark; bool _needReleaseMFStream; void ReleaseMatchFinder() { _matchFinder.Init = 0; _seqInStream.RealStream.Release(); } void ReleaseMFStream() { if (_matchFinderObj && _needReleaseMFStream) { #ifdef COMPRESS_MF_MT if (_mtMode) MatchFinderMt_ReleaseStream(&_matchFinderMt); #endif _needReleaseMFStream = false; } _seqInStream.RealStream.Release(); } UInt32 ReadMatchDistances(UInt32 &numDistancePairs); void MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const { UInt32 price; if(repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + GetPureRepPrice(repIndex, state, posState); } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); UInt32 GetOptimum(UInt32 position, UInt32 &backRes); UInt32 GetOptimumFast(UInt32 &backRes); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "LZMADecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CDecoder); } #ifndef EXTRACT_ONLY #include "LZMAEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C-Lz" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include #include #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBenchCon.h" #include "LzmaRam.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif #include "../../MyVersion.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kMatchFinderCycles, kLitContext, kLitPos, kPosBits, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA inputFile outputFile [...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary - [0,30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = (UInt32)-1; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dictionary); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 1; UInt32 numFastBytes = 128; UInt32 matchFinderCycles = 16 + numFastBytes / 2; bool matchFinderCyclesDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs; if (matchFinderCyclesDefined) if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionary; properties[1].ulVal = (UInt32)posStateBits; properties[2].ulVal = (UInt32)litContextBits; properties[3].ulVal = (UInt32)litPosBits; properties[4].ulVal = (UInt32)algorithm; properties[5].ulVal = (UInt32)numFastBytes; properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; properties[8].vt = VT_UI4; properties[8].ulVal = (UInt32)numThreads; // it must be last in property list properties[9].vt = VT_UI4; properties[9].ulVal = (UInt32)matchFinderCycles; int numProps = kNumPropsMax; if (!matchFinderCyclesDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include #ifdef USE_POSIX_TIME2 #include #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include #else #include #endif #endif extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/7zCrc.h" } #include "../../../Common/MyCom.h" #include "../../ICoder.h" #ifdef BENCH_MT #include "../../../Windows/Thread.h" #include "../../../Windows/Synchronization.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #else #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); // UInt64 numCommandsForOne = 1000 + ((t * t * 7) >> (2 * kSubBits)); // AMD K8 UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); // Intel Core2 UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { // UInt64 numCommands = (inSize * 216 + outSize * 14) * numIterations; // AMD K8 UInt64 numCommands = (inSize * 220 + outSize * 8) * numIterations; // Intel Core2 return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr inStream = inStreamSpec; CMyComPtr &decoder = decoders[decoderIndex]; CMyComPtr compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLZMA::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLZMA::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { size_t allocaSize = ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF; HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , allocaSize #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { if (size > (Size - Pos)) size = (UInt32)(Size - Pos); for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZ_RAM_E_FAIL (1) #define SZ_RAM_E_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZ_RAM_E_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1); } size_t minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZ_RAM_E_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZ_RAM_E_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZ_RAM_E_OUTOFMEMORY; } #endif } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../../../../C/Compress/Lzma/LzmaDecode.h" #include "../../../../C/Compress/Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(outBuffer, (SizeT)outSizeProcessedLoc, 0, &x86State, 0); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/comp.cc ================================================ /* * Copyright (C) 2006-2007 Junjiro Okajima * Copyright (C) 2006-2007 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: comp.cc,v 1.3 2007-11-13 13:27:23 jro Exp $ */ // extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp #include #include #include #include #include "StdAfx.h" #include "../../../Common/MyInitGuid.h" //#include "../../../Common/MyWindows.h" #include "../../../Common/StringConvert.h" //#include "../../../Common/StringToInt.h" //#include "../../Common/StreamUtils.h" #include "../LZMA/LZMAEncoder.h" #include #include #include "sqlzma.h" ////////////////////////////////////////////////////////////////////// class CMemoryStream { protected: Bytef *m_data; UInt64 m_limit; UInt64 m_pos; public: CMemoryStream(Bytef *data, UInt64 size) : m_data(data), m_limit(size), m_pos(0) {} virtual ~CMemoryStream() {} }; class CInMemoryStream : public CMemoryStream, public IInStream, public CMyUnknownImp { //protected: CMyComPtr m_stream; public: MY_UNKNOWN_IMP1(IInStream); CInMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~CInMemoryStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { UInt64 room = m_limit - m_pos; if (size > room) size = room; if (size) { memcpy(data, m_data + m_pos, size); m_pos += size; } if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } }; class COutMemoryStream : public CMemoryStream, public IOutStream, public CMyUnknownImp { //protected: CMyComPtr m_stream; public: MY_UNKNOWN_IMP1(IOutStream); COutMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~COutMemoryStream() {} UInt32 GetSize() {return m_pos;} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (m_pos + size > m_limit) return -ENOSPC; memcpy(m_data + m_pos, data, size); m_pos += size; if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } STDMETHOD(SetSize)(Int64 newSize) { assert(0); return E_NOTIMPL; } }; ////////////////////////////////////////////////////////////////////// static int LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, struct sqlzma_opts *opts, uLong *total_out) { int err; HRESULT res; const Byte a[] = { avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, 0, 0, 0, 0 }; NCompress::NLZMA::CEncoder encoderSpec; CMyComPtr encoder = &encoderSpec; encoder->AddRef(); CInMemoryStream inStreamSpec(next_in, avail_in); CMyComPtr inStream = &inStreamSpec; inStream->AddRef(); COutMemoryStream outStreamSpec(next_out, avail_out); CMyComPtr outStream = &outStreamSpec; outStream->AddRef(); // these values are dpending upon is_lzma() macro in sqlzma.h const UInt32 dictionary = opts->dicsize; //fprintf(stderr, "dic %u\n", dictionary); const UString mf = L"BT4"; const UInt32 posStateBits = 2; const UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data const UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data //const UInt32 algorithm = 2; const UInt32 algorithm = 1; const UInt32 numFastBytes = 128; const UInt32 matchFinderCycles = 16 + numFastBytes / 2; //const bool matchFinderCyclesDefined = false; const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_FALSE; // EOS properties[8].vt = VT_UI4; properties[8].ulVal = 1; // numThreads properties[9].vt = VT_UI4; properties[9].ulVal = UInt32(matchFinderCycles); err = -EINVAL; res = encoderSpec.SetCoderProperties(propIDs, properties, kNumPropsMax - 1); if (res) goto out; res = encoderSpec.WriteCoderProperties(outStream); if (res) goto out; UInt32 r; res = outStream->Write(a, sizeof(a), &r); if (res || r != sizeof(a)) goto out; err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); if (err) goto out; *total_out = outStreamSpec.GetSize(); out: return err; } ////////////////////////////////////////////////////////////////////// #define Failure(p) do { \ fprintf(stderr, "%s:%d: please report to jro " \ "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ __func__, __LINE__, \ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ abort(); \ } while(0) extern "C" int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out) { int err; Bytef *p = next_out; uInt l = avail_out; stream->next_in = next_in; stream->avail_in = avail_in; stream->next_out = p; stream->avail_out = l; err = deflate(stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) goto out_err; if (avail_in < stream->total_out) return err; if (is_lzma(*p)) Failure(p); if (opts->try_lzma) { unsigned char a[stream->total_out]; uLong processed; memcpy(a, p, stream->total_out); // malloc family in glibc and stdc++ seems to be thread-safe err = LzmaCompress(next_in, avail_in, p, l, opts, &processed); if (!err && processed <= stream->total_out) { if (!is_lzma(*next_out)) Failure(next_out); stream->total_out = processed; err = Z_STREAM_END; } else { //puts("by zlib"); memcpy(p, a, stream->total_out); err = Z_STREAM_END; } } return err; out_err: fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); return err; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LIBS = $(LIBS) oleaut32.lib user32.lib !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -W4 -Wp64 -DUNICODE -D_UNICODE !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../../../../C/Compress/Lzma/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../../../../C/Compress/Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaRam.o \ LZMADecoder.o \ LZMAEncoder.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ BranchX86.o \ MatchFinder.o \ LzmaDecode.o \ LzmaRamDecode.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c BranchX86.o: ../../../../C/Compress/Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Branch/BranchX86.c MatchFinder.o: ../../../../C/Compress/Lz/MatchFinder.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lz/MatchFinder.c LzmaDecode.o: ../../../../C/Compress/Lzma/LzmaDecode.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lzma/LzmaDecode.c LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef UseDebugFlags DebugFlags = -Wall -O0 -g -UNDEBUG endif # -pthread CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} Tgt = liblzma_r.a all: ${Tgt} RObjs = LZMAEncoder_r.o Alloc_r.o StreamUtils_r.o MatchFinder_r.o \ RangeCoderBit_r.o OutBuffer_r.o 7zCrc_r.o %_r.cc: ../LZMA/%.cpp ln $< $@ %_r.c: ../../../../C/%.c ln $< $@ %_r.c: ../../../../C/Compress/Lz/%.c ln $< $@ %_r.cc: ../../Common/%.cpp ln $< $@ %_r.cc: ../RangeCoder/%.cpp ln $< $@ LZMAEncoder_r.o: CXXFLAGS += -I../LZMA Alloc_r.o: CFLAGS += -I../../../../C StreamUtils_r.o: CXXFLAGS += -I../../Common MatchFinder_r.o: CFLAGS += -I../../../../C/Compress/Lz RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder OutBuffer_r.o: CXXFLAGS += -I../../Common 7zCrc_r.o: CFLAGS += -I../../../../C comp.o: CXXFLAGS += -I${Sqlzma} comp.o: comp.cc ${Sqlzma}/sqlzma.h liblzma_r.a: ${RObjs} comp.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) comp.o *_r.o ${Tgt} *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template class CBitEncoder: public CBitModel { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template class CBitDecoder: public CBitModel { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template class CBitTreeEncoder { CBitEncoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template class CBitTreeDecoder { CBitDecoder Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template void ReverseBitTreeEncode(CBitEncoder *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template UInt32 ReverseBitTreeDecode(CBitDecoder *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" DECL_INTERFACE(IProgress, 0, 5) { STDMETHOD(SetTotal)(UInt64 total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 57 #define MY_VER_BUILD 0 #define MY_VERSION "4.57" #define MY_7ZIP_VERSION "7-Zip 4.57" #define MY_DATE "2007-12-06" #define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/PropID.h ================================================ // Interface/PropID.h #ifndef __INTERFACE_PROPID_H #define __INTERFACE_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsFolder, kpidSize, kpidPackedSize, kpidAttributes, kpidCreationTime, kpidLastAccessTime, kpidLastWriteTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubFolders, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME UTCLastWriteTime; UInt32 Attributes; bool IsDirectory; bool AttributesAreDefined; bool UTCLastWriteTimeIsDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant)); UString fullPath; if(propVariant.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if(propVariant.vt != VT_BSTR) return E_FAIL; fullPath = propVariant.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attributes NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) { _processedFileInfo.Attributes = 0; _processedFileInfo.AttributesAreDefined = false; } else { if (propVariant.vt != VT_UI4) throw "incorrect item"; _processedFileInfo.Attributes = propVariant.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); { // Get Modified Time NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant)); _processedFileInfo.UTCLastWriteTimeIsDefined = false; switch(propVariant.vt) { case VT_EMPTY: // _processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault; break; case VT_FILETIME: _processedFileInfo.UTCLastWriteTime = propVariant.filetime; _processedFileInfo.UTCLastWriteTimeIsDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant)); bool newFileSizeDefined = (propVariant.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(propVariant); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.IsDirectory) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.UTCLastWriteTimeIsDefined) _outFileStreamSpec->SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if(newData != NULL) *newData = BoolToInt(true); if(newProperties != NULL) *newProperties = BoolToInt(true); if(indexInArchive != NULL) *indexInArchive = UInt32(-1); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = false; propVariant.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } propVariant.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if(dirItem.IsDirectory()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////////////////// // Main function int #ifdef _MSC_VER __cdecl #endif main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.CompareNoCase("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector dirItems; int i; for (i = 3; i < argc; i++) { CDirItem item; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(name, fileInfo)) { PrintString(UString(L"Can't find file") + name); return 1; } item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = name; item.FullPath = name; dirItems.Add(item); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.CompareNoCase("l") == 0) listCommand = true; else if (command.CompareNoCase("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidSize, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidPath, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include #include #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include #endif #include #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, kPassword, kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for(int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for(int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for(int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for(int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if(options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if(postString.IsEmpty()) { if(options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if(parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if(parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if(numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if(curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if(options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); CObjectVector dirItems; { UStringVector errorPaths; CRecordVector errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } UStringVector archivePaths; int i; for (i = 0; i < dirItems.Size(); i++) { const CDirItem &dirItem = dirItems[i]; if (!dirItem.IsDirectory()) archivePaths.Add(dirItem.FullPath); } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if(parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if(parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if(options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; if(parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if(updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if(options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if(options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; bool PasswordEnabled; UString Password; bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcLastWriteTimeDefault = utcLastWriteTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCreationTime, _processedFileInfo.CreationTime, _processedFileInfo.IsCreationTimeDefined)); RINOK(GetTime(index, kpidLastWriteTime, _processedFileInfo.LastWriteTime, _processedFileInfo.IsLastWriteTimeDefined)); RINOK(GetTime(index, kpidLastAccessTime, _processedFileInfo.LastAccessTime, _processedFileInfo.IsLastAccessTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDirectory) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDirectory) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDirectory) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size, fullPath, _processedFileInfo.IsLastWriteTimeDefined ? &_processedFileInfo.LastWriteTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDirectory, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDirectory) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IExtractCallBack STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr _archiveHandler; CMyComPtr _extractCallback2; CMyComPtr _compressProgress; CMyComPtr _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _encrypted; struct CProcessedFileInfo { FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt32 Attributes; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsDirectory; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcLastWriteTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteModified(true), WriteCreated(false), WriteAccessed(false), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == '\\') { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDirectory() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant propVariant; if (_subArchiveMode) { switch(propID) { case kpidName: propVariant = _subArchiveName; break; } propVariant.Detach(value); return S_OK; } switch(propID) { case kpidName: propVariant = _fileInfo.Name; break; case kpidIsFolder: propVariant = _fileInfo.IsDirectory(); break; case kpidSize: propVariant = _fileInfo.Size; break; case kpidAttributes: propVariant = (UInt32)_fileInfo.Attributes; break; case kpidLastAccessTime: propVariant = _fileInfo.LastAccessTime; break; case kpidCreationTime: propVariant = _fileInfo.CreationTime; break; case kpidLastWriteTime: propVariant = _fileInfo.LastWriteTime; break; } propVariant.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDirectory()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!Callback) return E_NOTIMPL; return Callback->CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" struct IOpenCallbackUI { virtual HRESULT CheckBreak() = 0; virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0; virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0; #ifndef _NO_CRYPTO virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0; virtual HRESULT GetPasswordIfAny(UString &password) = 0; virtual bool WasPasswordAsked() = 0; virtual void ClearPasswordWasAskedFlag() = 0; #endif }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); // IArchiveOpenVolumeCallback STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); #ifndef _NO_CRYPTO // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static const wchar_t *kEmptyFileAlias = L"[Content]"; UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; return kEmptyFileAlias; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; struct CArchiveItem { bool IsDirectory; // DWORD Attributes; // NWindows::NCOM::CPropVariant LastWriteTime; FILETIME LastWriteTime; bool SizeIsDefined; UInt64 Size; UString Name; bool Censored; int IndexInServer; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo( const UString &prefix, // prefix for logical path const UString &fullPathName, // path on disk: can be relative to some basePrefix const NFind::CFileInfoW &fileInfo, CObjectVector &dirItems) { CDirItem item; item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = prefix + fileInfo.Name; item.FullPath = fullPathName; dirItems.Add(item); } static void EnumerateDirectory( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UString &directory, // additional disk prefix starting from baseFolderPrefix const UString &prefix, // logical prefix CObjectVector &dirItems, UStringVector &errorPaths, CRecordVector &errorCodes) { NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + directory); return; } if (!found) break; AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } void EnumerateDirItems( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UStringVector &fileNames, // names relative to baseFolderPrefix const UString &archiveNamePrefix, CObjectVector &dirItems, UStringVector &errorPaths, CRecordVector &errorCodes) { for(int i = 0; i < fileNames.Size(); i++) { const UString &fileName = fileNames[i]; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + fileName); continue; } AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const UString &diskPrefix, // full disk path prefix const UString &archivePrefix, // prefix from root const UStringVector &addArchivePrefix, // prefix from curNode CObjectVector &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->CheckBreak()); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = diskPrefix + name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fileInfo.IsDirectory(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } const UString realName = fileInfo.Name; const UString realDiskPath = diskPrefix + realName; { UStringVector pathParts; pathParts.Add(fileInfo.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support } RINOK(EnumerateDirItems(*nextNode, realDiskPath + wchar_t(kDirDelimiter), archivePrefix + realName + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = diskPrefix + nextNode.Name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fileInfo.IsDirectory()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems(nextNode, diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter), archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter), UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(diskPrefix); break; } if (!found) break; if (callback) RINOK(callback->CheckBreak()); const UString &name = fileInfo.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory())) { AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems); if (fileInfo.IsDirectory()) enterToSubFolders2 = true; } if (!fileInfo.IsDirectory()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems(*nextNode, diskPrefix + name + wchar_t(kDirDelimiter), archivePrefix + name + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "DirItem.h" #include "Windows/FileFind.h" void AddDirFileInfo( const UString &prefix, const UString &fullPathName, const NWindows::NFile::NFind::CFileInfoW &fileInfo, CObjectVector &dirItems); void EnumerateDirItems( const UString &baseFolderPrefix, const UStringVector &fileNames, const UString &archiveNamePrefix, CObjectVector &dirItems, UStringVector &errorPaths, CRecordVector &errorCodes); struct IEnumDirItemCallback { virtual HRESULT CheckBreak() { return S_OK; } }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector &errorCodes); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const UString &defaultName, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", defaultName); if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.LastWriteTime, options.ArchiveFileInfo.Attributes, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "can't decompress folder"; archiveSizes.Add(archiveFileInfo.Size); totalPackSize += archiveFileInfo.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; options.ArchiveFileInfo = archiveFileInfo; #ifndef _NO_CRYPTO openCallback->ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback); bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), archiveFileInfo.Size + archiveLink.VolumesSize, archiveLink.GetDefaultItemName(), wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; virtual HRESULT SetPassword(const UString &password) = 0; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software\\7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fileInfo; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fileInfo)) if (!fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDirectory()) continue; RINOK(LoadDll(folderPrefix + fileInfo.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } int CCodecs::FindFormatForArchiveName(const UString &archivePath) const { int slashPos1 = archivePath.ReverseFind(L'\\'); int slashPos2 = archivePath.ReverseFind(L'.'); int dotPos = archivePath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = archivePath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(arcType) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UINT32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UINT32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector Libs; CObjectVector Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector Formats; HRESULT Load(); int FindFormatForArchiveName(const UString &archivePath) const; int FindFormatForArchiveType(const UString &arcType) const; MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UINT32 *numMethods); STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UINT32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UINT32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) result = defaultName; return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const UInt32 kBufferSize = (200 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); for (UInt32 pos = 0; pos < processedSize; pos++) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() == 0) continue; if (pos + sig.GetCapacity() > processedSize) continue; if (TestSignature(buffer + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices.Delete(i--); } } } orderIndices2 += orderIndices; orderIndices = orderIndices2; } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] && 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif HRESULT badResult = S_OK; for(i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; if(result != S_OK) { badResult = result; if(result == E_ABORT) break; continue; } *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } if (badResult != S_OK) return badResult; return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { HRESULT result = OpenArchive(codecs, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); CMyComPtr getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || getStream == 0) return S_OK; CMyComPtr subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK) return S_OK; CMyComPtr subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK) return S_OK; if (!subStream) return S_OK; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return S_OK; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, CMyComPtr &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr openCallback; SetCallback(archiveName, openCallbackUI, openCallback); int formatInfo; return OpenArchive(codecs, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, fileName, archiveLink, 0); CMyComPtr openCallback; SetCallback(fileName, NULL, openCallback); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI); struct CArchiveLink { CMyComPtr Archive0; CMyComPtr Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } bool IsOpen; CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCreationTime: case kpidLastWriteTime: case kpidLastAccessTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttributes: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDirectory(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; if (!property.Value.IsEmpty()) ParseNumberString(property.Value, propVariant); realNames.Add(property.Name); values[i] = propVariant; } CRecordVector names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector &properties); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #ifdef _WIN32 #include #endif #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Common/CommandLineParser.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" // #include "Windows/Synchronization.h" #include "../../Common/FileStreams.h" #include "../../Compress/Copy/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/UpdateProduce.h" #include "../Common/OpenArchive.h" #include "TempFiles.h" #include "UpdateCallback.h" #include "EnumDirItems.h" #include "SetProperties.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NCommandLineParser; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector Streams; public: // CMyComPtr VolumeCallback; CRecordVector Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType) { if (!arcType.IsEmpty()) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(arcType); else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector &archiveItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CObjectVector &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr outArchive; if(archive != NULL) { CMyComPtr archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kDOS: case NFileTimeType::kUnix: fileTimeType = NFileTimeType::EEnum(value); break; default: return E_FAIL; } CObjectVector updatePairs; GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!! CObjectVector updatePairs2; UpdateProduce(updatePairs, actionSet, updatePairs2); UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArchiveItems = &archiveItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector &archiveItems) { archiveItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); archiveItems.Reserve(numItems); for(UInt32 i = 0; i < numItems; i++) { CArchiveItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory)); ai.Censored = censor.CheckPath(ai.Name.IsEmpty() ? defaultItemName : ai.Name, !ai.IsDirectory); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.LastWriteTime, ai.LastWriteTime)); CPropVariant propertySize; RINOK(archive->GetProperty(i, kpidSize, &propertySize)); ai.SizeIsDefined = (propertySize.vt != VT_EMPTY); if (ai.SizeIsDefined) ai.Size = ConvertPropVariantToUInt64(propertySize); ai.IndexInServer = i; archiveItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector &archiveItems, const CObjectVector &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, archiveItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT CheckBreak() { return Callback->CheckBreak(); } }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, openCallback); RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CObjectVector dirItems; if (options.StdInMode) { CDirItem item; item.FullPath = item.Name = options.StdInFileName; item.Size = (UInt64)(Int64)-1; item.Attributes = 0; SYSTEMTIME st; FILETIME ft; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft; dirItems.Add(item); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if(res != S_OK) { errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector archiveItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, archiveItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, archiveItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArchiveItems(0), UpdatePairs(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsFolder, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidLastAccessTime, VT_FILETIME}, { NULL, kpidCreationTime, VT_FILETIME}, { NULL, kpidLastWriteTime, VT_FILETIME}, { NULL, kpidAttributes, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; */ STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return E_NOTIMPL; /* return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); */ } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(newData != NULL) *newData = BoolToInt(updatePair.NewData); if(newProperties != NULL) *newProperties = BoolToInt(updatePair.NewProperties); if(indexInArchive != NULL) { if (updatePair.ExistInArchive) { if (ArchiveItems == 0) *indexInArchive = updatePair.ArchiveItemIndex; else *indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; } else *indexInArchive = UInt32(-1); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = updatePair.IsAnti; propVariant.Detach(value); return S_OK; } if (updatePair.IsAnti) { switch(propID) { case kpidIsFolder: case kpidPath: break; case kpidSize: propVariant = (UInt64)0; propVariant.Detach(value); return S_OK; default: propVariant.Detach(value); return S_OK; } } if(updatePair.ExistOnDisk) { const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } else { if (propID == kpidPath) { if (updatePair.NewNameIsDefined) { propVariant = updatePair.NewName; propVariant.Detach(value); return S_OK; } } if (updatePair.ExistInArchive && Archive) { UInt32 indexInArchive; if (ArchiveItems == 0) indexInArchive = updatePair.ArchiveItemIndex; else indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } propVariant.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(!updatePair.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if(updatePair.IsAnti) { return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true); } const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; RINOK(Callback->GetStream(dirItem.Name, false)); if(dirItem.IsDirectory()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IUpdateCallback STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; UString DirPrefix; bool ShareForWrite; bool StdInMode; const CObjectVector *DirItems; const CObjectVector *ArchiveItems; const CObjectVector *UpdatePairs; CMyComPtr Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; if (!FileTimeToUnixTime(time1, unixTime1)) { unixTime1 = 0; // throw 4191614; } if (!FileTimeToUnixTime(time2, unixTime2)) { unixTime2 = 0; // throw 4191615; } return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); /* if (!FileTimeToDosTime(time1, dosTime1)) throw 4191616; if (!FileTimeToDosTime(time2, dosTime2)) throw 4191617; */ return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; /* static const char *kNotCensoredCollisionMessaged = "Internal file name collision:\n"; static const char *kSameTimeChangedSizeCollisionMessaged = "Collision between files with same date/time and different sizes:\n"; */ static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) { UString message = kDuplicateFileNameMessage; message += L"\n"; message += strings[indices[i]]; message += L"\n"; message += strings[indices[i + 1]]; throw message; } } void GetUpdatePairInfoList( const CObjectVector &dirItems, const CObjectVector &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector &updatePairs) { CIntVector dirIndices, archiveIndices; UStringVector dirNames, archiveNames; int numDirItems = dirItems.Size(); int i; for(i = 0; i < numDirItems; i++) dirNames.Add(dirItems[i].Name); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); int numArchiveItems = archiveItems.Size(); for(i = 0; i < numArchiveItems; i++) archiveNames.Add(archiveItems[i].Name); SortFileNames(archiveNames, archiveIndices); TestDuplicateString(archiveNames, archiveIndices); int dirItemIndex = 0, archiveItemIndex = 0; CUpdatePair pair; while(dirItemIndex < numDirItems && archiveItemIndex < numArchiveItems) { int dirItemIndex2 = dirIndices[dirItemIndex], archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CDirItem &dirItem = dirItems[dirItemIndex2]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; int compareResult = CompareFileNames(dirItem.Name, archiveItem.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirItemIndex2; dirItemIndex++; } else if (compareResult > 0) { pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; archiveItemIndex++; } else { if (!archiveItem.Censored) throw 1082022;; // TTString(kNotCensoredCollisionMessaged + dirItem.Name); pair.DirItemIndex = dirItemIndex2; pair.ArchiveItemIndex = archiveItemIndex2; switch (MyCompareTime(fileTimeType, dirItem.LastWriteTime, archiveItem.LastWriteTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (archiveItem.SizeIsDefined) if (dirItem.Size != archiveItem.Size) // throw 1082034; // kSameTimeChangedSizeCollisionMessaged; pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirItemIndex++; archiveItemIndex++; } updatePairs.Add(pair); } for(;dirItemIndex < numDirItems; dirItemIndex++) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirIndices[dirItemIndex]; updatePairs.Add(pair); } for(;archiveItemIndex < numArchiveItems; archiveItemIndex++) { int archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; updatePairs.Add(pair); } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArchiveItemIndex; int DirItemIndex; }; void GetUpdatePairInfoList( const CObjectVector &dirItems, const CObjectVector &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector &updatePairs); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CObjectVector &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector &operationChain) { for(int i = 0; i < updatePairs.Size(); i++) { // CUpdateArchiveRange aRange; const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 pair2; pair2.IsAnti = false; pair2.ArchiveItemIndex = pair.ArchiveItemIndex; pair2.DirItemIndex = pair.DirItemIndex; pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk); pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive && pair.State != NPairState::kNotMasked); switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]); // cout << "deleting"; */ break; case NPairAction::kCopy: { if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = false; operationChain.Add(pair2); break; } case NPairAction::kCompress: { if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } case NPairAction::kCompressAsAnti: { pair2.IsAnti = true; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } } } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { // bool OperationIsCompress; bool NewData; bool NewProperties; bool ExistInArchive; bool ExistOnDisk; bool IsAnti; int ArchiveItemIndex; int DirItemIndex; bool NewNameIsDefined; UString NewName; CUpdatePair2(): NewNameIsDefined(false) {} }; void UpdateProduce( const CObjectVector &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector &operationChain); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRename: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractingString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestingString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkippingString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (encrypted) (*OutStream) << "Can not open encrypted archive. Wrong password?"; else (*OutStream) << "Can not open file as archive"; (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword) STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); HRESULT SetPassword(const UString &password); public: bool PasswordIsDefined; UString Password; UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsFolder, L"Folder" }, { kpidSize, L"Size" }, { kpidPackedSize, L"Packed Size" }, { kpidAttributes, L"Attributes" }, { kpidCreationTime, L"Created" }, { kpidLastAccessTime, L"Accessed" }, { kpidLastWriteTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubFolders, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" } }; static const char kEmptyAttributeChar = '.'; static const char kDirectoryAttributeChar = 'D'; static const char kReadonlyAttributeChar = 'R'; static const char kHiddenAttributeChar = 'H'; static const char kSystemAttributeChar = 'S'; static const char kArchiveAttributeChar = 'A'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttributesString(DWORD wa, bool directory, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? kDirectoryAttributeChar: kEmptyAttributeChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? kReadonlyAttributeChar: kEmptyAttributeChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? kHiddenAttributeChar: kEmptyAttributeChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? kSystemAttributeChar: kEmptyAttributeChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? kArchiveAttributeChar: kEmptyAttributeChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidLastWriteTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; return L"?"; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &propVariant) { if (propVariant.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&propVariant.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant)); if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (propVariant.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: propVariant = defaultItemName; break; case kpidLastWriteTime: propVariant = archiveFileInfo.LastWriteTime; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidLastWriteTime) { PrintTime(propVariant); } else if (fieldInfo.PropID == kpidAttributes) { if (propVariant.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = propVariant.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttributesString(attributes, isFolder, s); g_StdOut << s; } else if (propVariant.vt == VT_BSTR) { if (techMode) g_StdOut << propVariant.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal); } else { UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackedSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant propVariant; if (archive->GetProperty(index, propID, &propVariant) != S_OK) throw "GetPropertyValue error"; if (propVariant.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(propVariant); return true; } HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl; numErrors++; continue; } if (archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback); if (result != S_OK) { g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackedSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " [...] [...]\n" " [<@listfiles...>]\n" "\n" "\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" " -p{Password}: set Password\n" " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UINT32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr extractCallback = ecs; ecs->OutStream = &stdStream; ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, options.PasswordEnabled, options.Password, numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, options.ArchiveName, options.ArcType)) throw "Unsupported archive type"; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int #ifdef _MSC_VER __cdecl #endif main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/XP/2003/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::SetTotal(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR temp(Password); *password = temp.Detach(); return S_OK; } HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: HRESULT CheckBreak(); HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes); HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes); HRESULT CryptoGetTextPassword(BSTR *password); HRESULT GetPasswordIfAny(UString &password); bool WasPasswordAsked(); void ClearPasswordWasAskedFlag(); CStdOutStream *OutStream; bool PasswordIsDefined; UString Password; bool PasswordWasAsked; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { /* if (NConsoleClose::TestBreakSignal()) return E_ABORT; */ return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; bool PasswordIsDefined; UString Password; bool AskPassword; CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), PasswordIsDefined(false), AskPassword(false), StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector FailedCodes; UStringVector CantFindFiles; CRecordVector CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRename = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? "; // return true if pressed Quite; // in: anAll // out: anAll, anYes; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRename: return NUserAnswerMode::kAutoRename; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRename, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/7zip/UI/Console/afxres.h ================================================ #include ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Build.mak ================================================ !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -EHsc -Gz -WX -Gy !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS_O1 = $(CFLAGS) -O1 -W4 -Wp64 CFLAGS_O2 = $(CFLAGS) -O2 -W4 -Wp64 !ELSE CFLAGS_O1 = $(CFLAGS) -O1 -W3 CFLAGS_O2 = $(CFLAGS) -O2 -W3 !ENDIF LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr& p): _p(p.release()) {} CMyAutoPtr& operator=(CMyAutoPtr& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if(_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template bool operator==(const CBuffer& b1, const CBuffer& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template bool operator!=(const CBuffer& b1, const CBuffer& b2) { return !(b1 == b2); } typedef CBuffer CCharBuffer; typedef CBuffer CWCharBuffer; typedef CBuffer CByteBuffer; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } class CCRCTableInit { public: CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include #include namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include #include #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template inline T MyMin(T a, T b) { return a < b ? a : b; } template inline T MyMax(T a, T b) { return a > b ? a : b; } template inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template class CDynamicBuffer: public CBuffer { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer(buffer) {}; CDynamicBuffer(size_t size): CBuffer(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer CCharDynamicBuffer; typedef CDynamicBuffer CWCharDynamicBuffer; typedef CDynamicBuffer CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for(int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } #endif template class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include // #include #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template CStringBase operator+(const CStringBase& s1, const CStringBase& s2) { CStringBase result(s1); result += s2; return result; } template CStringBase operator+(const CStringBase& s, T c) { CStringBase result(s); result += c; return result; } template CStringBase operator+(T c, const CStringBase& s) { CStringBase result(c); result += s; return result; } template CStringBase operator+(const CStringBase& s, const T * chars) { CStringBase result(s); result += chars; return result; } template CStringBase operator+(const T * chars, const CStringBase& s) { CStringBase result(chars); result += s; return result; } template bool operator==(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) == 0); } template bool operator<(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) < 0); } template bool operator==(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) == 0); } template bool operator==(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) == 0); } template bool operator!=(const CStringBase& s1, const CStringBase& s2) { return (s1.Compare(s2) != 0); } template bool operator!=(const T *s1, const CStringBase& s2) { return (s2.Compare(s1) != 0); } template bool operator!=(const CStringBase& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase AString; typedef CStringBase UString; typedef CObjectVector AStringVector; typedef CObjectVector UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include #else #define MIDL_INTERFACE(x) struct #endif #else #include #endif #include #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { Free(); } void CBaseRecordVector::Free() { delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if (newCapacity <= _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void Free(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while(--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector CIntVector; typedef CRecordVector CUIntVector; typedef CRecordVector CBoolVector; typedef CRecordVector CByteVector; typedef CRecordVector CPointerVector; template class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include // for wchar_t #include #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if(!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if(intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if(c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if(c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if(!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; char defaultChar = '_'; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_INT16_DEFINED #define _7ZIP_INT16_DEFINED typedef short Int16; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED typedef int Int32; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED typedef unsigned int UInt32; #endif #ifdef _MSC_VER #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef __int64 Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned __int64 UInt64; #endif #else #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef long long int Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned long long int UInt64; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; // These functions are for UTF8 <-> UTF16 conversion. bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { Byte c = (Byte)src[i++]; if (c < 0x80) { dest += (wchar_t)c; continue; } if(c < 0xC0) return false; int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { if (i >= src.Length()) return false; Byte c2 = (Byte)src[i++]; if (c2 < 0x80 || c2 >= 0xC0) return false; value <<= 6; value |= (c2 - 0x80); numAdds--; } while(numAdds > 0); if (value < 0x10000) dest += (wchar_t)(value); else { value -= 0x10000; if (value >= 0x100000) return false; dest += (wchar_t)(0xD800 + (value >> 10)); dest += (wchar_t)(0xDC00 + (value & 0x3FF)); } } return true; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { UInt32 value = (UInt32)src[i++]; if (value < 0x80) { dest += (char)value; continue; } if (value >= 0xD800 && value < 0xE000) { if (value >= 0xDC00) return false; if (i >= src.Length()) return false; UInt32 c2 = (UInt32)src[i++]; if (c2 < 0xDC00 || c2 >= 0xE000) return false; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; dest += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; dest += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); } return true; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if(CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector SubNodes; CObjectVector IncludeItems; CObjectVector ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if(!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if(::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for(int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if(string.IsEmpty()) { if(i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if(errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfo &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATAW &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA findData; _handle = ::FindFirstFile(wildcard, &findData); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW findData; _handle = ::FindFirstFileW(wildcard, &findData); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &findData); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA findData; bool result = BOOLToBool(::FindNextFile(_handle, &findData)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW findData; if (!::FindNextFileW(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; if (!::FindNextFileA(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for(UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for(UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDirectory(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attributes & mask) != 0); } public: DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDirectory() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif #ifdef _WIN32 const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } #endif }}} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif #ifdef _WIN32 void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); #endif }}} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if(hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if(vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" // #include #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(UInt32 value, char *s, int numPos) { char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if(!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(st.wYear, s, 4); *s++ = '-'; s = UIntToStringSpec(st.wMonth, s, 2); *s++ = '-'; s = UIntToStringSpec(st.wDay, s, 2); if (includeTime) { *s++ = ' '; s = UIntToStringSpec(st.wHour, s, 2); *s++ = ':'; s = UIntToStringSpec(st.wMinute, s, 2); if (includeSeconds) { *s++ = ':'; UIntToStringSpec(st.wSecond, s, 2); } } /* sprintf(s, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay); if (includeTime) { sprintf(s + strlen(s), " %02d:%02d", st.wHour, st.wMinute); if (includeSeconds) sprintf(s + strlen(s), ":%02d", st.wSecond); } */ return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return propVariant.bstrVal; case VT_UI1: return ConvertUInt64ToString(propVariant.bVal); case VT_UI2: return ConvertUInt64ToString(propVariant.uiVal); case VT_UI4: return ConvertUInt64ToString(propVariant.ulVal); case VT_UI8: return ConvertUInt64ToString(propVariant.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(propVariant.filetime, true, true); /* case VT_I1: return ConvertInt64ToString(propVariant.cVal); */ case VT_I2: return ConvertInt64ToString(propVariant.iVal); case VT_I4: return ConvertInt64ToString(propVariant.lVal); case VT_I8: return ConvertInt64ToString(propVariant.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(propVariant.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_UI1: return propVariant.bVal; case VT_UI2: return propVariant.uiVal; case VT_UI4: return propVariant.ulVal; case VT_UI8: return (UInt64)propVariant.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } HRes Close() { return Event_Close(&_object); } #ifdef _WIN32 HRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif HRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } HRes Reset() { return Event_Reset(&_object); } HRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: HRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 HRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: HRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: HRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: HRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } HRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } HRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } HRes Release() { return Semaphore_Release1(&_object); } HRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } HRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } HRes Close() { return Thread_Close(&thread); } HRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } HRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { inline bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime(UInt16(dosTime >> 16), UInt16(dosTime & 0xFFFF), &fileTime)); } const UInt32 kHighDosTime = 0xFF9FBF7D; const UInt32 kLowDosTime = 0x210000; inline bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { if (fileTime.dwHighDateTime >= 0x01C00000) // 2000 dosTime = kHighDosTime; else dosTime = kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } const UInt32 kNumTimeQuantumsInSecond = 10000000; const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; inline void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } inline bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } }} #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/Makefile ================================================ # Copyright (C) 2006, 2007 Junjiro Okajima # Copyright (C) 2006, 2007 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: Makefile,v 1.2 2007-10-26 07:25:05 steven Exp $ # paths Sqlzma = ${CURDIR} #LzmaVer = lzma443 LzmaVer = Lzma = ${Sqlzma}/${LzmaVer} SqVer = squashfs3.2-r2 Squashfs = ${Sqlzma}/${SqVer} #LzmaC = ${Lzma}/C/7zip/Compress/LZMA_C #LzmaAlone = ${Lzma}/C/7zip/Compress/LZMA_Alone LzmaC = ${Lzma}/C/Compress/Lzma LzmaAlone = ${Lzma}/CPP/7zip/Compress/LZMA_Alone SqTools = ${Squashfs}/squashfs-tools # enable it if you want to add -g option when compiling UseDebugFlags = # disable it if you don't want to compile squashfs kernel module here BuildSquashfs = 1 export all: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ clean: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ ${RM} *~ install: #cp squashfs3.2-r2/squashfs-tools/mksquashfs /opt/buildroot-gdb/bin/mksquashfs_lzma-3.2 cp squashfs3.2-r2/squashfs-tools/mksquashfs ../../source/vendors/Ralink/RT2880/mksquashfs_lzma-3.2 ######################################## ================================================ FILE: src/others/squashfs-3.2-r2-lzma/sqlzma.h ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma. */ /* $Id: sqlzma.h,v 1.20 2008-03-12 16:58:34 jro Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include #include #include #ifdef _REENTRANT #include #endif #else #include #endif #define _7ZIP_BYTE_DEFINED /* * detect the compression method automatically by the first byte of compressed * data. * according to rfc1950, the first byte of zlib compression must be 0x?8. */ #define is_lzma(c) (c == 0x5d) /* ---------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif #ifndef __KERNEL__ /* for mksquashfs only */ struct sqlzma_opts { unsigned int try_lzma; unsigned int dicsize; }; int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out); #endif /* ---------------------------------------------------------------------- */ /* * Three patterns for sqlzma uncompression. very dirty code. * - kernel space (squashfs kernel module) * - user space with pthread (mksquashfs) * - user space without pthread (unsquashfs) */ struct sized_buf { unsigned int sz; unsigned char *buf; }; enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST}; struct sqlzma_un { int un_lzma; struct sized_buf un_a[SQUN_LAST]; unsigned char un_prob[31960]; /* unlzma 64KB - 1MB */ z_stream un_stream; #define un_cmbuf un_stream.next_in #define un_cmlen un_stream.avail_in #define un_resbuf un_stream.next_out #define un_resroom un_stream.avail_out #define un_reslen un_stream.total_out }; int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz); int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst); void sqlzma_fin(struct sqlzma_un *un); /* ---------------------------------------------------------------------- */ #ifdef __cplusplus }; #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.1.1.1 2007-06-05 09:36:21 steven Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/ACKNOWLEDGEMENTS ================================================ ACKNOWLEDGEMENTS Thanks to everyone who have download squashfs. I appreciate people using it, and any feedback you have. The following have provided useful feedback, which has guided some of the extra features in squashfs. This is a randomly ordered (roughly in chronological order) list, which is updated when I remember... Acknowledgements for Squashfs-3.2-r2 ------------------------------------ Junjiro Okajima discovered a couple of SMP issues, thanks. Junjiro Okajima and Tomas Matejicek have produced some good LZMA patches for Squashfs. Acknowledgements for Squashfs-3.2 --------------------------------- Peter Korsgaard sent a patch updating Squashfs to changes in the VFS interface in Linux 2.6.20. Acknowledgements for Squashfs-3.1 --------------------------------- Kenneth Duda and Ed Swierk of Arastra Inc. identified numerous bugs with Squashfs, and provided patches which were the basis for some of the fixes. In particular they identified the fragment rounding bug, the NFS bug, the initrd bug, and helped identify the 4K stack overflow bug. Scott James Remnant (Ubuntu) also identified the fragment rounding bug, and he also provided a patch. Ming Zhang identified the Lseek bug in Mksquashfs. His tests on the performance of Mksquashfs on SMP systems encouraged the rewrite of Mksquashfs. Peter Korsgaard, Daniel Olivera and Zilvinas Valinskas noticed Squashfs 3.0 didn't compile on Linux-2.6.18-rc[1-4] due to changes in the Linux VFS interfaces, and provided patches. Tomas Matejicek (SLAX) suggested the -force option on Unsquashfs, and noticed Unsquashfs didn't return the correct exit status. Yann Le Doare reported a kernel oops and provided a Qemu image that led to the identification of the simultaneously accessing multiply mounted Squashfs filesystems bug. Older acknowledgements ---------------------- Mark Robson - pointed out early on that initrds didn't work Adam Warner - pointed out that greater than 2GB filesystems didn't work. John Sutton - raised the problem when archiving the entire filesystem (/) there was no way to prevent /proc being archived. This prompted exclude files. Martin Mueller (LinuxTV) - noticed that the filesystem length in the superblock doesn't match the output filesystem length. This is due to padding to a 4K boundary. This prompted the addition of the -nopad option. He also reported a problem where 32K block filesystems hung when used as initrds. Arkadiusz Patyk (Polish Linux Distribution - PLD) reported a problem where 32K block filesystems hung when used as a root filesystem mounted as a loopback device. Joe Blow emailed me that I'd forgotten to put anything in the README about mounting the squashfs filesystem. David Fox (Lindows) noticed that the exit codes returned by Mksquashfs were wrong. He also noticed that a lot of time was spent in the duplicate scan routine. Cameron Rich complained that Squashfs did not support FIFOs or sockets. Steve Chadsey and Thomas Weissmuller noticed that files larger than the available memory could not be compressed by Mksquashfs. "Ptwahyu" and "Hoan" (I have no full names and I don't like giving people's email addresses), noticed that Mksquashfs 1.3 SEGV'd occasionally. Even though I had already noticed this bug, it is useful to be informed by other people. Don Elwell, Murray Jensen and Cameron Rich, have all sent in patches. Thanks, I have not had time to do anything about them yet... Drew Scott Daniels has been a good advocate for Squashfs. Erik Andersen has made some nice suggestions, unfortunately, I have not had time to implement anything. Artemiy I. Pavlov has written a useful LDP mini-howto for Squashfs (http://linuxdoc.artemio.net/squashfs). Yves Combe reported the Apple G5 bug, when using Squashfs for his PPC Knoppix-mib livecd project. Jaco Greeff (mklivecd project, and maintainer of the Mandrake squashfs-tools package) suggested the new mksquashfs -ef option, and the standalone build for mksquashfs. Mike Schaudies made a donation. Arkadiusz Patyk from the Polish Linux Distribution reported that Squashfs didn't work on amd64 machines. He gave me an account on a PLD amd64 machine which allowed myself to track down these bugs. Miles Roper, Peter Kjellerstedt and Willy Tarreau reported that release 2.1 did not compile with gcc < 3.x. Marcel J.E. Mol reported lack of kernel memory issues when using Squashfs on small memory embedded systems. This prompted the addition of the embedded system kernel configuration options. Era Scarecrow noticed that Mksquashfs had not been updated to reflect that smaller than 4K blocks are no longer supported. Kenichi Shima reported the Kconfig file had not been updated to 2.2. Aaron Ten Clay made a donation! Tomas Matejicek (SLAX) made a donation! ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/CHANGES ================================================ SQUASHFS CHANGE LOG 3.2-r2 15 JAN 2007 Kernel patch update and progress bar bug fix 1. Kernel patches 2.6.19/2.6.20 have been updated to use const structures and mutexes rather than older semaphores. 2. Minor SMP bug fixes. 3. Progress bar broken on x86-64. Fixed. 3.2 2 JAN 2007 NFS support, improvements to the Squashfs-tools, major bug fixes, lots of small improvements/bug fixes, and new kernel patches. Improvements: 1. Squashfs filesystems can now be exported via NFS. 2. Unsquashfs now supports 2.x filesystems. 3. Mksquashfs now displays a progress bar. 4. Squashfs kernel code has been hardened against accidently or maliciously corrupted Squashfs filesystems. Bug fixes: 5. Race condition occurring on S390 in readpage() fixed. 6. Odd behaviour of MIPS memcpy in read_data() routine worked-around. 7. Missing cache_flush in Squashfs symlink_readpage() added. 3.1-r2 30 AUG 2006 Mksquashfs -sort bug fix A code optimisation after testing unfortunately broke sorting in Mksquashfs. This has been fixed. 3.1 19 AUG 2006 This release has some major improvements to the squashfs-tools, a couple of major bug fixes, lots of small improvements/bug fixes, and new kernel patches. 1. Mksquashfs has been rewritten to be multi-threaded. It has the following improvements 1.1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 1.2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 1.3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 1.4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 1.5 The use of swap memory was found to significantly impact performance. The amount of memory used to cache files is now a command line option, by default this is 512 Mbytes. 2. Unsquashfs has the following improvements 2.1 Unsquashfs now allows you to specify the filename or the directory within the Squashfs filesystem that is to be extracted, rather than always extracting the entire filesystem. 2.2 A new -force option has been added which forces Unsquashfs to output to the destination directory even if files and directories already exist in the destination directory. This allows you to update an already existing directory tree, or to Unsquashfs to a partially filled directory tree. Without the -force option Unsquashfs will refuse to output. 3. The following major bug fixes have been made 3.1 A fragment table rounding bug has been fixed in Mksquashfs. Previously if the number of fragments in the filesystem were a multiple of 512, Mksquashfs would generate an incorrect filesystem. 3.2 A rare SMP bug which occurred when simultaneously acccessing multiply mounted Squashfs filesystems has been fixed. 4. Miscellaneous improvements/bug fixes 4.1 Kernel code stack usage has been reduced. This is to ensure Squashfs works with 4K stacks. 4.2 Readdir (Squashfs kernel code) has been fixed to always return 0, rather than the number of directories read. Squashfs should now interact better with NFS. 4.3 Lseek bug in Mksquashfs when appending to larger than 4GB filesystems fixed. 4.4 Squashfs 2.x initrds can now been mounted. 4.5 Unsquashfs exit status fixed. 4.6 New patches for linux-2.6.18 and linux-2.4.33. 3.0 15 MAR 2006 Major filesystem improvements 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). 2.2-r2 8 SEPT 2005 Second release of 2.2, this release fixes a couple of small bugs, a couple of small documentation mistakes, and adds a patch for kernel 2.6.13. 1. Mksquashfs now deletes the output filesystem image file if an error occurs whilst generating the filesystem. Previously on error the image file was left empty or partially written. 2. Updated mksquashfs so that it doesn't allow you to generate filesystems with block sizes smaller than 4K. Squashfs hasn't supported block sizes less than 4K since 2.0-alpha. 3. Mksquashfs now ignores missing files/directories in sort files. This was the original behaviour before 2.2. 4. Fixed small mistake in fs/Kconfig where the version was still listed as 2.0. 5. Updated ACKNOWLEDGEMENTS file. 2.2 3 JUL 2005 This release has some small improvements, bug fixes and patches for new kernels. 1. Sort routine re-worked and debugged from release 2.1. It now allows you to give Mkisofs style sort files and checks for filenames that don't match anything. Sort priority has also been changed to conform to Mkisofs usage, highest priority files are now placed at the start of the filesystem (this means they will be on the inside of a CD or DVD). 2. New Configure options for embedded systems (memory constrained systems). See INSTALL file for further details. 3. Directory index bug fixed where chars were treated as signed on some architectures. A file would not be found in the rare case that the filename started with a chracter greater than 127. 4. Bug introduced into the read_data() routine when sped up to use data block queueing fixed. If the second or later block resulted in an I/O error this was not checked. 5. Append bug introduced in 2.1 fixed. The code to compute the new compressed and uncompressed directory parts after appending was wrong. 6. Metadata block length read routine altered to not perform a misaligned short read. This was to fix reading on an ARM7 running uCLinux without a misaligned read interrupt handler. 7. Checkdata bug introduced in 2.1 fixed. 2.1-r2 15 DEC 2004 Code changed so it can be compiled with gcc 2.x 1. In some of the code added for release 2.1 I unknowingly used some gcc extensions only supported by 3.x compilers. I have received a couple of reports that the 2.1 release doesn't build on 2.x and so people are clearly still using gcc 2.x. The code has been rewritten to remove these extensions. 2.1 10 DEC 2004 Significantly improved directory handling plus numerous other smaller improvements 1. Fast indexed directories implemented. These speed up directory operations (ls, file lookup etc.) significantly for directories larger than 8 KB. 2. All directories are now sorted in alphabetical order. This again speeds up directory operations, and in some cases it also results in a small compression improvement (greater data similarity between files with alphabetically similar names). 3. Maximum directory size increased from 512 KB to 128 MB. 4. Duplicate fragment checking and appending optimised in mksquashfs, depending on filesystem, this is now up to 25% faster. 5. Mksquashfs help information reformatted and reorganised. 6. The Squashfs version and release date is now printed at kernel boot-time or module insertion. This addition will hopefully help to reduce the growing problem where the Squashfs version supported by a kernel is unknown and the kernel source is unavailable. 7. New PERFORMANCE.README file. 8. New -2.0 mksquashfs option. 9. CHANGES file reorganised. 10. README file reorganised, clarified and updated to include the 2.0 mksquashfs options. 11. New patch for Linux 2.6.9. 12. New patch for Linux 2.4.28. 2.0r2 29 AUG 2004 Workaround for kernel bug in kernels 2.6.8 and newer added 1. New patch for kernel 2.6.8.1. This includes a workaround for a kernel bug introduced in 2.6.7bk14, which is present in all later versions of the kernel. If you're using a 2.6.8 kernel or later then you must use this 2.6.8.1 patch. If you've experienced hangs or oopses using Squashfs with a 2.6.8 or later kernel then you've hit this bug, and this patch will fix it. It is worth mentioning that this kernel bug potentially affects other filesystems. If you receive odd results with other filesystems you may be experiencing this bug with that filesystem. I submitted a patch but this has not yet gone into the kernel, hopefully the bug will be fixed in later kernels. 2.0 13 JULY 2004 A couple of new options, and some bug fixes 1. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 2. Initrds are now supported for kernels 2.6.x. 3. amd64 bug fixes. If you use an amd64, please read the README-AMD64 file. 4. Check-data and gid bug fixes. With 2.0-alpha when mounting 1.x filesystems in certain cases file gids were corrupted. 5. New patch for Linux 2.6.7. 2.0-ALPHA 21 MAY 2004 Filesystem changes and compression improvements 1. Squashfs 2.0 has added the concept of fragment blocks. Files smaller than the file block size and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K (in the ALPHA version of Squashfs 2.0). 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 6. Numerous small bug fixes have been made. 1.3r3 18 JAN 2004 Third release of 1.3, this adds a new mksquashfs option, some bug fixes, and extra patches for new kernels 1. New mksquashfs -ef exclude option. This option reads the exclude dirs/files from an exclude file, one exclude dir/file per line. This avoids the command line size limit when using the -e exclude option, 2. When appending to existing filesystems, if mksquashfs experiences a fatal error (e.g. out of space when adding to the destination), the original filesystem is restored, 3. Mksquashfs now builds standalone, without the kernel needing to be patched. 4. Bug fix in the kernel squashfs filesystem, where the pages being filled were not kmapped. This seems to only have caused problems on an Apple G5, 5. New patch for Linux 2.4.24, 6. New patch for Linux 2.6.1, this replaces the patch for 2.6.0-test7. 1.3r2 14 OCT 2003 Second release of 1.3, bug fixes and extra patches for new kernels 1. Bug fix in routine that adds files to the filesystem being generated in mksquashfs. This bug was introduced in 1.3 (not enough testing...) when I rewrote it to handle files larger than available memory. This bug caused a SEGV, so if you've ever got that, it is now fixed, 2. Long running bug where ls -s and du reported wrong block size fixed. I'm pretty sure this used to work many kernel versions ago (2.4.7) but it broke somewhere along the line since then, 3. New patch for Linux 2.4.22, 4. New patch for 2.6.0-test7, this replaces the patch for 2.6.0-test1. 1.3 29 JUL 2003 FIFO/Socket support added plus optimisations and improvements 1. FIFOs and Socket inodes are now supported, 2. Mksquashfs can now compress files larger than available memory, 3. File duplicate check routine optimised, 4. Exit codes fixed in Mksquashfs, 5. Patch for Linux 2.4.21, 6. Patch for Linux 2.6.0-test1. Hopefully, this will work for the next few releases of 2.6.0-testx, otherwise, I'll be releasing a lot of updates to the 2.6.0 patch... 1.2 13 MAR 2003 Append feature and new mksquashfs options added Mksquashfs can now add to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. See the README file for usage changes. 1.1b 16 JAN 2003 Bug fix release Fixed readpage deadlock bug. This was a rare deadlock bug that happened when pushing pages into the page cache when using greater than 4K blocks. I never got this bug when I tested the filesystem, but two people emailed me on the same day about the problem! I fixed it by using a page cache function that wasn't there when I originally did the work, which was nice :-) 1.1 8 JAN 2003 Added features 1. Kernel squashfs can now mount different byte order filesystems. 2. Additional features added to mksquashfs. Mksquashfs now supports exclude files and multiple source files/directories can be specified. A nopad option has also been added, which informs mksquashfs not to pad filesystems to a multiple of 4K. See README for mksquashfs usage changes. 3. Greater than 2GB filesystems bug fix. Filesystems greater than 2GB can now be created. 1.0c 14 NOV 2002 Bug fix release Fixed bugs with initrds and device nodes 1.0 23 OCT 2002 Initial release ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/INSTALL ================================================ INSTALLING SQUASHFS The squashfs3.2-r2.tar.gz file contains this file, a README-3.2 file, another README file, an ACKNOWLEDGEMENTS file, a CHANGES file, the kernel-patches directory containing the squashfs patches, and the squashfs-tools directory (mksquashfs and unsquashfs). 1. Patching the kernel ---------------------- There are eleven kernel patch directories depending on your linux kernel version. If your kernel version isn't listed then try the patch for the nearest kernel listed. To patch your kernel, cd into the top level directory, and run the "patch" command, e.g. assuming linux-2.6.20 %cd /usr/src/linux-2.6.20 %patch -p1 < location-of-squashfs/kernel-patches/linux-2.6.20/squashfs3.2-patch Where "location-of-squashfs" is the path to the squashfs3.2 source directory. The squashfs patches patch the relevant kernel files to add configure support, initrd support, include files, and the squashfs directory under linux/fs/. Once patched, the kernel must be reconfigured, with squashfs support turned on (either Y/M) to ensure that inflate support is built into the kernel. The squashfs kernel option can be found in the miscellaneous filesystems submenu near the bottom of the filesystems submenu. There are a set of options which are intended for use by embedded systems with low memory. At the "Additional options for memory-constrained systems" prompt, please say NO unless you're using an embedded system! Saying Y here allows you to specify cache sizes and how Squashfs allocates memory. The "Number of fragments cached" prompt allows the number of fragments cached to be controlled. By default SquashFS caches the last 3 fragments read from the filesystem. Increasing this amount may mean SquashFS has to re-read fragments less often from disk, at the expense of extra system memory. Decreasing this amount will mean SquashFS uses less memory at the expense of extra reads from disk. Note there must be at least one cached fragment. Anything much more than three will probably not make much difference. The "Use Vmalloc rather than Kmalloc" prompt allows you to tell SquashFS to use Vmalloc. By default SquashFS uses kmalloc to obtain fragment cache memory. Kmalloc memory is the standard kernel allocator, but it can fail on memory constrained systems. Because of the way Vmalloc works, Vmalloc can succeed when kmalloc fails. Specifying this option will make SquashFS always use Vmalloc to allocate the fragment cache memory. 2. Building squashfs tools -------------------------- The squashfs-tools directory contains the mksquashfs and unsquashfs programs. These can be made by typing make. The source files use a local copy of squashfs_fs.h (included in the kernel patches) allowing the tools to be made without needing to patch the kernel. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/OLD-READMEs/README-2.0 ================================================ NOTE: This the original README for version 2.0. It is retained as it contains information about the fragment design. A description of the new 2.0 mksquashfs options has been added to the main README file, and that file should now be consulted for these. SQUASHFS 2.0 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to the final release of Squashfs version 2.0! A lot of changes to the filesystem have been made under the bonnet (hood). Squashfs 2.0 uses fragment blocks and larger blocks (64K) to improve compression ratio by about 5 - 20% over Squashfs 1.0 depending on the files being compressed. Using fragment blocks allows Squashfs 2.0 to achieve better compression than cloop and similar compression to tgz files while retaining the I/O efficiency of a compressed filesystem. Detailed changes: 1. Squashfs 2.0 has added the concept of fragment blocks (see later discussion). Files smaller than the file block size (64K in Squashfs 2.0) and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K. 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 6. Initrds are now supported for kernels 2.6.x. 7. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 8. AMD64, check-data and gid bug fixes. 9. Numerous small bug fixes have been made. 10. New patch for Linux 2.6.7. New Squashfs 2.0 options ------------------------ -noF or -noFragmentCompression Do not compress the fragments. Added for compatibility with noI and noD, probably not that useful. -no-fragments Do not use fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. -always-use-fragments By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. -no-duplicates Do not detect duplicate files. -all-root -root-owned These options (both do exactly the same thing), force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. -force-uid uid This option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. -force-gid gid This option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. Compression improvements example -------------------------------- The following is the compression results obtained compressing the 2.6.6 linux kernel source using CRAMFS, Cloop (with iso filesystem), Squashfs 1.3 and Squashfs 2.0 (results generated using big-endian filesystems). In decreasing order of size: CRAMFS 62791680 bytes (59.9M) Squashfs 1.x 51351552 bytes (48.9M) Cloop 46118681 bytes (44.0M) Squashfs 2.0 45604854 bytes (43.5M) The Squashfs 1.x filesystem is 12.6% larger than the new 2.0 filesystem. The cloop filesystem is 1.1% larger than the Squashfs 2.0 filesystem. Fragment blocks in Squashfs 2.0 ------------------------------- Squashfs like all other compressed filesystems compresses files individually on a block by block basis. This is performed to allow mounting and de-compression of files on a block by block basis without requiring the entire filesystem to be decompressed. This is in contrast to data-based compression schemes which compress without understanding the underlying filesystem (i.e. cloop and tgz files) and which, therefore, do not compress files individually. Each approach has advantages and disadvantages, data-based systems have better compression because compression is always performed at the maximum block size (64K in cloop) irrespective of the size of each file (which could be less than the block size). Compressed filesystems tend to be faster at I/O because they understand the filesystem and therefore employ better caching stategies and read less un-needed data from the filesystem. Fragment blocks in Squashfs 2.0 solves this problem by packing files (and optionally the ends of files) which are smaller than the block size into shared blocks, which are compressed together. For example five files each of 10K will be packed into one shared fragment of 50K and compressed together, rather than being compressed in five 10K blocks. This scheme produces a hybrid filesystem, retaining the I/O efficiency of a compressed filesystem, while obtaining the compression efficiency of data-based schemes by compressing small files together. Squashfs 1.x and Squashfs 2.0 compatibility ------------------------------------------- Appending to Squashfs 1.x filesystems is not supported. If you wish to append to 1.x filesystems, then either use the original mksquashfs, or convert them to Squashfs 2.0 by mounting the filesystem and running the 2.0 mksquashfs on the mounted filesystem. Mounting Squashfs 1.x filesystems IS supported by the 2.0 kernel patch. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/OLD-READMEs/README-2.1 ================================================ SQUASHFS 2.1 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to Squashfs version 2.1-r2. Squashfs 2.1 introduces indexed directories which considerably speed up directory lookup (ls, find etc.) for directories which are greater than 8K in size. All directories are now also sorted alphabetically which further speeds up directory lookup. Many smaller improvements have also been made to this release, please see the CHANGES file entry for detailed changes. 1. DIRECTORY SPEED IMPROVEMENT EXAMPLES --------------------------------------- To give an indication of the directory speed improvements a number of test results are shown here. There is in addition a new PERFORMANCE.README file which gives details of I/O and lookup performance for Squashfs 2.1 against the Zisofs, Cloop and CRAMFS filesystems. example 1: Filesystems generated from a single directory of 72,784 files (2.6 MB directory size). Each file is 10 bytes in size (the test is directory lookup and so the file size isn't an issue). The ext3 uncompressed directory size is 288 MB (presumably because of one file per block). Zisofs compressed size 153.50 MB Cloop (isofs) compressed size 1.74 MB Squashfs2.1 compressed size 612 KB (0.60 MB) Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 35 minutes 7.895 seconds (User 7.868 secs, Sys 34 mins 5.621 secs) Cloop 35 minutes 12.765 seconds (User 7.771 secs, Sys 34 mins 3.869 secs) Squashfs2.1 19 seconds (User 5.119 secs, Sys 14.547 secs) example 2: Filesystems were generated from the Ubuntu Warty livecd (original uncompressed size on ext3 is 1.4 GB). Zisofs compressed size 589.81 MB Cloop (isofs) compressed size 471.19 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 49.875 seconds (User time 2.589 secs, Sys 11.194 secs) Cloop 20.797 seconds (User time 2.706 secs, Sys 13.496 secs) Squashfs2.0 16.556 seconds (User time 2.424 secs, Sys 10.371 secs) Squashfs2.1 10.143 seconds (User time 2.475 secs, Sys 4.440 secs) NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 2. NEW MKSQUASHFS OPTIONS ------------------------- There is only one extra option "-2.0". This tells mksquashfs to generate a filesystem which is mountable with Squashfs version 2.0. 3. APPENDING AND MOUNTING SQUASHFS 2.0 FILESYSTEMS -------------------------------------------------- Mounting 2.0 filesystems is supported by Squashfs 2.1. In addition mksquashfs v2.1 can append to 2.0 filesystems, although the generated filesystem will still be a 2.0 filesystem. 4. DONATIONS ------------ If you find Squashfs useful then please consider making a donation, particularly if you use Squashfs in a commercial product. Please consider giving something back especially if you're making money from it. Off the Squashfs subject somewhat I'm currently looking for another job doing Linux kernel or filesystems work. If you know of any such work that can be performed from the UK then please get in touch. Thanks. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/OLD-READMEs/README-3.0 ================================================ SQUASHFS 3.0 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to the first release of Squashfs version 3.0. Squashfs 3.0 has the the following improvements to 2.x. 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). There is a new Unsquashfs utility (in squashfs-tools) than can be used to decompress a filesystem without mounting it. Squashfs 3.0 supports 2.x filesystems. Support for 1.x filesystems will be added in the future. 1. UNSQUASHFS ------------- Unsquashfs has the following options: SYNTAX: unsquashfs [-ls | -dest] filesystem -version print version, licence and copyright information -info print files as they are unsquashed -ls list filesystem only -dest unsquash to , default "squashfs-root" The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. Unsquashfs can decompress 3.0 filesystems. Support for 2.x and 1.x filesystems will be added in the future. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/OLD-READMEs/README-3.1 ================================================ SQUASHFS 3.1 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.1-r2. Squashfs 3.1 has major improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- Mksquashfs has been rewritten and it is now multi-threaded. It offers the following improvements: 1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 5. The use of swap memory was found to significantly impact performance. The amount of memory used to cache the file is now a command line option, by default this is 512 Mbytes. 1.1 NEW COMMAND LINE OPTIONS ---------------------------- The new Mksquashfs program has a couple of extra command line options which can be used to control the new features: -processors This specifies the number of processors used by Mksquashfs. By default this is the number of available processors. -read_queue This specifies the size of the file input queue used by the reader thread. This defaults to 64 Mbytes. -write_queue This specifies the size of the filesystem output queue used by the writer thread. It also specifies the maximum cache used in file duplicate detection (the output queue is shared between these tasks). This defaults to 512 Mbytes. 1.2 PERFORMANCE RESULTS ----------------------- The following results give an indication of the speed improvements. Two example filesystems were tested, a liveCD filesystem (about 1.8 Gbytes uncompressed), and my home directory consisting largely of text files (about 1.3 Gbytes uncompressed). Tests were run on a single core and a dual core system. Dual Core (AMDx2 3800+) system: Source directories on ext3. LiveCD, old mksquashfs: real 11m48.401s user 9m27.056s sys 0m15.281s LiveCD, new par_mksquashfs: real 4m8.736s user 7m11.771s sys 0m27.749s "Home", old mksquashfs: real 4m34.360s user 3m54.007s sys 0m32.155s "Home", new par_mksquashfs: real 1m27.381s user 2m7.304s sys 0m17.234s Single Core PowerBook (PowerPC G4 1.5 GHz Ubuntu Linux) Source directories on ext3. LiveCD, old mksquashs: real 11m38.472s user 9m6.137s sys 0m23.799s LiveCD, par_mksquashfs: real 10m5.572s user 8m59.921s sys 0m16.145s "Home", old mksquashfs: real 3m42.298s user 2m49.478s sys 0m13.675s "Home", new par_mksquashfs: real 3m9.178s user 2m50.699s sys 0m9.069s I'll be interested in any performance results obtained, especially from SMP machines larger than my dual-core AMD box, as this will give an indication of the scalability of the code. Obviously, I'm also interested in any problems, deadlocks, low performance etc. 2. UNSQUASHFS ------------- Unsquashfs now allows you to specify the filename or directory that is to be extracted from the Squashfs filesystem, rather than always extracting the entire filesystem. It also has a new "-force" option, and all options can be specified in a short form (-i rather than -info). The Unsquashfs usage info is now: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] unsquash to , default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The new "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/OLD-READMEs/README-AMD64 ================================================ Information for amd64 users --------------------------- All releases of Squashfs prior to 2.0 generate incorrect filesystems on amd64 machines. Filesystems created on amd64 machines work correctly on amd64 machines, but cannot be mounted on non-amd64 machines. Likewise, filesystems created on non-amd64 machines cannot be mounted on amd64 machines. This bug is caused by the different size of the "time_t" definition used in SquashFS filesystem structures. This bug is fixed in releases 2.0 and newer. However, all amd64 filesystems generated by previous releases will not be mountable on amd64 machines with newer releases. If you have amd64 filesystems generated with mksquashfs version 2.0-alpha or older, it is important that you recreate the filesystem. This can be performed by mounting the filesystem using a kernel with the original patch (i.e. a 2.0-alpha or older patch) and running the NEW (i.e. this release) mksquashfs tool to create a new SquashFS filesystem. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/PERFORMANCE.README ================================================ GENERAL INFORMATION ON PERFORMANCE TESTS ---------------------------------------- The following performance tests were based on two file sets: the liveCD filesystem from the Ubuntu liveCD (Warty release), and the liveCD filesystem from the Damn Small Linux liveCD (release 0.8.4). The Ubuntu liveCD filesystem was used to test filesystem performance from CDROM and hard disk for Zisofs, Cloop, Squashfs 2.0 and Squashfs2.1. CRAMFS filesystem performance could not be tested for this filesystem bacause it exceeds the maximum supported size of CRAMFS. To test CRAMFS performance against Squashfs, the liveCD filesystem from Damn Small Linux was used. NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 1. Ubuntu liveCD performance tests ext3 uncompressed size 1.4 GB Zisofs compressed size 589.81 MB Cloop compressed size 471.89 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB 1.1 Performance tests from CDROM 1.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM Zisofs 49.88 seconds (User 2.60 secs, Sys 11.19 secs) Cloop 20.80 seconds (User 2.71 secs, Sys 13.50 secs) Squashfs2.0 16.56 seconds (User 2.42 secs, Sys 10.37 secs) Squashfs2.1 10.14 seconds (User 2.48 secs, Sys 4.44 secs) 1.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM Zisofs 27 minutes 28.54 seconds (User 3.00 secs, Sys 1 min 4.80 secs) Cloop 5 minutes 55.72 seconds (User 2.90 secs, Sys 3 min 37.90 secs) Squashfs2.0 5 minutes 20.87 seconds (User 2.33 secs, Sys 56.98 secs) Squashfs2.1 5 minutes 15.46 seconds (user 2.28 secs, Sys 51.12 secs) 1.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM Zisofs 101 minutes 29.65 seconds (User 5.33 secs, Sys 1 min 17.20 secs) Cloop 35 minutes 27.51 seconds (user 5.93 secs, Sys 4 mins 30.23 secs) Squashfs2.0 21 minutes 53.05 seconds (user 5.71 secs, Sys 2 mins 36.59 secs) Squashfs2.1 21 minutes 46.99 seconds (User 5.80 secs, Sys 2 mins 31.88 secs) 1.2 Performance tests from Hard disk 1.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 17.29 seconds (User 2.62 secs, Sys 11.08 secs) Cloop 16.46 seconds (User 2.63 secs, Sys 13.41 secs) Squashfs2.0 13.75 seconds (User 2.44 secs, Sys 11.00 secs) Squashfs2.1 6.94 seconds (User 2.44 secs, Sys 4.48 secs) 1.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 1 minute 21.47 seconds (User 2.73 secs, Sys 54.44 secs) Cloop 1 minute 34.06 seconds (user 2.85 secs, Sys 1 min 12.13 secs) Squashfs2.0 1 minute 21.22 seconds (User 2.42 secs, Sys 56.21 secs) Squashfs2.1 1 minute 15.46 seconds (User 2.36 secs, Sys 49.78 secs) 1.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk Zisofs 11 minutes 13.64 seconds (User 5.08 secs, Sys 52.62 secs) Cloop 5 minutes 37.93 seconds (user 6 secs, Sys 2 mins 22.38 secs) Squashfs2.0 5 minutes 7.11 seconds (user 5.63 secs, Sys 2 mins 35.23 secs) Squashfs2.1 5 minutes 1.87 seconds (User 5.71 secs, Sys 2 mins 29.98 secs) 2. Damn Small Linux liveCD performance tests ext3 uncompressed size 126 MB CRAMFS compressed size 52.19 MB Squashfs2.0 compressed size 46.52 MB Squashfs2.1 compressed size 46.52 MB 2.1 Performance tests from CDROM 2.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 10.85 seconds (User 0.39 secs, Sys 0.98 secs) Squashfs2.0 2.97 seconds (User 0.36 secs, Sys 2.15 secs) Squashfs2.1 2.43 seconds (User 0.40 secs, Sys 1.42 secs) 2.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 55.38 seconds (User 0.34 secs, Sys 6.98 secs) Squashfs2.0 35.99 seconds (User 0.30 secs, Sys 6.35 secs) Squashfs2.1 33.83 seconds (User 0.26 secs, Sys 5.56 secs) 2.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM CRAMFS 3 minutes 1.68 seconds (User 0.54 secs, Sys 9.51 secs) Squashfs2.0 1 minute 39.45 seconds (User 0.57 secs, Sys 13.14 secs) Squashfs2.1 1 minute 38.41 seconds (User 0.58 secs, Sys 13.08 secs) 2.2 Performance tests from Hard disk 2.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 1.77 seconds (User 0.53 secs, Sys 1.21 secs) Squashfs2.0 2.67 seconds (User 0.41 secs, Sys 2.25 secs) Squashfs2.1 1.87 seconds (User 0.41 secs, Sys 1.46 secs) 2.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 6.80 seconds (User 0.36 secs, Sys 6.02 secs) Squashfs2.0 7.23 seconds (User 0.29 secs, Sys 6.62 secs) Squashfs2.1 6.53 seconds (User 0.31 secs, Sys 5.82 secs) 2.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk CRAMFS 28.55 seconds (User 0.49 secs, Sys 6.49 secs) Squashfs2.0 25.44 seconds (User 0.58 secs, Sys 13.17 secs) Squashfs2.1 24.72 seconds (User 0.56 secs, Sys 13.15 secs) ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/README ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Please read the README-3.2 and CHANGES files for details of changes. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. 1. SQUASHFS OVERVIEW -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. In theory files up to 2^64 bytes are supported. In theory filesystems can be up to 2^64 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 64K (the default size is 64K). Using 64K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 7. Both big and little endian architectures are supported. Squashfs can mount filesystems created on different byte order machines. 2. USING SQUASHFS ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 3. MKSQUASHFS ------------- 3.1 Mksquashfs options and overview. ------------------------------------ As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. SYNTAX:mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Options are -version print version, licence and copyright message -info print files written to filesystem -b set data block to . Default 65536 bytes -processors Use processors. By default will use number of processors available -read-queue Set input queue to Mbytes. Default 64 Mbytes -write-queue Set output queue to Mbytes. Default 512 Mbytes -noI do not compress inode table -noD do not compress data blocks -noF do not compress fragment blocks -no-fragments do not use fragments -always-use-fragments use fragment blocks for files larger than block size -no-duplicates do not perform duplicate checking -noappend do not append to existing filesystem -keep-as-directory if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory -root-becomes when appending source files/directories, make the original root become a subdirectory in the new root called , rather than adding the new source items to the original root -all-root make all files owned by root -force-uid uid set all file uids to uid -force-gid gid set all file gids to gid -le create a little endian filesystem -be create a big endian filesystem -nopad do not pad filesystem to a multiple of 4K -check_data add checkdata for greater filesystem checks -root-owned alternative name for -all-root -noInodeCompression alternative name for -noI -noDataCompression alternative name for -noD -noFragmentCompression alternative name for -noF -sort sort files according to priorities in . One file or dir with priority per line. Priority -32768 to 32767, default priority 0 -ef list of exclude dirs/files. One per line Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. 3.2 Changing compression defaults used in mksquashfs ---------------------------------------------------- There are a large number of options that can be used to control the compression in mksquashfs. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances! The -noI, -noD and -noF options (also -noInodeCompression, -noDataCompression and -noFragmentCompression) can be used to force mksquashfs to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. The -no-fragments tells mksquashfs to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. The -always-use-fragments option tells mksquashfs to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. The -no-duplicates option tells mksquashfs to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. The -b option allows the block size to be selected, this can be either 4096, 8192, 16384, 32768 or 65536 bytes. 3.3 Specifying the UIDs/GIDs used in the filesystem --------------------------------------------------- By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, mksquashfs provides a number of options which can be used to override the ownership. The options -all-root and -root-owned (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The "-force-uid uid" option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. The "-force-gid gid" option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. 3.4 Excluding files from the filesystem --------------------------------------- The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. 3.5 Appending to squashfs filesystems ------------------------------------- Running squashfs with the destination directory containing an existing filesystem will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3.6 Miscellaneous options ------------------------- The -info option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The -le and -be options can be used to force mksquashfs to generate a little endian or big endian filesystem. Normally mksquashfs will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 4. UNSQUASHFS ------------- Unsquashfs allows you to decompress and extract a Squashfs filesystem without mounting it. It can extract the entire filesystem, or a specific file or directory. The Unsquashfs usage info is: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] unsquash to , default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. The "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. Unsquashfs can decompress 2.x and 3.x filesystems. Support for 1.x filesystems will be added in the future. 5. FILESYSTEM LAYOUT -------------------- Brief filesystem design notes follow for the original 1.x filesystem layout. A description of the 2.x and 3.x filesystem layouts will be written sometime! A squashfs filesystem consists of five parts, packed together on a byte alignment: --------------- | superblock | |---------------| | data | | blocks | |---------------| | inodes | |---------------| | directories | |---------------| | uid/gid | | lookup table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory and uid/gid lookup tables are written. 5.1 Metadata ------------ Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. An inode is identified by a two field tuple . Inode contents vary depending on the file type. The base inode consists of: base inode: Inode type Mode uid index gid index The inode type is 4 bits in size, and the mode is 12 bits. The uid and gid indexes are 4 bits in length. Ordinarily, this will allow 16 unique indexes into the uid table. To minimise overhead, the uid index is used in conjunction with the spare bit in the file type to form a 48 entry index as follows: inode type 1 - 5: uid index = uid inode type 5 -10: uid index = 16 + uid inode type 11 - 15: uid index = 32 + uid In this way 48 unique uids are supported using 4 bits, minimising data inode overhead. The 4 bit gid index is used to index into a 15 entry gid table. Gid index 15 is used to indicate that the gid is the same as the uid. This prevents the 15 entry gid table filling up with the common case where the uid/gid is the same. The data contents of symbolic links are stored immediately after the symbolic link inode, inside the inode table. This allows the normally small symbolic link to be compressed as part of the inode table, achieving much greater compression than if the symbolic link was compressed individually. Similarly, the block index for regular files is stored immediately after the regular file inode. The block index is a list of block lengths (two bytes each), rather than block addresses, saving two bytes per block. The block address for a given block is computed by the summation of the previous block lengths. This takes advantage of the fact that the blocks making up a file are stored contiguously in the filesystem. The top bit of each block length is set if the block is uncompressed, either because the -noD option is set, or if the compressed block was larger than the uncompressed block. 5.2 Directories --------------- Like inodes, directories are packed into the metadata blocks, and are not aligned on block boundaries, therefore directories can overlap compressed blocks. A directory is, again, identified by a two field tuple . Directories are organised in a slightly complex way, and are not simply a list of file names and inode tuples. The organisation takes advantage of the observation that in most cases, the inodes of the files in the directory will be in the same compressed metadata block, and therefore, the inode tuples will have the same start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. The organisation is as follows: directory_header: count (8 bits) inode start block (24 bits) directory entry: * count inode offset (13 bits) inode type (3 bits) filename size (8 bits) filename This organisation saves on average 3 bytes per filename. 5.3 File data ------------- File data is compressed on a block by block basis and written to the filesystem. The filesystem supports up to 32K blocks, which achieves greater compression ratios than the Linux 4K page size. The disadvantage with using greater than 4K blocks (and the reason why most filesystems do not), is that the VFS reads data in 4K pages. The filesystem reads and decompresses a larger block containing that page (e.g. 32K). However, only 4K can be returned to the VFS, resulting in a very inefficient filesystem, as 28K must be thrown away. Squashfs, solves this problem by explicitly pushing the extra pages into the page cache. 6. AUTHOR INFO -------------- Squashfs was written by Phillip Lougher, email phillip@lougher.org.uk, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback! ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/README-3.2 ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Squashfs 3.2 has support for NFS exporting, some improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- New command line options: -no-exports Squashfs now supports NFS exports. By default the additional information necessary is added to the filesystem by Mksquashfs. If you do not wish this extra information, then this option can be specified. This will save a couple of bytes per file, and the filesystem will be identical to Squashfs 3.1. -no-progress Mksquashfs by default now displays a progress bar. This option disables it. 2. UNSQUASHFS ------------- Unsquashfs now supports Squashfs 2.x filesystems. ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/sqlzma2u-3.2-r2.patch ================================================ Index: squashfs3.2-r2/squashfs-tools/Makefile =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/Makefile 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/Makefile 16 Jan 2007 05:08:17 -0000 1.2 @@ -1,19 +1,44 @@ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 +ifdef UseDebugFlags +DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG +endif +CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} +LDLIBS += -lz -L${LzmaAlone} -L${LzmaC} +Tgt = mksquashfs unsquashfs -all: mksquashfs unsquashfs +all: ${Tgt} -mksquashfs: mksquashfs.o read_fs.o sort.o - $(CC) mksquashfs.o read_fs.o sort.o -lz -lpthread -lm -o $@ +read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h -mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h +sort.o: sort.c squashfs_fs.h global.h sort.h -read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h +mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ + ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a -sort.o: sort.c squashfs_fs.h global.h sort.h +mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ +mksquashfs: mksquashfs.o read_fs.o sort.o + +unsquashfs.o: CFLAGS += -U_REENTRANT +unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a +unsquashfs: LDLIBS += -lunlzma unsquashfs: unsquashfs.o - $(CC) unsquashfs.o -lz -o $@ -unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h +clean: + ${RM} *~ *.o ${Tgt} + +-include test.mk + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: squashfs3.2-r2/squashfs-tools/mksquashfs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/mksquashfs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/mksquashfs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/mksquashfs.c 16 Jan 2007 05:08:17 -0000 1.2 @@ -59,6 +59,8 @@ #include "mksquashfs.h" #include "global.h" #include "sort.h" +#include "sqlzma.h" +#include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ @@ -107,6 +109,7 @@ unsigned short uid_count = 0, guid_count squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; +struct sqlzma_un un; /* write position within data section */ long long bytes = 0, total_bytes = 0; @@ -326,6 +329,7 @@ struct dir_info *dir_scan1(char *, int ( struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; +int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) @@ -593,21 +597,7 @@ unsigned int mangle2(z_stream **strm, ch BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } - stream->next_in = (unsigned char *) s; - stream->avail_in = size; - stream->next_out = (unsigned char *) d; - stream->avail_out = block_size; - - res = deflate(stream, Z_FINISH); - if(res != Z_STREAM_END && res != Z_OK) { - if(res == Z_STREAM_ERROR) - BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::compress failed, no progress possible\n"); - else - BAD_ERROR("zlib::compress failed, unknown error %d\n", res); - } - + res = sqlzma_cm(un.un_lzma, stream, s, size, d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { @@ -706,6 +696,7 @@ void write_bytes(int fd, long long byte, EXIT_MKSQUASHFS(); } + //printf("%d bytes at %Ld\n", bytes, off); if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); @@ -1220,17 +1211,17 @@ char *get_fragment(char *buffer, struct int res; unsigned long bytes = block_size; char cbuffer[block_size]; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = cbuffer, .sz = size}, + {.buf = buffer, .sz = bytes} + }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); - - if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { - if(res == Z_MEM_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); - } + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); + bytes = un.un_reslen; } else read_bytes(fd, disk_fragment->start_block, size, buffer); @@ -1623,7 +1614,7 @@ void reader_read_file(struct dir_ent *di file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; - if(file_buffer->fragment = count == frag_block) + if((file_buffer->fragment = (count == frag_block))) //?? queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); @@ -1682,6 +1673,7 @@ void *reader(void *arg) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } + return NULL; } @@ -1711,6 +1703,7 @@ void *writer(void *arg) write_error = TRUE; } + //printf("%d bytes at %Ld\n", file_buffer->size, off); if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; @@ -1830,7 +1823,7 @@ int progress_bar(long long current, long int spaces = columns - used - hashes; if(!progress || columns - used < 0) - return; + return 0; printf("\r["); @@ -1843,6 +1836,7 @@ int progress_bar(long long current, long printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); + return 0; } @@ -2479,7 +2473,7 @@ error: int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { - int squashfs_type; + int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; @@ -2774,7 +2768,8 @@ skip_inode_hash_table: printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n"); \ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; @@ -2792,6 +2787,7 @@ int main(int argc, char *argv[]) be = FALSE; #endif + un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); @@ -2947,6 +2943,8 @@ int main(int argc, char *argv[]) exit(1); } root_name = argv[i]; + } else if(strcmp(argv[i], "-nolzma") == 0) { + un.un_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { @@ -3125,8 +3123,8 @@ printOptions: printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); - compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); - uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); + compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); //?? + uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); //?? /* save original filesystem state for restoring ... */ sfragments = fragments; @@ -3193,6 +3191,11 @@ printOptions: #endif block_offset = check_data ? 3 : 2; + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + ERROR("%s:%d: %d\n", __func__, __LINE__, i); + EXIT_MKSQUASHFS(); + } if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { @@ -3211,7 +3214,9 @@ printOptions: dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; - sBlk.s_magic = SQUASHFS_MAGIC; + sBlk.s_magic = SQUASHFS_MAGIC_LZMA; + if (!un.un_lzma) + sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; Index: squashfs3.2-r2/squashfs-tools/read_fs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/read_fs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/read_fs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/read_fs.c 16 Jan 2007 05:08:17 -0000 1.2 @@ -46,6 +46,8 @@ extern int add_file(long long, long long #include #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include @@ -62,6 +64,7 @@ extern int add_file(long long, long long } while(0) int swap; +extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { @@ -81,19 +84,20 @@ int read_block(int fd, long long start, char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = buffer}, + {.buf = block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); - if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -351,18 +355,30 @@ int read_super(int fd, squashfs_super_bl /* Check it is a SQUASHFS superblock */ swap = 0; - if(sBlk->s_magic != SQUASHFS_MAGIC) { - if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); - memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } - } + switch (sBlk->s_magic) { + squashfs_super_block sblk; + + case SQUASHFS_MAGIC_LZMA: + if (!un.un_lzma) + goto bad; + break; + case SQUASHFS_MAGIC: + break; + case SQUASHFS_MAGIC_LZMA_SWAP: + if (!un.un_lzma) + goto bad; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); + memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + break; + bad: + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; + } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { @@ -416,7 +432,8 @@ unsigned char *squashfs_readdir(int fd, squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; - long long start = sBlk->directory_table_start + directory_start_block, last_start_block; + long long start = sBlk->directory_table_start + directory_start_block, + last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) Index: squashfs3.2-r2/squashfs-tools/unsquashfs.c =================================================================== RCS file: squashfs3.2-r2/squashfs-tools/unsquashfs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.2-r2/squashfs-tools/unsquashfs.c 16 Jan 2007 03:32:18 -0000 1.1 +++ squashfs3.2-r2/squashfs-tools/unsquashfs.c 16 Jan 2007 05:08:18 -0000 1.2 @@ -46,6 +46,8 @@ #include #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include @@ -97,6 +99,7 @@ unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; +struct sqlzma_un un; #define CALCULATE_HASH(start) (start & 0xffff) @@ -144,6 +147,7 @@ int read_bytes(long long byte, int bytes return FALSE; } + /* printf("%d bytes at %Ld\n", bytes, off); */ if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; @@ -175,21 +179,21 @@ int read_block(long long start, long lon char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = buffer}, + {.buf = block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - goto failed; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -216,20 +220,19 @@ int read_data_block(long long start, uns TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = data, .sz = c_byte}, + {.buf = block, .sz = bytes} + }; + if(read_bytes(start, c_byte, data) == FALSE) return 0; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) data, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } - + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) @@ -660,7 +663,7 @@ int create_inode(char *pathname, unsigne set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else - ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", + ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; @@ -818,7 +821,7 @@ int create_inode_2(char *pathname, unsig set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else - ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", + ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; @@ -1225,18 +1228,26 @@ int read_super(char *source) read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ + un.un_lzma = 1; swap = 0; - if(sBlk.s_magic != SQUASHFS_MAGIC) { - if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); - memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } + switch (sBlk.s_magic) { + squashfs_super_block sblk; + case SQUASHFS_MAGIC: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA: + break; + case SQUASHFS_MAGIC_SWAP: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); + memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; } /* Check the MAJOR & MINOR versions */ @@ -1305,14 +1316,15 @@ failed_mount: printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n"); \ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; - if(root_process = geteuid() == 0) + if((root_process = (geteuid() == 0))) //?? umask(0); for(i = 1; i < argc; i++) { @@ -1371,6 +1383,11 @@ options: EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + fputs("sqlzma_init failed", stderr); + abort(); + } read_uids_guids(); s_ops.read_fragment_table(); ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/Makefile ================================================ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 ifdef UseDebugFlags DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG endif CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} LDLIBS += -lz -lm -L${LzmaAlone} -L${LzmaC} Tgt = mksquashfs unsquashfs all: ${Tgt} read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ mksquashfs: mksquashfs.o read_fs.o sort.o unsquashfs.o: CFLAGS += -U_REENTRANT unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a unsquashfs: LDLIBS += -lunlzma unsquashfs: unsquashfs.o $(CC) unsquashfs.o -o unsquashfs $(LDLIBS) -lz clean: ${RM} *~ *.o ${Tgt} -include test.mk # Local variables: ; # compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "sqlzma.h" #include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; struct sqlzma_un un; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } struct sqlzma_opts sqopts; sqopts.try_lzma=un.un_lzma; sqopts.dicsize=64435; res = sqlzma_cm(&sqopts, stream, s, size, d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } //printf("%d bytes at %Ld\n", bytes, off); if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = cbuffer, .sz = size}, {.buf = buffer, .sz = bytes} }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); bytes = un.un_reslen; } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { char buffer2[SQUASHFS_FILE_MAX_SIZE]; long long dup_start = dupl_ptr->start; char *buffer; int block; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else buffer = read_from_disk(b->start, b->size); read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf; int count; int blocks = (buf->st_size + block_size - 1) >> block_log; int frag_block = !no_fragments && (always_use_fragments || (buf->st_size < block_size)) ? buf->st_size >> block_log : -1; int file; static int block_order = 0; struct file_buffer *file_buffer; if(buf->st_size == 0 || dir_ent->inode->read) return; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; for(count = 0; count < blocks; count ++) { file_buffer = alloc_get(reader_buffer); if((file_buffer->size = read(file, file_buffer->data, block_size)) == -1) { close(file); goto read_err2; } file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; if((file_buffer->fragment = (count == frag_block))) //?? queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); } close(file); dir_ent->inode->read = TRUE; return; read_err: file_buffer = alloc_get(reader_buffer); read_err2: file_buffer->block_order = block_order ++; file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } return NULL; } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } //printf("%d bytes at %Ld\n", file_buffer->size, off); if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } int write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } int write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; struct file_buffer *file_buffer = get_file_buffer(from_deflate); if(file_buffer->error) { alloc_free(file_buffer); return FALSE; } checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) return write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size) { int block, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return FALSE; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, int *duplicate_file) { int block, status, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return FALSE; } int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", dir_ent->pathname, SQUASHFS_MAX_FILE_SIZE); if(read_size == 0) return write_file_empty(inode, dir_ent, duplicate_file); if(!no_fragments && (read_size < block_size)) return write_file_frag(inode, dir_ent, read_size, duplicate_file); if(pre_duplicate(read_size)) return write_file_blocks_dup(inode, dir_ent, read_size, duplicate_file); *duplicate_file = FALSE; return write_file_blocks(inode, dir_ent, read_size); } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, reader_buffer_size); writer_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, writer_buffer_size); fragment_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } #define VERSION() \ printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); \ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { un.un_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); //?? uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); //?? /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { ERROR("%s:%d: %d\n", __func__, __LINE__, i); EXIT_MKSQUASHFS(); } if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC_LZMA; if (!un.un_lzma) sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = buffer}, {.buf = block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC_LZMA: if (!un.un_lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_LZMA_SWAP: if (!un.un_lzma) goto bad; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-lzma/squashfs3.2-r2/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); int (*create_inode)(char *pathname, unsigned int start_block, unsigned int offset); } squashfs_operations; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; struct sqlzma_un un; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } /* printf("%d bytes at %Ld\n", bytes, off); */ if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = buffer}, {.buf = block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = data, .sz = c_byte}, {.buf = block, .sz = bytes} }; if(read_bytes(start, c_byte, data) == FALSE) return 0; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } int create_inode_2(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header_2 header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, sBlk.mkfs_time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header_2 header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } int matches(char *targname, char *name) { if(*targname == '\0' || strcmp(targname, name) == 0) return TRUE; return FALSE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, char *target) { struct dir *dir = s_ops.squashfs_opendir(start_block, offset); unsigned int type; char *name, pathname[1024]; char targname[1024]; target = get_component(target, targname); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(targname, name)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, target); else if(!lsonly) s_ops.create_inode(pathname, start_block, offset); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ un.un_lzma = 1; swap = 0; switch (sBlk.s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.create_inode = create_inode_2; } else if(sBlk.s_major == 3 && sBlk.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.create_inode = create_inode; } else { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk.s_major, sBlk.s_minor); ERROR("I support Squashfs 2.x and 3.0 filesystems!\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk.block_size); TRACE("\tNumber of fragments %d\n", sBlk.fragments); TRACE("\tNumber of inodes %d\n", sBlk.inodes); TRACE("\tNumber of uids %d\n", sBlk.no_uids); TRACE("\tNumber of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.3 (2007/01/02)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); \ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; if((root_process = (geteuid() == 0))) //?? umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) goto options; dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directory or file to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-l[s]\t\t\tlist filesystem only\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); } exit(1); } if((i + 1) < argc) target = argv[i + 1]; if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { fputs("sqlzma_init failed", stderr); abort(); } read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), target); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/Makefile ================================================ CC = gcc SRCBASE = . INCLUDEDIR = -I$(SRCBASE)/include -I. LZMADIR = $(SRCBASE)/lzma_src/C CFLAGS := $(INCLUDEDIR) -I$(LZMADIR) -I$(LINUXDIR)/include -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 LZMAOBJS = LzmaEnc.o LzFind.o LzmaDec.o MKOBJS = mksquashfs.o read_fs.o sort.o sqlzma.o all: mksquashfs unsquashfs $(LZMAOBJS): %.o: $(LZMADIR)/%.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $^ -o $@ mksquashfs: $(MKOBJS) $(LZMAOBJS) $(CC) $(MKOBJS) $(LZMAOBJS) -lz -lpthread -lm -lstdc++ -o $@ unsquashfs: unsquashfs.o $(LZMAOBJS) $(CC) unsquashfs.o sqlzma.o $(LZMAOBJS) -lz -lpthread -lm -o $@ clean: -rm -f *.o mksquashfs unsquashfs install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #ifndef BCMLZMA #include #endif #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; int src = (int)pos - (int)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #include /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { /* The default dictionary size is 16M, it is too big for CFE heap memory size (400K). * The lzma_compression_level is between 1 to 5 and dictionary size is * (1<< (lzma_compression_level*2+14)). */ p->level = 1; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1); } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/lzma_src/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #ifndef BCMLZMA #include #endif #ifdef _WIN32 #include #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif #ifndef Byte typedef unsigned char Byte; #endif typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include "squashfs_fs.h" #include "sqmagic.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "LzmaEnc.h" #include "Alloc.h" #include "sqlzma.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; int lzma = 1; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 struct squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if (!lzma) { if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } } /* broadcom start */ else { res = LzmaCompress(s, size, d, block_size, &c_byte); if (res) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } } /* broadcom end */ return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if (!lzma) { if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } /* LZMA */ else { if((res = LzmaUncompress(buffer, &bytes, cbuffer, size)) != SZ_OK) BAD_ERROR("LzmaUncompress: error (%d)\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { char buffer2[SQUASHFS_FILE_MAX_SIZE]; long long dup_start = dupl_ptr->start; char *buffer; int block; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else buffer = read_from_disk(b->start, b->size); read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf; int count; int blocks = (buf->st_size + block_size - 1) >> block_log; int frag_block = !no_fragments && (always_use_fragments || (buf->st_size < block_size)) ? buf->st_size >> block_log : -1; int file; static int block_order = 0; struct file_buffer *file_buffer; if(buf->st_size == 0 || dir_ent->inode->read) return; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; for(count = 0; count < blocks; count ++) { file_buffer = alloc_get(reader_buffer); if((file_buffer->size = read(file, file_buffer->data, block_size)) == -1) { close(file); goto read_err2; } file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; if((file_buffer->fragment = (count == frag_block))) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); } close(file); dir_ent->inode->read = TRUE; return; read_err: file_buffer = alloc_get(reader_buffer); read_err2: file_buffer->block_order = block_order ++; file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } return NULL; } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } int write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } int write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; struct file_buffer *file_buffer = get_file_buffer(from_deflate); if(file_buffer->error) { alloc_free(file_buffer); return FALSE; } checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) return write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size) { int block, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return FALSE; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, int *duplicate_file) { int block, status, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return FALSE; } int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", dir_ent->pathname, SQUASHFS_MAX_FILE_SIZE); if(read_size == 0) return write_file_empty(inode, dir_ent, duplicate_file); if(!no_fragments && (read_size < block_size)) return write_file_frag(inode, dir_ent, read_size, duplicate_file); if(pre_duplicate(read_size)) return write_file_blocks_dup(inode, dir_ent, read_size, duplicate_file); *duplicate_file = FALSE; return write_file_blocks(inode, dir_ent, read_size); } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, reader_buffer_size); writer_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, writer_buffer_size); fragment_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } #define VERSION() \ printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem using %s on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, lzma ? "LZMA" : "GZIP", argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; if (lzma) sBlk.s_magic = SQUASHFS_MAGIC_LZMA; else sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include "squashfs_fs.h" #include "sqmagic.h" #include "read_fs.h" #include "global.h" #include "LzmaDec.h" #include "sqlzma.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern int lzma; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if(!lzma) { if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } } /* lzma */ else { if((res = LzmaUncompress(block, &bytes, buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { squashfs_super_block sblk; read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { case SQUASHFS_MAGIC_LZMA: if (!lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include "squashfs_fs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/sqlzma.c ================================================ /* * squashfs with lzma compression * * Copyright (C) 2008, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: sqlzma.c,v 1.3 2009/03/10 08:42:14 Exp $ */ #include #include #include #include #include "LzmaDec.h" #include "LzmaEnc.h" #include "sqlzma.h" static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } static void SzFree(void *p, void *address) { p = p; free(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen) { int res; SizeT inSizePure; ELzmaStatus status; if (srclen < LZMA_PROPS_SIZE) { memcpy(dst, src, srclen); return srclen; } inSizePure = srclen - LZMA_PROPS_SIZE; res = LzmaDecode(dst, dstlen, src + LZMA_PROPS_SIZE, &inSizePure, src, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); srclen = inSizePure ; if ((res == SZ_OK) || ((res == SZ_ERROR_INPUT_EOF) && (srclen == inSizePure))) res = 0; if (res != SZ_OK) printf("LzmaUncompress: error (%d)\n", res); return res; } int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out) { CLzmaEncProps props; size_t headerSize = LZMA_PROPS_SIZE; int ret; SizeT outProcess; LzmaEncProps_Init(&props); props.algo = 1; outProcess = out_size - LZMA_PROPS_SIZE; ret = LzmaEncode(out_data+LZMA_PROPS_SIZE, &outProcess, in_data, in_size, &props, out_data, &headerSize, 0, NULL, &g_Alloc, &g_Alloc); *total_out = outProcess + LZMA_PROPS_SIZE; return ret; } ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/sqlzma.h ================================================ /* * squashfs with lzma compression * * Copyright (C) 2008, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: sqlzma.h,v 1.3 2009/03/10 08:42:14 Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include #include #endif /* * detect the compression method automatically by the first byte of compressed * data. */ #define is_lzma(c) (c == 0x5d) int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen); int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out); #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/sqmagic.h ================================================ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #else #define SQUASHFS_CACHED_FRAGMENTS 3 #endif #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-rtn12/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "LzmaDec.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); int (*create_inode)(char *pathname, unsigned int start_block, unsigned int offset); } squashfs_operations; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if (!is_lzma(buffer[0])) { if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } } else { if((res = LzmaUncompress(block, &bytes, buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if (!is_lzma(data[0])) { if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } } /* LZMA */ else { if((res = LzmaUncompress(block, &bytes, data, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } int create_inode_2(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header_2 header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, sBlk.mkfs_time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header_2 header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } int matches(char *targname, char *name) { if(*targname == '\0' || strcmp(targname, name) == 0) return TRUE; return FALSE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, char *target) { struct dir *dir = s_ops.squashfs_opendir(start_block, offset); unsigned int type; char *name, pathname[1024]; char targname[1024]; target = get_component(target, targname); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(targname, name)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, target); else if(!lsonly) s_ops.create_inode(pathname, start_block, offset); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(char *source) { squashfs_super_block sblk; read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk.s_magic) { case SQUASHFS_MAGIC: case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.create_inode = create_inode_2; } else if(sBlk.s_major == 3 && sBlk.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.create_inode = create_inode; } else { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk.s_major, sBlk.s_minor); ERROR("I support Squashfs 2.x and 3.0 filesystems!\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk.block_size); TRACE("\tNumber of fragments %d\n", sBlk.fragments); TRACE("\tNumber of inodes %d\n", sBlk.inodes); TRACE("\tNumber of uids %d\n", sBlk.no_uids); TRACE("\tNumber of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.3 (2007/01/02)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; if((root_process = (geteuid() == 0))) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) goto options; dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directory or file to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-l[s]\t\t\tlist filesystem only\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); } exit(1); } if((i + 1) < argc) target = argv[i + 1]; if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), target); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/Makefile ================================================ CC = gcc LZMADIR = ./lzma_src/C CFLAGS := -I$(LZMADIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 LZMAOBJS = LzmaEnc.o LzFind.o LzmaDec.o MKOBJS = mksquashfs.o read_fs.o sort.o sqlzma.o all: mksquashfs unsquashfs $(LZMAOBJS): %.o: $(LZMADIR)/%.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $^ -o $@ mksquashfs: $(MKOBJS) $(LZMAOBJS) $(CC) $(MKOBJS) $(LZMAOBJS) -lz -lpthread -lm -lstdc++ -o $@ unsquashfs: unsquashfs.o $(LZMAOBJS) $(CC) unsquashfs.o sqlzma.o $(LZMAOBJS) -lz -lpthread -lm -o $@ clean: -rm -f *.o mksquashfs unsquashfs install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #ifndef BCMLZMA #include #endif #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; int src = (int)pos - (int)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #include /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { /* The default dictionary size is 16M, it is too big for CFE heap memory size (400K). * The lzma_compression_level is between 1 to 5 and dictionary size is * (1<< (lzma_compression_level*2+14)). */ p->level = 1; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1); } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/lzma_src/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #ifndef BCMLZMA #include #endif #ifdef _WIN32 #include #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif #ifndef Byte typedef unsigned char Byte; #endif typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include "squashfs_fs.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "LzmaEnc.h" #include "Alloc.h" #include "sqlzma.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; int lzma = 1; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 struct squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if (!lzma) { if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } } /* broadcom start */ else { res = LzmaCompress(s, size, d, block_size, &c_byte); if (res) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } } /* broadcom end */ return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if (!lzma) { if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } /* LZMA */ else { if((res = LzmaUncompress(buffer, &bytes, cbuffer, size)) != SZ_OK) BAD_ERROR("LzmaUncompress: error (%d)\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { char buffer2[SQUASHFS_FILE_MAX_SIZE]; long long dup_start = dupl_ptr->start; char *buffer; int block; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else buffer = read_from_disk(b->start, b->size); read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf; int count; int blocks = (buf->st_size + block_size - 1) >> block_log; int frag_block = !no_fragments && (always_use_fragments || (buf->st_size < block_size)) ? buf->st_size >> block_log : -1; int file; static int block_order = 0; struct file_buffer *file_buffer; if(buf->st_size == 0 || dir_ent->inode->read) return; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; for(count = 0; count < blocks; count ++) { file_buffer = alloc_get(reader_buffer); if((file_buffer->size = read(file, file_buffer->data, block_size)) == -1) { close(file); goto read_err2; } file_buffer->block = count; file_buffer->block_order = block_order ++; file_buffer->error = FALSE; if((file_buffer->fragment = (count == frag_block))) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); } close(file); dir_ent->inode->read = TRUE; return; read_err: file_buffer = alloc_get(reader_buffer); read_err2: file_buffer->block_order = block_order ++; file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } return NULL; } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } int write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } int write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; struct file_buffer *file_buffer = get_file_buffer(from_deflate); if(file_buffer->error) { alloc_free(file_buffer); return FALSE; } checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) return write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); return dir_ent->inode->nlink == 1 ? create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL) : create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size) { int block, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return FALSE; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, int *duplicate_file) { int block, status, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; block_list[block] = read_buffer->c_byte; read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return FALSE; } int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", dir_ent->pathname, SQUASHFS_MAX_FILE_SIZE); if(read_size == 0) return write_file_empty(inode, dir_ent, duplicate_file); if(!no_fragments && (read_size < block_size)) return write_file_frag(inode, dir_ent, read_size, duplicate_file); if(pre_duplicate(read_size)) return write_file_blocks_dup(inode, dir_ent, read_size, duplicate_file); *duplicate_file = FALSE; return write_file_blocks(inode, dir_ent, read_size); } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, reader_buffer_size); writer_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, writer_buffer_size); fragment_buffer = alloc_init(SQUASHFS_FILE_MAX_SIZE, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } #define VERSION() \ printf("mksquashfs version 3.2-r2 (2007/01/15)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem using %s on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, lzma ? "LZMA" : "GZIP", argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; if (lzma) sBlk.s_magic = SQUASHFS_MAGIC_LZMA; else sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "LzmaDec.h" #include "sqlzma.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern int lzma; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if(!lzma) { if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } } /* lzma */ else { if((res = LzmaUncompress(block, &bytes, buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { squashfs_super_block sblk; read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { case SQUASHFS_MAGIC_LZMA: if (!lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include "squashfs_fs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/sqlzma.c ================================================ /* * squashfs with lzma compression * * Copyright (C) 2008, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: sqlzma.c,v 1.3 2009/03/10 08:42:14 Exp $ */ #include #include #include #include #include "LzmaDec.h" #include "LzmaEnc.h" #include "sqlzma.h" static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } static void SzFree(void *p, void *address) { p = p; free(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen) { int res; SizeT inSizePure; ELzmaStatus status; if (srclen < LZMA_PROPS_SIZE) { memcpy(dst, src, srclen); return srclen; } inSizePure = srclen - LZMA_PROPS_SIZE; res = LzmaDecode(dst, dstlen, src + LZMA_PROPS_SIZE, &inSizePure, src, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); srclen = inSizePure ; if ((res == SZ_OK) || ((res == SZ_ERROR_INPUT_EOF) && (srclen == inSizePure))) res = 0; if (res != SZ_OK) printf("LzmaUncompress: error (%d)\n", res); return res; } int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out) { CLzmaEncProps props; size_t headerSize = LZMA_PROPS_SIZE; int ret; SizeT outProcess; LzmaEncProps_Init(&props); props.algo = 1; outProcess = out_size - LZMA_PROPS_SIZE; ret = LzmaEncode(out_data+LZMA_PROPS_SIZE, &outProcess, in_data, in_size, &props, out_data, &headerSize, 0, NULL, &g_Alloc, &g_Alloc); *total_out = outProcess + LZMA_PROPS_SIZE; return ret; } ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/sqlzma.h ================================================ /* * squashfs with lzma compression * * Copyright (C) 2008, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: sqlzma.h,v 1.3 2009/03/10 08:42:14 Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include #include #endif /* * detect the compression method automatically by the first byte of compressed * data. */ #define is_lzma(c) (c == 0x5d) int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen); int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out); #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #else #define SQUASHFS_CACHED_FRAGMENTS 3 #endif #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.2-r2-wnr1000/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "LzmaDec.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); int (*create_inode)(char *pathname, unsigned int start_block, unsigned int offset); } squashfs_operations; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE; char **created_inode; int root_process; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if (!is_lzma(buffer[0])) { if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } } else { if((res = LzmaUncompress(block, &bytes, buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if (!is_lzma(data[0])) { if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } } /* LZMA */ else { if((res = LzmaUncompress(block, &bytes, data, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } int create_inode_2(char *pathname, unsigned int start_block, unsigned int offset) { long long start = sBlk.inode_table_start + start_block; squashfs_inode_header_2 header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, force); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(force) unlink(pathname); if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, sBlk.mkfs_time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, sBlk.mkfs_time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start = sBlk.inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header_2 header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk.directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } int matches(char *targname, char *name) { if(*targname == '\0' || strcmp(targname, name) == 0) return TRUE; return FALSE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, char *target) { struct dir *dir = s_ops.squashfs_opendir(start_block, offset); unsigned int type; char *name, pathname[1024]; char targname[1024]; target = get_component(target, targname); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(targname, name)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, target); else if(!lsonly) s_ops.create_inode(pathname, start_block, offset); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(char *source) { squashfs_super_block sblk; read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk.s_magic) { case SQUASHFS_MAGIC: case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.create_inode = create_inode_2; } else if(sBlk.s_major == 3 && sBlk.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.create_inode = create_inode; } else { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk.s_major, sBlk.s_minor); ERROR("I support Squashfs 2.x and 3.0 filesystems!\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else TRACE("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk.block_size); TRACE("\tNumber of fragments %d\n", sBlk.fragments); TRACE("\tNumber of inodes %d\n", sBlk.inodes); TRACE("\tNumber of uids %d\n", sBlk.no_uids); TRACE("\tNumber of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.3 (2007/01/02)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, version = FALSE; char *target = ""; if((root_process = (geteuid() == 0))) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) goto options; dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directory or file to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-l[s]\t\t\tlist filesystem only\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); } exit(1); } if((i + 1) < argc) target = argv[i + 1]; if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), target); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.3/Makefile ================================================ CC := gcc CXX := g++ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 LZMAPATH = ../../lzma/C/7zip/Compress/LZMA_Lib all: mksquashfs unsquashfs # mksquashfs-lzma unsquashfs-lzma mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lpthread -lz -lm -o $@ #mksquashfs-lzma: mksquashfs.o read_fs.o sort.o # make -C $(LZMAPATH) # $(CXX) -O3 mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -lpthread -lm -llzma -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h #unsquashfs-lzma: unsquashfs.o # make -C $(LZMAPATH) # $(CXX) -O3 unsquashfs.o -L$(LZMAPATH) -llzma -o $@ unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h clean: rm -f *.o rm -f mksquashfs rm -f unsquashfs rm -f mksquashfs-lzma rm -f unsquashfs-lzma rm -f mksquashfs.exe rm -f unsquashfs.exe rm -f mksquashfs-lzma.exe rm -f unsquashfs-lzma.exe make -C $(LZMAPATH) clean ================================================ FILE: src/others/squashfs-3.3/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.3/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include #else #include #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { long long file_size; struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %d, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %d is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n"); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL); #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else if(b->size != 0) chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_MAX_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } char buffer2[SQUASHFS_FILE_MAX_SIZE]; struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long dup_start = dupl_ptr->start; char *buffer; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else if(b->size) buffer = read_from_disk(b->start, b->size); else continue; read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int block_order = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = alloc_get(reader_buffer); byte = file_buffer->size = read(file, file_buffer->data, block_size); file_buffer->block_order = block_order ++; file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read(file, &buffer, 1) == 1) goto restat; } if(file_buffer->fragment = file_buffer->block == frag_block) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = alloc_get(reader_buffer); file_buffer->block_order = block_order ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); if(sparse_files && all_zero(file_buffer)) write_buffer->c_byte = 0; else write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; int status; *duplicate_file = FALSE; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else alloc_free(read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; int status; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; } else { buffer_list[block].read_buffer = NULL; alloc_free(read_buffer); } buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); if(status = read_buffer->error) { alloc_free(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); alloc_free(read_buffer); } else if(!no_fragments && (read_size < block_size)) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, new, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; #if 0 default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; #endif } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(block_size, reader_buffer_size); writer_buffer = alloc_init(block_size, writer_buffer_size); fragment_buffer = alloc_init(block_size, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB)) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing exclude which subsumes the exclude currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific excludes, delete as they're subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with -wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories in the * filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n"); read_bytes(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) BAD_ERROR("Failed to create recovery file, because %s. Aborting\n", strerror(errno)); if(write(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int readbytes; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n"); if((readbytes = read(recoverfd, metadata, bytes)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(readbytes != bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_bytes(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 3.3 (2007/10/31)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; int s_minor; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-recover \t\trecover filesystem data using recovery file \n"); ERROR("-no-recovery\t\tdon't generate a recovery file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors \tUse processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue \tSet input queue to Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue \tSet output queue to Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); if(block_size <= 65536 && sparse_files == FALSE) s_minor = 0; else s_minor = SQUASHFS_MINOR; for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } be = orig_be; block_log = slog(block_size = sBlk.block_size); s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { int uid = uids[i]; struct passwd *user = getpwuid(uid); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } return 0; } ================================================ FILE: src/others/squashfs-3.3/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.3/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.3/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.3/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.3/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.3/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.2 2006-11-27 03:54:58 jro Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.3/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.3/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define _GNU_SOURCE #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "sqmagic.h" #include "global.h" #include #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("unsquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ exit(1); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(char *pathname, unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, unsigned char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; struct test { int mask; int value; int position; char mode; }; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, unsigned char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, unsigned char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int lseek_broken = FALSE; char *zero_data; long long hole; int write_block(int file_fd, char *buffer, int size) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } hole = 0; } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } int write_file(long long file_size, char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; int file_end = file_size / block_size; TRACE("write_file: regular file, blocks %d\n", blocks); hole = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } s_ops.read_block_list(block_list, block_ptr, blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if(block_list[i] == 0) { /* sparse file */ hole += i == file_end ? file_size & (block_size - 1) : block_size; continue; } if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write_block(file_fd, file_data, bytes) == FALSE) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write_block(file_fd, fragment_data + offset, frag_bytes) == FALSE) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } if(hole) { /* corner case for hole extending to end of file */ hole --; if(write_block(file_fd, "\0", 1) == FALSE) { ERROR("write_file: failed to write sparse data block\n"); goto failure; } } close(file_fd); free(block_list); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i->data, pathname, i->fragment, i->frag_bytes, i->offset, i->blocks, i->start, i->block_ptr, i->mode)) { set_attributes(pathname, i->mode, i->uid, i->gid, i->time, force); file_count ++; } break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %d\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%x\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB)) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { struct dir *dir = s_ops.squashfs_opendir(parent_name, start_block, offset); unsigned int type; char *name, pathname[1024]; struct pathnames *new; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) create_inode(pathname, i); } free_subdir(new); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk.s_magic != SQUASHFS_MAGIC && sBlk.s_magic != SQUASHFS_MAGIC_LZMA) { if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP || sBlk.s_magic == SQUASHFS_MAGIC_LZMA_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } #define VERSION() \ printf("unsquashfs version 1.5 (2007/10/31)\n");\ printf("copyright (C) 2007 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; char **target_name = NULL; int n, targets = 0; struct pathnames *paths = NULL; struct pathname *path = NULL; if(root_process = geteuid() == 0) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-d[est] \tunsquash to , default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] \tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/.tmpdeps ================================================ t/squashfs-lzma t/lzma t/sqlzma t/ksquashfs ================================================ FILE: src/others/squashfs-3.3-grml-lzma/.topdeps ================================================ squashfs ================================================ FILE: src/others/squashfs-3.3-grml-lzma/.topmsg ================================================ From: Michael Gebetsroither Subject: [PATCH] t/squashfs-lzma squashfs lzma patch Signed-off-by: Michael Gebetsroither ================================================ FILE: src/others/squashfs-3.3-grml-lzma/Makefile ================================================ # Copyright (C) 2006-2008 Junjiro Okajima # Copyright (C) 2006-2008 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: Makefile,v 1.30 2008-03-12 16:24:54 jro Exp $ # paths Sqlzma = ${CURDIR} LzmaVer = lzma Lzma = ${Sqlzma}/${LzmaVer} SqVer = squashfs3.3 Squashfs = ${Sqlzma}/${SqVer} KVer = linux-2.6.24.3 SqFs = ${Squashfs}/kernel-patches/${KVer}/fs/squashfs #KDir = /lib/modules/$(shell uname -r)/build ifeq (${LzmaVer}, lzma443) LzmaC = ${Lzma}/C/7zip/Compress/LZMA_C LzmaAlone = ${Lzma}/C/7zip/Compress/LZMA_Alone else LzmaC = ${Lzma}/C/Compress/Lzma LzmaAlone = ${Lzma}/CPP/7zip/Compress/LZMA_Alone endif SqTools = ${Squashfs}/squashfs-tools # enable it if you want to add -g option when compiling UseDebugFlags = # disable it if you don't want to compile squashfs kernel module here #BuildSquashfs = 1 export all: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ clean: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ ${RM} *~ ######################################## -include priv.mk ifdef BuildSquashfs CONFIG_SQUASHFS = m CONFIG_SQUASHFS_EMBEDDED = CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE = 3 EXTRA_CFLAGS = -I${Sqlzma} -I${SqFs}/../../include -Wall -Werror EXTRA_CFLAGS += -DCONFIG_SQUASHFS_MODULE -UCONFIG_SQUASHFS EXTRA_CFLAGS += -UCONFIG_SQUASHFS_EMBEDDED -DCONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # if you enabled CONFIG_PREEMPT, but want CPU to try concentrating # the uncompression, then define UnsquashNoPreempt. # if you don't define UnsquashNoPreempt, the behaviour follows # the CONFIG_PREEMPT. EXTRA_CFLAGS += -DUnsquashNoPreempt export # the environment variables are not inherited since 2.6.23 MAKE += SQLZMA_EXTRA_CFLAGS="$(shell echo ${EXTRA_CFLAGS} | sed -e 's/\"/\\\\\\"/g')" all: all_sq FORCE: all_sq: ${MAKE} -C ${KDir} M=${SqFs} modules clean: clean_sq clean_sq: ${MAKE} -C ${KDir} M=${SqFs} clean endif ######################################## load: for i in ${LzmaC}/kmod/unlzma.ko ${LzmaC}/kmod/sqlzma.ko \ ${SqFs}/squashfs.ko; \ do sudo insmod $$i; done unload: -sudo rmmod squashfs sqlzma unlzma ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/changelog ================================================ squashfs-lzma (3.3-1) unstable; urgency=low [ Michael Gebetsroither ] * Initial release [Closes: issue465] [ Michael Prokop ] * Fix build of squashfs-lzma-source. * Bump Standard Version to 3.8.0 (no further changes). * Add myself to uploaders. -- Michael Prokop Tue, 16 Sep 2008 12:53:30 +0200 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/compat ================================================ 5 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/control ================================================ Source: squashfs-lzma Section: admin Priority: optional Maintainer: Michael Gebetsroither Uploaders: Michael Prokop Build-Depends: cdbs (>= 0.4.23-1.1), patchutils (>= 0.2.25), debhelper (>= 5), zlib1g-dev, po4a (>= 0.21), xsltproc, docbook-xsl, bzip2, binutils-hppa64 [hppa], gcc-4.2-hppa64 [hppa], docbook-xml Standards-Version: 3.8.0 Homepage: http://squashfs.sourceforge.net/ XS-Vcs-git: git://git.grml.org/squashfs-lzma.git XS-Vcs-Browser: http://git.grml.org/?p=squashfs-lzma.git Package: squashfs-lzma-tools Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: squashfs-tools Provides: squashfs-tools Conflicts: squashfs-tools Suggests: squashfs-source Description: Tool to create and append to squashfs filesystems Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. . Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. . This version supports lzma for http://grml.org. Package: squashfs-lzma-source Architecture: all Depends: module-assistant, debhelper (>= 5), make, bzip2, zlib1g-dev Recommends: squashfs-tools Conflicts: kernel-patch-squashfs Replaces: kernel-patch-squashfs Description: Source for the squash filesystem Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. . Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. . This package provides the source code for the squashfs kernel modules. The squashfs-tools package is also required in order to make use of these modules. Kernel source or headers are required to compile these modules. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/control.modules.in ================================================ Source: squashfs-lzma Section: misc Priority: optional Maintainer: Michael Gebetsroither Build-Depends: debhelper (>= 5), linux-headers-_KVERS_, zlib1g-dev Standards-Version: 3.7.3 Homepage: http://squashfs.sourceforge.net/ Package: squashfs-lzma-modules-_KVERS_ Architecture: any Provides: squashfs-modules Depends: linux-modules-_KVERS_ | linux-image-_KVERS_ Description: Squash filesystem support for Debian Linux kernels Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. . Squashfs is intended for general read-only filesystem use, for archival use (e.g. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. . This package contains the compiled kernel module for _KVERS_ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/copyright ================================================ This package was debianized by Michael Gebetsroither on Thu, 04 Sep 2008 18:15:47 +0200. It was downloaded from http://www.squashfs-lzma.org/ Copyright: Upstream Author: Phillip Lougher (plougher@users.sourceforge.net) License: This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991. This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. On Debian systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL-2'. The Debian packaging is (C) 2008, Michael Gebetsroither and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/en/mksquashfs.dbk ================================================ .
will be generated. You may view the manual page with: nroff -man .
| less'. A typical entry in a Makefile or Makefile.am is: DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ manpages/docbook.xsl XP=xsltproc -''-nonet manpage.1: manpage.dbk $(XP) $(DB2MAN) $< The xsltproc binary is found in the xsltproc package. The XSL files are in docbook-xsl. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include xsltproc and docbook-xsl in your Build-Depends control field. --> Frédéric"> Boiteux"> december 20, 2004"> 1"> fboiteux@calistel.com"> MKSQUASHFS"> Debian"> GNU"> GPL"> ]>
&dhemail;
2005 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Create or modify a Squash file system &dhpackage; &dhpackage; source dest DESCRIPTION A squashfs is a compressed read-only file system. Use the &dhpackage; program to create a new squashed file system, and to append new data to an existing squashed file system. If a single source directory is specified (i.e. mksquashfs source output_fs), the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, &dhpackage; will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. The dest argument can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, &dhpackage; will append. The option will write a new filesystem irrespective of whether an existing filesystem is present. There are a large number of options that can be used to control the compression in &dhpackage;. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances ! The , and options (also , and ) can be used to force &dhpackage; to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, &dhpackage; provides a number of options which can be used to override the ownership: The options and (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. root) or by number. The option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. root) or by number. The and options allow files/directories to be specified which are excluded from the output filesystem. The option takes the exclude files/directories from the command line, the option takes the exlude files/directories from the specified exclude file, one file/directory per line. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. The and exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple options can be specified on the command line, and the option can be used in conjuction with the option. The option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The option doesn't make the filesystem exportable via NFS. The option doesn't display the progress bar. The and options can be used to force &dhpackage; to generate a little endian or big endian filesystem. Normally &dhpackage; will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. OPTIONS print version, licence and copyright message. Allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure) using recovery file name. Recovery files are now created when appending to existing Squashfs filesystems. don't generate a recovery file print files written to filesystem don't make the filesystem exportable via NFS don't display the progress bar don't detect sparse files set data block to block_size. Default is 131072 bytes Use number processors. By default will use number of processors available Set input queue to size Mbytes. Default 64 Mbytes. Set output queue to size Mbytes. Default 512 Mbytes. or do not compress inode table or do not compress data blocks or do not compress fragment blocks do not use fragments: tells &dhpackage; to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. use fragment blocks for files larger than block size: tells &dhpackage; to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. do not perform duplicate checking: tells &dhpackage; to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. do not append to existing filesystem if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory when appending source files/directories, make the original root become a subdirectory in the new root called name, rather than adding the new source items to the original root or make all files owned by root set all file uids to uid set all file gids to gid create a little endian filesystem create a big endian filesystem do not pad filesystem to a multiple of 4Ko. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. add checkdata for greater filesystem checks sort files according to priorities in sort_file. One file or dir with priority per line. Priority -32768 to 32767, default priority 0 inline list of files / directories to exclude file containing a list of files / directories to exclude, one per line Allow extended shell wildcards (globbing) to be used in exclude dirs/files Allow POSIX regular expressions to be used in exclude dirs/files EXAMPLES For following examples, take two example directories: Source directory /home/phillip/test contains file1, file2 and dir1. Source directory goodies contains goodies1, goodies2 and goodies3. mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries file1, file2 and dir1. mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries test and goodies corresponding to the source directories /home/phillip/test and goodies. mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory test has been specified. This conflicts with the first directory named test and will be renamed test_1. Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as the first example, except for . This will generate a root directory containing directory test, rather than the test directory contents file1, file2 and dir1. AUTHORS Squashfs was written by Phillip Lougher plougher@users.sourceforge.net, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback ! This manual page was written by &dhusername; &dhemail; for the &debian; system (but may be used by others) using the SquashFS HOWTO from Artemiy I. Pavlov and squashfs's README file. Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 any later version published by the Free Software Foundation. On Debian systems, the complete text of the &gnu; General Public License can be found in /usr/share/common-licenses/GPL.
================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/en/unsquashfs.dbk ================================================ .
will be generated. You may view the manual page with: nroff -man .
| less'. A typical entry in a Makefile or Makefile.am is: DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ manpages/docbook.xsl XP=xsltproc -''-nonet manpage.1: manpage.dbk $(XP) $(DB2MAN) $< The xsltproc binary is found in the xsltproc package. The XSL files are in docbook-xsl. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include xsltproc and docbook-xsl in your Build-Depends control field. --> Arnaud"> Fontaine"> november 02, 2006"> 1"> arnau@debian.org"> UNSQUASHFS"> Debian"> GNU"> GPL"> ]>
&dhemail;
2006 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Decompress and extract a Squash file system &dhpackage; &dhpackage; &dhpackage; filesystem to_extract DESCRIPTION A squashfs is a compressed read-only file system. Use the &dhpackage; program to decompress and extract a Squash file system without mounting it. &dhpackage; is able to extract the entire file system or a specific file or directory. OPTIONS print version, licence and copyright message. print files as they are unsquashed. print files as they are unsquashed with file attributes (like ls -l output). list filesystem only, doesn't decompress anything. list filesystem only with file attributes, doesn't decompress anything. decompress to pathname. This default to squashfs-root. if file already exists then overwrite. display filesystem superblock information. list of directories or files to extract. One per line. treat extract names as POSIX regular expressions rather than use the default shell wildcard expansion (globbing). AUTHORS Squashfs was written by Phillip Lougher plougher@users.sourceforge.net, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback ! This manual page was written by &dhusername; &dhemail; for the &debian; system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 any later version published by the Free Software Foundation. On Debian systems, the complete text of the &gnu; General Public License can be found in /usr/share/common-licenses/GPL.
================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/po/mksquashfs.fr.add ================================================ PO4A-HEADER:position=AUTEURS;mode=after;beginboundary= Traduction française : &dhusername; &dhemail;. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/po/mksquashfs.fr.po ================================================ # mksquashfs's manpages translation to French # Copyright (C) 2005 Free Software Foundation, Inc. # Frédéric Boiteux , 2005. msgid "" msgstr "" "Project-Id-Version: squashfs\n" "POT-Creation-Date: 2008-04-05 09:29-0300\n" "PO-Revision-Date: 2007-08-08 17:23+0100\n" "Last-Translator: Arnaud Fontaine \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" # type: Content of the dhfirstname entity #: ../en/mksquashfs.dbk:30 msgid "Frédéric" msgstr "Frédéric" # type: Content of the dhsurname entity #: ../en/mksquashfs.dbk:31 msgid "Boiteux" msgstr "Boiteux" # type: Content of the dhdate entity #: ../en/mksquashfs.dbk:34 msgid "december 20, 2004" msgstr "december 20, 2004" # type: Content of the dhsection entity #: ../en/mksquashfs.dbk:38 msgid "1" msgstr "1" # type: Content of the dhemail entity #: ../en/mksquashfs.dbk:39 msgid "fboiteux@calistel.com" msgstr "fboiteux@calistel.com" # type: Content of the dhusername entity #: ../en/mksquashfs.dbk:40 msgid "Frédéric Boiteux" msgstr "Frédéric Boiteux" # type: Content of the dhucpackage entity #: ../en/mksquashfs.dbk:41 msgid "MKSQUASHFS" msgstr "MKSQUASHFS" # type: Content of the dhpackage entity #: ../en/mksquashfs.dbk:42 msgid "mksquashfs" msgstr "mksquashfs" # type: Content of the debian entity #: ../en/mksquashfs.dbk:44 msgid "Debian" msgstr "Debian" # type: Content of the gnu entity #: ../en/mksquashfs.dbk:45 msgid "GNU" msgstr "GNU" # type: Content of the gpl entity #: ../en/mksquashfs.dbk:46 msgid "&gnu; GPL" msgstr "&gnu; GPL" # type: Attribute 'lang' of: #: ../en/mksquashfs.dbk:50 msgid "fr" msgstr "fr" # type: Content of:
#: ../en/mksquashfs.dbk:52 #, no-wrap msgid "" "\n" " &dhemail;\n" " " msgstr "" # type: Content of: #: ../en/mksquashfs.dbk:61 msgid "&dhusername;" msgstr "&dhusername;" # type: Content of: #: ../en/mksquashfs.dbk:75 msgid "&dhpackage;" msgstr "&dhpackage;" # type: Content of: #: ../en/mksquashfs.dbk:77 msgid "Create or modify a Squash file system" msgstr "" "Crée ou modifie un système de fichiers compressé Squash" # type: Content of: #: ../en/mksquashfs.dbk:83 msgid "&dhpackage; " msgstr "&dhpackage; " # type: Content of: #: ../en/mksquashfs.dbk:88 msgid "" "&dhpackage; source dest " " " msgstr "" "&dhpackage; source dest " " " # type: Content of: #: ../en/mksquashfs.dbk:101 msgid "DESCRIPTION" msgstr "DESCRIPTION" # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:103 msgid "" "A squashfs is a compressed read-only file system. Use the " "<command>&dhpackage;</command> program to create a new squashed file system, " "and to append new data to an existing squashed file system." msgstr "" "Squashfs est un système de fichiers compressé, accessible en lecture " "seulement. Utilisez la commande <command>&dhpackage;</command> pour créer un " "nouveau système de fichiers de ce type ou pour ajouter des données à un " "système existant." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:108 msgid "" "If a single source directory is specified (i.e. <userinput>mksquashfs " "<replaceable>source</replaceable> <replaceable>output_fs</replaceable></" "userinput>), the squashfs filesystem will consist of that directory, with " "the top-level root directory corresponding to the source directory." msgstr "" "Si on ne donne qu'un seul répertoire source (i.e. <userinput>mksquashfs " "<replaceable>source</replaceable> <replaceable>sf_résultant</replaceable></" "userinput>), on obtiendra un système de fichiers constitué du contenu de ce " "répertoire source." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:115 msgid "" "If multiple source directories or files are specified, <command>&dhpackage;</" "command> will merge the specified sources into a single filesystem, with the " "root directory containing each of the source files/directories. The name of " "each directory entry will be the basename of the source path. If more than " "one source entry maps to the same name, the conflicts are named " "<replaceable>xxx</replaceable>_1, <replaceable>xxx</replaceable>_2, etc. " "where <replaceable>xxx</replaceable> is the original name." msgstr "" "Si on fournit plusieurs fichier(s) ou répertoire(s) sources, " "<command>&dhpackage;</command> créera un seul système de fichiers qui " "contiendra tous les répertoires et fichiers source. Le nom de chaque " "répertoire obtenu sera le nom <emphasis>sans chemin d'accès</emphasis> de " "chaque répertoire source ; En cas de noms identiques, les doublons seront " "renommés en <replaceable>xxx</replaceable>_1, <replaceable>xxx</" "replaceable>_2, etc." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:125 msgid "" "The <replaceable>dest</replaceable> argument can either be a conventional " "file or a block device. If the file doesn't exist it will be created, if it " "does exist and a squashfs filesystem exists on it, <command>&dhpackage;</" "command> will append. The <option>-noappend </option>option will write a " "new filesystem irrespective of whether an existing filesystem is present." msgstr "" "L'argument <replaceable>dest</replaceable> peut être soit un fichier " "classique, soit un périphérique de type bloc (comme un disque ou une " "partition). Si le fichier n'existe pas, il sera créé ; s'il existe déjà et " "contient un système de fichiers Squashfs, <command>&dhpackage;</command> " "rajoutera les sources données à son contenu actuel, sauf si l'option " "<option>-noappend</option> est précisée." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:133 msgid "" "There are a large number of options that can be used to control the " "compression in <command>&dhpackage;</command>. By and large the defaults " "are the most optimum settings and should only be changed in exceptional " "circumstances !" msgstr "" "Il existe un grand nombre d'options qui permettent de contrôler la " "compression de <command>&dhpackage;</command>. Les valeurs par défaut sont " "de loin les optimales et ne devraient être modifiées qu'exceptionnellement !" # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:138 msgid "" "The <option>-noI</option>, <option>-noD</option> and <option>-noF</option> " "options (also <option>-noInodeCompression</option>, <option>-" "noDataCompression</option> and <option>-noFragmentCompression</option>) can " "be used to force <command>&dhpackage;</command> to not compress inodes/" "directories, data and fragments respectively. Giving all options generates " "an uncompressed filesystem." msgstr "" "Les options <option>-noI</option>, <option>-noD</option> et <option>-noF</" "option> (équivalentes à <option>-noInodeCompression</option>, <option>-" "noDataCompression</option> et <option>-noFragmentCompression</option>) " "peuvent être utilisées pour obliger <command>&dhpackage;</command> à ne pas " "comprimer respectivement les i-noeuds et répertoires, les blocs de données " "et les blocs de données fragmentés. Si l'on utilise ces trois options, on " "obtient un système de fichiers non comprimé." # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:148 msgid "" "By default files in the generated filesystem inherit the UID and GID " "ownership of the original file. However, <command>&dhpackage;</command> " "provides a number of options which can be used to override the ownership:" msgstr "" "Par défaut, les fichiers contenus dans le système de fichiers résultat ont " "le même propriétaire et groupe que les fichiers sources. Toutefois, " "<command>&dhpackage;</command> propose certaines options pour modifier ce " "comportement :" # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><simpara> #: ../en/mksquashfs.dbk:157 msgid "" "The options <option>-all-root</option> and <option>-root-owned</option> " "(both do exactly the same thing) force all file uids/gids in the generated " "Squashfs filesystem to be <literal>root</literal>. This allows root owned " "filesystems to be built without root access on the host machine." msgstr "" "Les options <option>-all-root</option> et <option>-root-owned</option> " "(synonymes) forcent tous les fichiers du système de fichiers Squashfs généré " "à appartenir à <literal>root</literal> (utilisateur et groupe). Elle permet " "de construire un système de fichiers appartenant à <literal>root</literal> " "sans avoir un accès à ce compte sur la machine où on le construit." # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><simpara> #: ../en/mksquashfs.dbk:164 msgid "" "The <option>-force-uid <replaceable>uid</replaceable></option> option forces " "all files in the generated Squashfs filesystem to be owned by the specified " "<replaceable>uid</replaceable>. The uid can be specified either by name (i." "e. <literal>root</literal>) or by number." msgstr "" "L'option <option>-force-uid <replaceable>uid</replaceable></option> force " "tous les fichiers du système de fichiers Squashfs généré à appartenir à " "l'utilisateur d'identifiant <replaceable>uid</replaceable> donné. Cet " "identifiant peut être soit un nom (par exemple <literal>root</literal>), " "soit un nombre." # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><simpara> #: ../en/mksquashfs.dbk:172 msgid "" "The <option>-force-gid <replaceable>gid</replaceable></option> option forces " "all files in the generated Squashfs filesystem to be group owned by the " "specified <replaceable>gid</replaceable>. The gid can be specified either " "by name (i.e. <literal>root</literal>) or by number." msgstr "" "L'option <option>-force-gid <replaceable>gid</replaceable></option> force " "tous les fichiers du système de fichiers Squashfs généré à appartenir au " "groupe d'identifiant <replaceable>gid</replaceable> donné. Cet identifiant " "peut être soit un nom (par exemple <literal>root</literal>), soit un nombre." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:181 msgid "" "The <option>-e</option> and <option>-ef</option> options allow files/" "directories to be specified which are excluded from the output filesystem. " "The <option>-e</option> option takes the exclude files/directories from the " "command line, the <option>-ef</option> option takes the exlude files/" "directories from the specified exclude file, one file/directory per line. If " "an exclude file/directory is absolute (i.e. prefixed with <filename>/</" "filename>, <filename>../</filename>, or <filename>./</filename>) the entry " "is treated as absolute, however, if an exclude file/directory is relative, " "it is treated as being relative to each of the sources in turn, i.e. " "<userinput>mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 " "out/ex3</userinput> Will generate exclude files <filename>/tmp/source1/ex2</" "filename>, <filename>/tmp/source1/ex1</filename>, <filename>source2/ex1</" "filename>, <filename>/tmp/source1/out/ex3</filename> and <filename>source2/" "out/ex3</filename>." msgstr "" "Les options <option>-e</option> et <option>-ef</option> permettent de " "déclarer des fichiers ou répertoires à exclure du système de fichiers " "résultat. L'option <option>-e</option> lit les fichiers/répertoires à " "exclure sur la ligne de commande, tandis que l'option <option>-ef</option> " "les trouve dans le fichier d'exclusions spécifié contenant un fichier ou " "répertoire par ligne. Si le chemin d'un fichier ou répertoire à exclure est " "absolu (c'est-à-dire débutant par <filename>/</filename>, <filename>../</" "filename> ou <filename>./</filename>), il est considéré indépendamment des " "sources ; en revanche, s'il est relatif, il s'appliquera pour chaque " "répertoire source ; par exemple, <userinput>mksquashfs /tmp/source1 source2 " "sf_résultant -e ex1 /tmp/source1/ex2 out/ex3</userinput> exclura les " "fichiers <filename>/tmp/source1/ex2</filename>, <filename>/tmp/source1/ex1</" "filename>, <filename>source2/ex1</filename>, <filename>/tmp/source1/out/ex3</" "filename> et <filename>source2/out/ex3</filename>." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:201 msgid "" "The <option>-e</option> and <option>-ef</option> exclude options are " "usefully used in archiving the entire filesystem, where it is wished to " "avoid archiving <filename>/proc</filename>, and the filesystem being " "generated, i.e. <userinput>mksquashfs / /tmp/root.sqsh -e proc /tmp/root." "sqsh</userinput>" msgstr "" "Ces options <option>-e</option> et <option>-ef</option> sont pratiques pour, " "par exemple, archiver un système de fichier complet en évitant le répertoire " "<filename>/proc</filename> et le système de fichiers résultat : " "<userinput>mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh</userinput>" # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:208 msgid "" "Multiple <option>-ef</option> options can be specified on the command line, " "and the <option>-ef</option> option can be used in conjuction with the " "<option>-e</option> option." msgstr "" "On peut utiliser plusieurs fois l'option <option>-ef</option> dans une même " "commande, et on peut également l'utiliser en même temps que l'option " "<option>-e</option>." # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:213 msgid "" "The <option>-info</option> option displays the files/directories as they are " "compressed and added to the filesystem. The original uncompressed size of " "each file is printed, along with <literal>DUPLICATE</literal> if the file is " "a duplicate of a file in the filesystem." msgstr "" "L'option <option>-info</option> affiche les fichiers et répertoires ajoutés " "au système de fichiers, avec leur taille originelle et éventuellement le mot " "<literal>DUPLICATE</literal> si un fichier avec un contenu identique y est " "déjà présent." # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:219 msgid "" "The <option>-no-exports</option> option doesn't make the filesystem " "exportable via NFS." msgstr "" "L'option <option>-no-exports</option> permet d'éviter le partage du système " "de fichiers par NFS" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:222 msgid "" "The <option>-no-progress</option> option doesn't display the progress bar." msgstr "" "L'option <option>-no-progress</option> n'affiche pas la barre de progression" # type: Content of: <refentry><refsect1><simpara> #: ../en/mksquashfs.dbk:225 msgid "" "The <option>-le</option> and <option>-be</option> options can be used to " "force <command>&dhpackage;</command> to generate a little endian or big " "endian filesystem. Normally <command>&dhpackage;</command> will generate a " "filesystem in the host byte order. Squashfs, for portability, will mount " "different ordered filesystems (i.e. it can mount big endian filesystems " "running on a little endian machine), but these options can be used for " "greater optimisation." msgstr "" "Les options <option>-le</option> et <option>-be</option> peuvent servir à " "forcer <command>&dhpackage;</command> à générer un système de fichiers " "<foreignphrase>little endian</foreignphrase> ou <foreignphrase>big endian</" "foreignphrase>. Par défaut, <command>&dhpackage;</command> génère un système " "de fichiers avec le boutisme de la machine hôte. Le pilote Squashfs " "permettant, par souci de portabilité, de monter les deux types de systèmes " "de fichiers (c'est-à-dire qu'il peut monter un système <foreignphrase>big " "endian</foreignphrase> sur une machine <foreignphrase>little endian</" "foreignphrase>), ces options peuvent servir à améliorer l'efficacité d'un " "système de fichiers généré pour une architecture différente." # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:237 msgid "OPTIONS" msgstr "OPTIONS" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:242 msgid "<option>-version</option>" msgstr "<option>-version</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:245 msgid "print version, licence and copyright message." msgstr "affiche la version, la licence et un message de copyright." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:250 msgid "<option>-recover <replaceable>name</replaceable></option>" msgstr "<option>-recover <replaceable>nom</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:253 msgid "" "Allows the original filesystem to be recovered if Mksquashfs aborts " "unexpectedly (i.e. power failure) using recovery file <replaceable>name</" "replaceable>. Recovery files are now created when appending to existing " "Squashfs filesystems." msgstr "" "Permet au système de fichier original d'être restauré si Mksquashfs se " "termine de façon inattendu (par exemple alimentation défaillante) en " "utilisant le fichier de restauration <replaceable>nom</replaceable>. Les " "fichiers de restauration sont désormais créés lors de l'ajout à un système " "de fichier Squashfs existant." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:262 msgid "<option>-no-recovery</option>" msgstr "<option>-no-recovery</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:263 msgid "don't generate a recovery file" msgstr "ne pas générer un fichier de restauration" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:268 msgid "<option>-info</option>" msgstr "<option>-info</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:269 msgid "print files written to filesystem" msgstr "affiche les fichiers ajoutés au système de fichiers." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:274 msgid "<option>-no-exports</option>" msgstr "<option>-no-exports</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:275 msgid "don't make the filesystem exportable via NFS" msgstr "permet d'éviter le partage du système de fichier par NFS" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:281 msgid "<option>-no-progress</option>" msgstr "<option>-no-progress</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:282 msgid "don't display the progress bar" msgstr "n'affiche pas la barre de progression" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:287 msgid "<option>-no-sparse</option>" msgstr "<option>-no-sparse</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:288 msgid "don't detect sparse files" msgstr "ne pas détecter les fichiers vides" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:293 msgid "<option>-b <replaceable>block_size</replaceable></option>" msgstr "<option>-b <replaceable>taille_bloc</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:295 msgid "" "set data block to <replaceable>block_size</replaceable>. Default is 131072 " "bytes" msgstr "" "fixe la taille des blocs de données à <replaceable>block_size</replaceable>. " "Par défaut, elle vaut 65536 octets." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:302 msgid "<option>-processors <replaceable>number</replaceable></option>" msgstr "<option>-processors <replaceable>nombre</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:304 msgid "" "Use <replaceable>number</replaceable> processors. By default will use " "number of processors available" msgstr "" "Utilise <replaceable>nombre</replaceable> processeurs. Utilise par défaut le " "nombre de processeurs disponibles" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:311 msgid "<option>-read-queue <replaceable>size</replaceable></option>" msgstr "<option>-read-queue <replaceable>taille</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:313 msgid "" "Set input queue to <replaceable>size</replaceable> Mbytes. Default 64 Mbytes." msgstr "" "Initialise la file d'entrée à <replaceable>taille</replaceable> Mo. La " "valeur par défaut est 64Mo." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:320 msgid "<option>-write-queue <replaceable>size</replaceable></option>" msgstr "<option>-write-queue <replaceable>taille</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:322 msgid "" "Set output queue to <replaceable>size</replaceable> Mbytes. Default 512 " "Mbytes." msgstr "" "Initialise la file de sortie à <replaceable>taille</replaceable> Mo. La " "valeur par défaut est 512Mo." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:329 msgid "<option>-noI</option> or <option>-noInodeCompression</option>" msgstr "<option>-noI</option> ou <option>-noInodeCompression</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:331 msgid "do not compress inode table" msgstr "ne comprime pas la table des i-noeuds." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:336 msgid "<option>-noD</option>or <option>-noDataCompression</option>" msgstr "<option>-noD</option> ou <option>-noDataCompression</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:338 msgid "do not compress data blocks" msgstr "ne comprime pas les blocs de données." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:343 msgid "<option>-noF</option> or <option>-noFragmentCompression</option>" msgstr "<option>-noF</option> ou <option>-noFragmentCompression</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:345 msgid "do not compress fragment blocks" msgstr "ne comprime pas les blocs fragmentés." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:350 msgid "<option>-no-fragments</option>" msgstr "<option>-no-fragments</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:351 msgid "" "do not use fragments: tells <command>&dhpackage;</command> to not generate " "fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x " "filesystem. It will of course still be a Squashfs 2.0 filesystem but without " "fragments, and so it won't be mountable on a Squashfs 1.x system." msgstr "" "n'utilise pas de blocs fragmentés : indique à <command>&dhpackage;</command> " "de ne pas créer de blocs fragmentés, mais plutôt un système de fichiers du " "même genre que ceux des versions 1.x de Squashfs. Ce sera quand même un " "système de fichiers Squashfs 2.0 (mais sans fragments), donc il ne pourra " "être monté par un système Squashfs en version 1.x." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:361 msgid "<option>-always-use-fragments</option>" msgstr "<option>-always-use-fragments</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:362 msgid "" "use fragment blocks for files larger than block size: tells " "<command>&dhpackage;</command> to always generate fragments for files " "irrespective of the file length. By default only small files less than the " "block size are packed into fragment blocks. The ends of files which do not " "fit fully into a block, are <emphasis>NOT</emphasis> by default packed into " "fragments. To illustrate this, a 100K file has an initial 64K block and a " "36K remainder. This 36K remainder is not packed into a fragment by " "default. This is because to do so leads to a 10 - 20% drop in sequential I/" "O performance, as a disk head seek is needed to seek to the initial file " "data and another disk seek is need to seek to the fragment block. Specify " "this option if you want file remainders to be packed into fragment blocks. " "Doing so may increase the compression obtained <emphasis>BUT</emphasis> at " "the expense of I/O speed." msgstr "" "utilise des blocs fragmentés pour les fichiers plus gros que la taille d'un " "bloc : indique à <command>&dhpackage;</command> d'utiliser des blocs " "fragmentés quelle que soit la longueur des fichiers. Par défaut, seuls les " "petits fichiers (dont la taille est inférieure à celle d'un bloc) sont " "assemblés dans des blocs fragmentés. La fin des fichiers qui remplisse plus " "d'un bloc ne sont <emphasis>pas</emphasis>, par défaut, assemblés dans des " "fragments. Par exemple, un fichier de 100 ko est découpé en un bloc de " "64 ko et un reste de 36 ko, qui par défaut n'est pas placé dans un bloc " "fragmenté. Ce choix est fait pour éviter une perte de performance de 10 à " "20% en accès séquentiel à ce genre de fichiers, car il faudrait sinon " "déplacer la tête de lecture d'un disque pour accéder au(x) bloc(s) entier(s) " "et un autre pour le fragment (qui ne sera sans doute pas consécutif). " "Utilisez cette option pour forcer ces fins de fichiers à être rassemblées " "dans les blocs fragmentés ; cela améliore le taux de compression obtenu " "<emphasis>mais</emphasis> au dépens de la vitesse d'accès." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:384 msgid "<option>-no-duplicates</option>" msgstr "<option>-no-duplicates</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:385 msgid "" "do not perform duplicate checking: tells <command>&dhpackage;</command> to " "not check the files being added to the filesystem for duplicates. This can " "result in quicker filesystem generation and appending although obviously " "compression will suffer badly if there is a lot of duplicate files." msgstr "" "ne vérifie pas s'il y a des doublons : indique à <command>&dhpackage;</" "command> de ne pas vérifier dans les fichiers ajoutés s'il y en a avec des " "contenus identiques. Ceci permet une génération/modification du système de " "fichiers résultant plus rapide, mais bien sûr le taux de compression sera " "nettement moins bon s'il y a beaucoup de fichiers aux contenus identiques." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:395 msgid "<option>-noappend</option>" msgstr "<option>-noappend</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:396 msgid "do not append to existing filesystem" msgstr "ne pas ajouter en fin d'un système de fichiers existant." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:402 msgid "<option>-keep-as-directory</option>" msgstr "<option>-keep-as-directory</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:403 msgid "" "if one source directory is specified, create a root directory containing " "that directory, rather than the contents of the directory" msgstr "" "si un répertoire source est donné, crée un système de fichiers contenant ce " "répertoire plutôt que simplement son contenu." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:410 msgid "<option>-root-becomes <replaceable>name</replaceable></option>" msgstr "<option>-root-becomes <replaceable>nom</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:412 msgid "" "when appending source files/directories, make the original root become a " "subdirectory in the new root called <replaceable>name</replaceable>, rather " "than adding the new source items to the original root" msgstr "" "lorsqu'on ajoute des fichiers ou répertoires à un système existant, le " "contenu de l'ancien système sera placé dans un répertoire de " "<replaceable>nom</replaceable> donné, plutôt que de mélanger les anciens " "fichiers et les nouveaux." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:420 msgid "<option>-all-root</option> or <option>-root-owned</option>" msgstr "<option>-all-root</option> ou <option>-root-owned</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:422 msgid "make all files owned by root" msgstr "" "tous les fichiers ajoutés au système appartiendront à <literal>root</" "literal>." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:427 msgid "<option>-force-uid <replaceable>uid</replaceable></option>" msgstr "<option>-force-uid <replaceable>uid</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:429 msgid "set all file uids to <replaceable>uid</replaceable>" msgstr "" "tous les fichiers ajoutés au système appartiendront à l'utilisateur " "d'identifiant <replaceable>uid</replaceable> (un nom ou un nombre)." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:435 msgid "<option>-force-gid <replaceable>gid</replaceable></option>" msgstr "<option>-force-gid <replaceable>gid</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:437 msgid "set all file gids to <replaceable>gid</replaceable>" msgstr "" "tous les fichiers ajoutés au système appartiendront au groupe d'identifiant " "<replaceable>gid</replaceable> (un nom ou un nombre)." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:443 msgid "<option>-le</option>" msgstr "<option>-le</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:444 msgid "create a little endian filesystem" msgstr "" "crée un système de fichiers au format petit boutiens (<foreignphrase>little " "endian</foreignphrase> en anglais)." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:449 msgid "<option>-be</option>" msgstr "<option>-be</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:450 msgid "create a big endian filesystem" msgstr "" "crée un système de fichiers au format gros boutiens (<foreignphrase>big " "endian</foreignphrase> en anglais)." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:455 msgid "<option>-nopad</option>" msgstr "<option>-nopad</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:456 msgid "" "do not pad filesystem to a multiple of 4Ko. This is performed by default to " "enable the output filesystem file to be mounted by loopback, which requires " "files to be a 4K multiple. If the filesystem is being written to a block " "device, or is to be stored in a bootimage, the extra pad bytes are not " "needed." msgstr "" "Ne pas arrondir le système de fichiers au multiple de 4 ko [supérieur] : cet " "arrondi, effectué par défaut, permet au système de fichiers d'être monté par " "l'interface <literal>loopback</literal> qui ne fonctionne qu'avec des " "fichiers multiples de 4 ko. Si le système de fichiers est destiné à être " "écrit sur un périphérique de type bloc (un disque ou une partition par " "exemple) ou être placé dans une image de démarrage, cet arrondi est inutile." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:466 msgid "<option>-check_data</option>" msgstr "<option>-check_data</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:467 msgid "add checkdata for greater filesystem checks" msgstr "" "positionne un drapeau dans le système de fichiers créé pour plus de " "vérifications de ce système lorsqu'il est monté." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:473 msgid "<option>-sort <replaceable>sort_file</replaceable></option>" msgstr "<option>-sort <replaceable>ordre</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:475 msgid "" "sort files according to priorities in <replaceable>sort_file</replaceable>. " "One file or dir with priority per line. Priority -32768 to 32767, default " "priority 0" msgstr "" "trie les fichiers suivant les priorités décrites dans le fichier " "<replaceable>ordre</replaceable>, qui doit contenir un nom de fichier ou " "répertoire par ligne avec sa priorité associée (nombre entre -32768 et " "32767, 0 par défaut)." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:483 msgid "" "<option>-e <replaceable>list of exclude dirs/files</replaceable></option>" msgstr "" "<option>-e <replaceable>liste des répertoires/fichiers exclus</replaceable></" "option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:485 msgid "inline list of files / directories to exclude" msgstr "liste (en ligne) des fichiers et répertoires à exclure." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:491 msgid "<option>-ef <replaceable>exclude_file</replaceable></option>" msgstr "<option>-ef <replaceable>fichier_exclus</replaceable></option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><simpara> #: ../en/mksquashfs.dbk:493 msgid "file containing a list of files / directories to exclude, one per line" msgstr "" "le fichier <replaceable>fichier_exclus</replaceable> contient la liste des " "fichiers ou répertoires à exclure, un par ligne." # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:499 msgid "<option>-wildcards</option>" msgstr "<option>-wildcards</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:500 msgid "" "Allow extended shell wildcards (globbing) to be used in exclude dirs/files" msgstr "" "Permet l'utilisation des caractères spéciaux de l'interpréteur de commande " "afin d'exclure des répertoires ou fichiers" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:505 msgid "<option>-regex</option>" msgstr "<option>-regex</option>" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:506 msgid "Allow POSIX regular expressions to be used in exclude dirs/files" msgstr "" "Permet l'utilisation des expressions rationnelle POSIX pour l'exclusion de " "fichiers ou répertoires" # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:514 msgid "EXAMPLES" msgstr "EXEMPLES" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:516 msgid "For following examples, take two example directories:" msgstr "Pour les exemples suivants, on utilise deux répertoires :" # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><simpara> #: ../en/mksquashfs.dbk:519 msgid "" "Source directory <filename>/home/phillip/test</filename> contains " "<filename>file1</filename>, <filename>file2</filename> and <filename>dir1</" "filename>." msgstr "" "le répertoire source <filename>/home/phillip/test</filename> contient " "<filename>fichier1</filename>, <filename>fichier2</filename> et " "<filename>rep1</filename>." # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><simpara> #: ../en/mksquashfs.dbk:525 msgid "" "Source directory <filename>goodies</filename> contains <filename>goodies1</" "filename>, <filename>goodies2</filename> and <filename>goodies3</filename>." msgstr "" "le répertoire source <filename>outils</filename> contient <filename>outils1</" "filename>, <filename>outils2</filename> et <filename>outils3</filename>." # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:537 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test output_fs</userinput>" msgstr "<userinput>mksquashfs /home/phillip/test sf_resultat</userinput>" # type: Content of: <refentry><refsect1><refsect2><example><simpara> #: ../en/mksquashfs.dbk:538 msgid "" "This will generate a squashfs filesystem with root entries <filename>file1</" "filename>, <filename>file2</filename> and <filename>dir1</filename>." msgstr "" "va créer un système de fichiers Squashfs contenant dans sa racine les items " "<filename>fichier1</filename>, <filename>fichier2</filename> et " "<filename>rep1</filename>." # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:547 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test goodies output_fs</userinput>" msgstr "<userinput>mksquashfs /home/phillip/test outils sf_resultat</userinput>" # type: Content of: <refentry><refsect1><refsect2><example><simpara> #: ../en/mksquashfs.dbk:548 msgid "" "This will create a squashfs filesystem with the root containing entries " "<filename>test</filename> and <filename>goodies</filename> corresponding to " "the source directories <filename>/home/phillip/test</filename> and " "<filename>goodies</filename>." msgstr "" "va créer un système de fichiers Squashfs contenant dans sa racine les " "répertoires <filename>test</filename> et <filename>outils</filename>, " "correspondant aux répertoires source <filename>/home/phillip/test</filename> " "et <filename>outils</filename>." # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:559 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test goodies test output_fs</userinput>" msgstr "<userinput>mksquashfs /home/phillip/test outils test sf_resultat</userinput>" # type: Content of: <refentry><refsect1><refsect2><example><simpara> #: ../en/mksquashfs.dbk:561 msgid "" "This is the same as the previous example, except a third source directory " "<filename>test</filename> has been specified. This conflicts with the first " "directory named <filename>test</filename> and will be renamed " "<filename>test_1</filename>." msgstr "" "commande identique à l'exemple précédent, sauf qu'un troisième répertoire " "source <filename>test</filename> a été donné, d'où un conflit avec le " "premier répertoire <filename>test</filename>. Ce troisième répertoire sera " "donc renommé <filename>test_1</filename>." # type: Content of: <refentry><refsect1><refsect2><example><simpara> #: ../en/mksquashfs.dbk:566 msgid "" "Multiple sources allow filesystems to be generated without needing to copy " "all source files into a common directory. This simplifies creating " "filesystems." msgstr "" "Donner plusieurs répertoires source permet de générer des systèmes de " "fichiers sans préalablement copier tous les fichiers nécessaires dans un " "répertoire commun, ce qui simplifie le processus." # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:575 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test output_fs -keep-as-directory</userinput>" msgstr "<userinput>mksquashfs /home/phillip/test sf_resultat -keep-as-directory</userinput>" # type: Content of: <refentry><refsect1><refsect2><example><simpara> #: ../en/mksquashfs.dbk:577 msgid "" "This is the same as the first example, except for <option>-keep-as-" "directory</option>. This will generate a root directory containing directory " "<filename>test</filename>, rather than the <filename>test</filename> " "directory contents <filename>file1</filename>, <filename>file2</filename> " "and <filename>dir1</filename>." msgstr "" "commande identique au premier exemple, sauf que l'option <option>-keep-as-" "directory</option> va donner un système de fichiers dont la racine " "contiendra un répertoire <filename>test</filename>, au lieu de n'avoir que " "son contenu <filename>fichier1</filename>, <filename>fichier2</filename> et " "<filename>rep1</filename>." # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:590 msgid "AUTHORS" msgstr "AUTEURS" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:592 msgid "" "Squashfs was written by <personname> <firstname>Phillip</firstname> " "<surname>Lougher</surname> </personname> <email>plougher@users.sourceforge." "net</email>, in Chepstow, Wales, UK. If you like the program, or have any " "problems, then please email me, as it's nice to get feedback !" msgstr "" "Squashfs a été écrit par <personname> <firstname>Phillip</firstname> " "<surname>Lougher</surname> </personname> <email>plougher@users.sourceforge." "net</email>, à Chepstow, Pays de Galles, Royaume-Uni. Si vous appréciez ce " "programme ou rencontrez des problèmes en l'utilisant, contactez-le, il est " "intéressé par des retours d'expérience." # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:600 msgid "" "This manual page was written by &dhusername; &dhemail; for the &debian; " "system (but may be used by others) using the <citetitle>SquashFS HOWTO</" "citetitle> from <author> <firstname>Artemiy I.</firstname> <surname>Pavlov</" "surname> </author> and squashfs's <filename>README</filename> file. " "Permission is granted to copy, distribute and/or modify this document under " "the terms of the &gnu; General Public License, Version 2 any later version " "published by the Free Software Foundation." msgstr "" "Cette page de manuel a été écrit par &dhusername; &dhemail; pour le système " "&debian; (mais peut être utilisé par d'autres) à partir du document " "<citetitle>SquashFS HOWTO</citetitle> de <author> <firstname>Artemiy I.</" "firstname> <surname>Pavlov</surname> </author> et du fichier " "<filename>README</filename> des sources de SquashFS. Il est permis de " "copier, distribuer et/ou modifier ce document en vertu de la licence GPL " "version 2 ou postérieure, telle que publiée par la Free Software Foundation." # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:613 msgid "" "On Debian systems, the complete text of the &gnu; General Public License can " "be found in <filename>/usr/share/common-licenses/GPL</filename>." msgstr "" "Sur les systèmes Debian, le texte complet de la licence &gpl; (Licence " "Public Générale &gnu;) se trouve dans le fichier <filename>/usr/share/common-" "licenses/GPL</filename>." ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/po/mksquashfs.pot ================================================ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2008-04-05 09:29-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: ENCODING" # type: Content of the dhfirstname entity #: ../en/mksquashfs.dbk:30 msgid "<firstname>Frédéric</firstname>" msgstr "" # type: Content of the dhsurname entity #: ../en/mksquashfs.dbk:31 msgid "<surname>Boiteux</surname>" msgstr "" # type: Content of the dhdate entity #: ../en/mksquashfs.dbk:34 msgid "<date>december 20, 2004</date>" msgstr "" # type: Content of the dhsection entity #: ../en/mksquashfs.dbk:38 msgid "<manvolnum>1</manvolnum>" msgstr "" # type: Content of the dhemail entity #: ../en/mksquashfs.dbk:39 msgid "<email>fboiteux@calistel.com</email>" msgstr "" # type: Content of the dhusername entity #: ../en/mksquashfs.dbk:40 msgid "Frédéric Boiteux" msgstr "" # type: Content of the dhucpackage entity #: ../en/mksquashfs.dbk:41 msgid "<refentrytitle>MKSQUASHFS</refentrytitle>" msgstr "" # type: Content of the dhpackage entity #: ../en/mksquashfs.dbk:42 msgid "mksquashfs" msgstr "" # type: Content of the debian entity #: ../en/mksquashfs.dbk:44 msgid "<productname>Debian</productname>" msgstr "" # type: Content of the gnu entity #: ../en/mksquashfs.dbk:45 msgid "<acronym>GNU</acronym>" msgstr "" # type: Content of the gpl entity #: ../en/mksquashfs.dbk:46 msgid "&gnu; <acronym>GPL</acronym>" msgstr "" # type: Attribute 'lang' of: <refentry> #: ../en/mksquashfs.dbk:50 msgid "fr" msgstr "" # type: Content of: <refentry><refentryinfo><address> #: ../en/mksquashfs.dbk:52 #, no-wrap msgid "" "\n" " &dhemail;\n" " " msgstr "" # type: Content of: <refentry><refentryinfo><copyright><holder> #: ../en/mksquashfs.dbk:61 msgid "&dhusername;" msgstr "" # type: Content of: <refentry><refnamediv><refname> #: ../en/mksquashfs.dbk:75 msgid "&dhpackage;" msgstr "" # type: Content of: <refentry><refnamediv><refpurpose> #: ../en/mksquashfs.dbk:77 msgid "Create or modify a Squash file system" msgstr "" # type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> #: ../en/mksquashfs.dbk:83 msgid "<command>&dhpackage;</command> <arg><option>-version</option></arg>" msgstr "" # type: Content of: <refentry><refsynopsisdiv><cmdsynopsis> #: ../en/mksquashfs.dbk:88 msgid "" "<command>&dhpackage;</command> <arg choice=\"plain\" " "rep=\"repeat\"><replaceable>source</replaceable></arg> <arg " "choice=\"plain\"><replaceable>dest</replaceable></arg> " "<arg><option>options</option></arg> <arg><option>-e <replaceable>list of " "exclude dirs/files</replaceable></option></arg> <arg><option>-ef " "<replaceable>exclude_file</replaceable></option></arg>" msgstr "" # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:101 msgid "DESCRIPTION" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:103 msgid "" "A squashfs is a compressed read-only file system. Use the " "<command>&dhpackage;</command> program to create a new squashed file system, " "and to append new data to an existing squashed file system." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:108 msgid "" "If a single source directory is specified (i.e. <userinput>mksquashfs " "<replaceable>source</replaceable> " "<replaceable>output_fs</replaceable></userinput>), the squashfs filesystem " "will consist of that directory, with the top-level root directory " "corresponding to the source directory." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:115 msgid "" "If multiple source directories or files are specified, " "<command>&dhpackage;</command> will merge the specified sources into a " "single filesystem, with the root directory containing each of the source " "files/directories. The name of each directory entry will be the basename of " "the source path. If more than one source entry maps to the same name, the " "conflicts are named <replaceable>xxx</replaceable>_1, " "<replaceable>xxx</replaceable>_2, etc. where <replaceable>xxx</replaceable> " "is the original name." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:125 msgid "" "The <replaceable>dest</replaceable> argument can either be a conventional " "file or a block device. If the file doesn't exist it will be created, if it " "does exist and a squashfs filesystem exists on it, " "<command>&dhpackage;</command> will append. The <option>-noappend " "</option>option will write a new filesystem irrespective of whether an " "existing filesystem is present." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:133 msgid "" "There are a large number of options that can be used to control the " "compression in <command>&dhpackage;</command>. By and large the defaults " "are the most optimum settings and should only be changed in exceptional " "circumstances !" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:138 msgid "" "The <option>-noI</option>, <option>-noD</option> and <option>-noF</option> " "options (also <option>-noInodeCompression</option>, " "<option>-noDataCompression</option> and " "<option>-noFragmentCompression</option>) can be used to force " "<command>&dhpackage;</command> to not compress inodes/directories, data and " "fragments respectively. Giving all options generates an uncompressed " "filesystem." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:148 msgid "" "By default files in the generated filesystem inherit the UID and GID " "ownership of the original file. However, <command>&dhpackage;</command> " "provides a number of options which can be used to override the ownership:" msgstr "" # type: Content of: <refentry><refsect1><itemizedlist><listitem><para> #: ../en/mksquashfs.dbk:157 msgid "" "The options <option>-all-root</option> and <option>-root-owned</option> " "(both do exactly the same thing) force all file uids/gids in the generated " "Squashfs filesystem to be <literal>root</literal>. This allows root owned " "filesystems to be built without root access on the host machine." msgstr "" # type: Content of: <refentry><refsect1><itemizedlist><listitem><para> #: ../en/mksquashfs.dbk:164 msgid "" "The <option>-force-uid <replaceable>uid</replaceable></option> option forces " "all files in the generated Squashfs filesystem to be owned by the specified " "<replaceable>uid</replaceable>. The uid can be specified either by name " "(i.e. <literal>root</literal>) or by number." msgstr "" # type: Content of: <refentry><refsect1><itemizedlist><listitem><para> #: ../en/mksquashfs.dbk:172 msgid "" "The <option>-force-gid <replaceable>gid</replaceable></option> option forces " "all files in the generated Squashfs filesystem to be group owned by the " "specified <replaceable>gid</replaceable>. The gid can be specified either " "by name (i.e. <literal>root</literal>) or by number." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:181 msgid "" "The <option>-e</option> and <option>-ef</option> options allow " "files/directories to be specified which are excluded from the output " "filesystem. The <option>-e</option> option takes the exclude " "files/directories from the command line, the <option>-ef</option> option " "takes the exlude files/directories from the specified exclude file, one " "file/directory per line. If an exclude file/directory is absolute " "(i.e. prefixed with <filename>/</filename>, <filename>../</filename>, or " "<filename>./</filename>) the entry is treated as absolute, however, if an " "exclude file/directory is relative, it is treated as being relative to each " "of the sources in turn, i.e. <userinput>mksquashfs /tmp/source1 source2 " "output_fs -e ex1 /tmp/source1/ex2 out/ex3</userinput> Will generate exclude " "files <filename>/tmp/source1/ex2</filename>, " "<filename>/tmp/source1/ex1</filename>, <filename>source2/ex1</filename>, " "<filename>/tmp/source1/out/ex3</filename> and " "<filename>source2/out/ex3</filename>." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:201 msgid "" "The <option>-e</option> and <option>-ef</option> exclude options are " "usefully used in archiving the entire filesystem, where it is wished to " "avoid archiving <filename>/proc</filename>, and the filesystem being " "generated, i.e. <userinput>mksquashfs / /tmp/root.sqsh -e proc " "/tmp/root.sqsh</userinput>" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:208 msgid "" "Multiple <option>-ef</option> options can be specified on the command line, " "and the <option>-ef</option> option can be used in conjuction with the " "<option>-e</option> option." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:213 msgid "" "The <option>-info</option> option displays the files/directories as they are " "compressed and added to the filesystem. The original uncompressed size of " "each file is printed, along with <literal>DUPLICATE</literal> if the file is " "a duplicate of a file in the filesystem." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:219 msgid "" "The <option>-no-exports</option> option doesn't make the filesystem " "exportable via NFS." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:222 msgid "The <option>-no-progress</option> option doesn't display the progress bar." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:225 msgid "" "The <option>-le</option> and <option>-be</option> options can be used to " "force <command>&dhpackage;</command> to generate a little endian or big " "endian filesystem. Normally <command>&dhpackage;</command> will generate a " "filesystem in the host byte order. Squashfs, for portability, will mount " "different ordered filesystems (i.e. it can mount big endian filesystems " "running on a little endian machine), but these options can be used for " "greater optimisation." msgstr "" # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:237 msgid "OPTIONS" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:242 msgid "<option>-version</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:245 msgid "print version, licence and copyright message." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:250 msgid "<option>-recover <replaceable>name</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:253 msgid "" "Allows the original filesystem to be recovered if Mksquashfs aborts " "unexpectedly (i.e. power failure) using recovery file " "<replaceable>name</replaceable>. Recovery files are now created when " "appending to existing Squashfs filesystems." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:262 msgid "<option>-no-recovery</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:263 msgid "don't generate a recovery file" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:268 msgid "<option>-info</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:269 msgid "print files written to filesystem" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:274 msgid "<option>-no-exports</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:275 msgid "don't make the filesystem exportable via NFS" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:281 msgid "<option>-no-progress</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:282 msgid "don't display the progress bar" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:287 msgid "<option>-no-sparse</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:288 msgid "don't detect sparse files" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:293 msgid "<option>-b <replaceable>block_size</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:295 msgid "" "set data block to <replaceable>block_size</replaceable>. Default is 131072 " "bytes" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:302 msgid "<option>-processors <replaceable>number</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:304 msgid "" "Use <replaceable>number</replaceable> processors. By default will use " "number of processors available" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:311 msgid "<option>-read-queue <replaceable>size</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:313 msgid "" "Set input queue to <replaceable>size</replaceable> Mbytes. Default 64 " "Mbytes." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:320 msgid "<option>-write-queue <replaceable>size</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:322 msgid "" "Set output queue to <replaceable>size</replaceable> Mbytes. Default 512 " "Mbytes." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:329 msgid "<option>-noI</option> or <option>-noInodeCompression</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:331 msgid "do not compress inode table" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:336 msgid "<option>-noD</option>or <option>-noDataCompression</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:338 msgid "do not compress data blocks" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:343 msgid "<option>-noF</option> or <option>-noFragmentCompression</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:345 msgid "do not compress fragment blocks" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:350 msgid "<option>-no-fragments</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:351 msgid "" "do not use fragments: tells <command>&dhpackage;</command> to not generate " "fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x " "filesystem. It will of course still be a Squashfs 2.0 filesystem but without " "fragments, and so it won't be mountable on a Squashfs 1.x system." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:361 msgid "<option>-always-use-fragments</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:362 msgid "" "use fragment blocks for files larger than block size: tells " "<command>&dhpackage;</command> to always generate fragments for files " "irrespective of the file length. By default only small files less than the " "block size are packed into fragment blocks. The ends of files which do not " "fit fully into a block, are <emphasis>NOT</emphasis> by default packed into " "fragments. To illustrate this, a 100K file has an initial 64K block and a " "36K remainder. This 36K remainder is not packed into a fragment by " "default. This is because to do so leads to a 10 - 20% drop in sequential " "I/O performance, as a disk head seek is needed to seek to the initial file " "data and another disk seek is need to seek to the fragment block. Specify " "this option if you want file remainders to be packed into fragment " "blocks. Doing so may increase the compression obtained " "<emphasis>BUT</emphasis> at the expense of I/O speed." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:384 msgid "<option>-no-duplicates</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:385 msgid "" "do not perform duplicate checking: tells <command>&dhpackage;</command> to " "not check the files being added to the filesystem for duplicates. This can " "result in quicker filesystem generation and appending although obviously " "compression will suffer badly if there is a lot of duplicate files." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:395 msgid "<option>-noappend</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:396 msgid "do not append to existing filesystem" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:402 msgid "<option>-keep-as-directory</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:403 msgid "" "if one source directory is specified, create a root directory containing " "that directory, rather than the contents of the directory" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:410 msgid "<option>-root-becomes <replaceable>name</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:412 msgid "" "when appending source files/directories, make the original root become a " "subdirectory in the new root called <replaceable>name</replaceable>, rather " "than adding the new source items to the original root" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:420 msgid "<option>-all-root</option> or <option>-root-owned</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:422 msgid "make all files owned by root" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:427 msgid "<option>-force-uid <replaceable>uid</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:429 msgid "set all file uids to <replaceable>uid</replaceable>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:435 msgid "<option>-force-gid <replaceable>gid</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:437 msgid "set all file gids to <replaceable>gid</replaceable>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:443 msgid "<option>-le</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:444 msgid "create a little endian filesystem" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:449 msgid "<option>-be</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:450 msgid "create a big endian filesystem" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:455 msgid "<option>-nopad</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:456 msgid "" "do not pad filesystem to a multiple of 4Ko. This is performed by default to " "enable the output filesystem file to be mounted by loopback, which requires " "files to be a 4K multiple. If the filesystem is being written to a block " "device, or is to be stored in a bootimage, the extra pad bytes are not " "needed." msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:466 msgid "<option>-check_data</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:467 msgid "add checkdata for greater filesystem checks" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:473 msgid "<option>-sort <replaceable>sort_file</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:475 msgid "" "sort files according to priorities in <replaceable>sort_file</replaceable>. " "One file or dir with priority per line. Priority -32768 to 32767, default " "priority 0" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:483 msgid "<option>-e <replaceable>list of exclude dirs/files</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:485 msgid "inline list of files / directories to exclude" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:491 msgid "<option>-ef <replaceable>exclude_file</replaceable></option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:493 msgid "file containing a list of files / directories to exclude, one per line" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:499 msgid "<option>-wildcards</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:500 msgid "Allow extended shell wildcards (globbing) to be used in exclude dirs/files" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><term> #: ../en/mksquashfs.dbk:505 msgid "<option>-regex</option>" msgstr "" # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para> #: ../en/mksquashfs.dbk:506 msgid "Allow POSIX regular expressions to be used in exclude dirs/files" msgstr "" # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:514 msgid "EXAMPLES" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:516 msgid "For following examples, take two example directories:" msgstr "" # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><para> #: ../en/mksquashfs.dbk:519 msgid "" "Source directory <filename>/home/phillip/test</filename> contains " "<filename>file1</filename>, <filename>file2</filename> and " "<filename>dir1</filename>." msgstr "" # type: Content of: <refentry><refsect1><para><itemizedlist><listitem><para> #: ../en/mksquashfs.dbk:525 msgid "" "Source directory <filename>goodies</filename> contains " "<filename>goodies1</filename>, <filename>goodies2</filename> and " "<filename>goodies3</filename>." msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:537 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test output_fs</userinput>" msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><para> #: ../en/mksquashfs.dbk:538 msgid "" "This will generate a squashfs filesystem with root entries " "<filename>file1</filename>, <filename>file2</filename> and " "<filename>dir1</filename>." msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:547 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test goodies output_fs</userinput>" msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><para> #: ../en/mksquashfs.dbk:548 msgid "" "This will create a squashfs filesystem with the root containing entries " "<filename>test</filename> and <filename>goodies</filename> corresponding to " "the source directories <filename>/home/phillip/test</filename> and " "<filename>goodies</filename>." msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:559 #, no-wrap msgid "<userinput>mksquashfs /home/phillip/test goodies test output_fs</userinput>" msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><para> #: ../en/mksquashfs.dbk:561 msgid "" "This is the same as the previous example, except a third source directory " "<filename>test</filename> has been specified. This conflicts with the first " "directory named <filename>test</filename> and will be renamed " "<filename>test_1</filename>." msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><para> #: ../en/mksquashfs.dbk:566 msgid "" "Multiple sources allow filesystems to be generated without needing to copy " "all source files into a common directory. This simplifies creating " "filesystems." msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><screen> #: ../en/mksquashfs.dbk:575 #, no-wrap msgid "" "<userinput>mksquashfs /home/phillip/test output_fs " "-keep-as-directory</userinput>" msgstr "" # type: Content of: <refentry><refsect1><refsect2><example><para> #: ../en/mksquashfs.dbk:577 msgid "" "This is the same as the first example, except for " "<option>-keep-as-directory</option>. This will generate a root directory " "containing directory <filename>test</filename>, rather than the " "<filename>test</filename> directory contents <filename>file1</filename>, " "<filename>file2</filename> and <filename>dir1</filename>." msgstr "" # type: Content of: <refentry><refsect1><title> #: ../en/mksquashfs.dbk:590 msgid "AUTHORS" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:592 msgid "" "Squashfs was written by <personname> <firstname>Phillip</firstname> " "<surname>Lougher</surname> </personname> " "<email>plougher@users.sourceforge.net</email>, in Chepstow, Wales, UK. If " "you like the program, or have any problems, then please email me, as it's " "nice to get feedback !" msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:600 msgid "" "This manual page was written by &dhusername; &dhemail; for the &debian; " "system (but may be used by others) using the <citetitle>SquashFS " "HOWTO</citetitle> from <author> <firstname>Artemiy I.</firstname> " "<surname>Pavlov</surname> </author> and squashfs's " "<filename>README</filename> file. Permission is granted to copy, distribute " "and/or modify this document under the terms of the &gnu; General Public " "License, Version 2 any later version published by the Free Software " "Foundation." msgstr "" # type: Content of: <refentry><refsect1><para> #: ../en/mksquashfs.dbk:613 msgid "" "On Debian systems, the complete text of the &gnu; General Public License can " "be found in <filename>/usr/share/common-licenses/GPL</filename>." msgstr "" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/doc/po/po4a.cfg ================================================ [po4a_langs] fr [po4a_paths] mksquashfs.pot fr:mksquashfs.fr.po [type:docbook] ../en/mksquashfs.dbk \ fr:../fr/mksquashfs.fr.dbk add_fr:mksquashfs.fr.add \ opt:"-o inline=<option> -M UTF-8" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/rules ================================================ #!/usr/bin/make -f # -*- mode: makefile; coding: utf-8 -*- # Common include files include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/makefile.mk # Path to squashfs-tools DEB_STOOLS = $(CURDIR)/squashfs3.3/squashfs-tools # Manpages stuff DOC_DIR = debian/doc PO_DIR = $(DOC_DIR)/po MAN_TMP_DIR = $(DOC_DIR)/manpages MANPAGES = $(addprefix $(DOC_DIR)/,en/mksquashfs.1 fr/mksquashfs.fr.1 en/unsquashfs.1) XSLT_CMD = xsltproc -''-nonet -''-param man.charmap.use.subset "0" DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl # Flags to GCC #CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE # The build directory is squashfs-tools DEB_MAKE_INVOKE := make DEB_MAKE_BUILD_TARGET := all DEB_MAKE_CHECK_TARGET := DEB_MAKE_CLEAN_TARGET := # Squashfs-tools manpages targets install/squashfs-lzma-tools:: po $(MANPAGES) po: mkdir -p $(dir $(MANPAGES)) cd $(PO_DIR) && po4a -v po4a.cfg %.1: %.dbk cd $(<D) && $(XSLT_CMD) $(DB2MAN) $(<F) mv $(@D)/*.1 $(DOC_DIR)/$(@F) ## Squashfs-modules packages STAMP_CONFIG = $(CURDIR)/debian/stamp-configure # Version of the Linux Kernel SRC_DIR_MOD = ksquashfs DIR_MOD = linux-2.6 SNAME = squashfs-lzma PSOURCE = $(SNAME)-source MNAME = $(SNAME)-modules pre-build:: # Create the 'linux-2.6' directory using last patch of squashfs, it is # needed for out-of-tree compilation if ! test -f $(STAMP_CONFIG); then \ mkdir -p $(DIR_MOD); \ cp $(SRC_DIR_MOD)/fs/squashfs/* $(DIR_MOD); \ cp $(SRC_DIR_MOD)/include/linux/* $(DIR_MOD); \ touch $(STAMP_CONFIG); \ fi # For creating correctly the 'squashfs-source' package which will be # used for building module package with custom kernel install/squashfs-lzma-source:: # Create the needed directories mkdir -p debian/modules/$(SNAME)/debian \ debian/$(PSOURCE)/usr/src # Copy the source and header files cp $(DIR_MOD)/*.h $(DIR_MOD)/*.c $(DIR_MOD)/Makefile \ debian/modules/$(SNAME) # Copy the debian specific files cp debian/changelog debian/compat debian/copyright debian/*.modules.in \ debian/modules/$(SNAME)/debian # This rules file is specific to m-a install -m755 debian/rules.modules \ debian/modules/$(SNAME)/debian/rules # Finally create the tarball which contains the modules directory cd debian && tar jcf $(PSOURCE)/usr/src/$(SNAME).tar.bz2 modules # Common targets clean:: rm -rf $(DOC_DIR)/fr $(DOC_DIR)/*.8 $(DOC_DIR)/*.1 $(DOC_DIR)/en/*.8 $(DIR_MOD) debian/modules rm -f $(DEB_STOOLS)/*.o $(DEB_STOOLS)/mksquashfs $(DEB_STOOLS)/unsquashfs $(STAMP_CONFIG) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/rules.modules ================================================ #!/usr/bin/make -f # -*- mode: makefile; coding: utf-8 -*- # prefix of the target package name PACKAGE=squashfs-lzma-modules # modifieable for experiments or debugging m-a MA_DIR ?= /usr/share/modass # load generic variable handling -include $(MA_DIR)/include/generic.make # load default rules, including kdist, kdist_image, ... -include $(MA_DIR)/include/common-rules.make # module assistant calculates all needed things for us and sets # following variables: # KSRC (kernel source directory), KVERS (kernel version string), KDREV # (revision of the Debian kernel-image package), CC (the correct # compiler), VERSION (the final package version string), PKGNAME (full # package name with KVERS included), DEB_DESTDIR (path to store DEBs) # The kdist_configure target is called by make-kpkg modules_config and # by kdist* rules by dependency. It should configure the module so it is # ready for compilation (mostly useful for calling configure). # prep-deb-files from module-assistant creates the neccessary debian/ files kdist_config: prep-deb-files # the kdist_clean target is called by make-kpkg modules_clean and from # kdist* rules. It is responsible for cleaning up any changes that have # been made by the other kdist_commands (except for the .deb files created) kdist_clean: $(MAKE) -C $(KSRC) M=$(PWD) clean binary-modules: dh_testroot dh_clean -k dh_installdirs $(MAKE) -C $(KSRC) M=$(PWD) modules # Install the module mkdir -p debian/$(PACKAGE)-$(KVERS)/lib/modules/$(KVERS)/kernel/fs/squashfs cp squashfs.ko debian/$(PACKAGE)-$(KVERS)/lib/modules/$(KVERS)/kernel/fs/squashfs dh_installdocs dh_installchangelogs dh_installmodules dh_compress dh_fixperms dh_installdeb dh_gencontrol -- -v$(VERSION) dh_md5sums dh_builddeb --destdir=$(DEB_DESTDIR) dh_clean -k ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-source.NEWS ================================================ squashfs (1:3.3-4) unstable; urgency=medium This version removes LZMA compression support again. Current released squashfs versions have bugs in lzma mode which are also affection the normal operation of squashfs when using zlib compression. This can be avoided by carefully tracking squashfs cvs, which the current maintainers of squashfs do not have the time for. Therefore, for the moment, lzma support is removed again. -- Daniel Baumann <daniel@debian.org> Fri, 21 Mar 2008 20:37:00 +0100 squashfs (1:3.2r2-9exp1) experimental; urgency=low This version introduces LZMA compression in addition of ZLIB. WARNING! The new squashfs image file (generated without '-nolzma' option) has no backward compatibility, while the patched squashfs and its tools can handle the old squashfs image generated by the unpatched squashfs-tools. -- Arnaud Fontaine <arnaud@andesi.org> Mon, 29 Oct 2007 20:06:05 +0000 squashfs (2.0-ALPHA-1) unstable; urgency=low WARNING! Images prepared by new mksquashfs 2.0 aren't readable by kernel with old squashfs 1.3 driver. You'll get the following kernel message: SQUASHFS error: Major/Minor mismatch, filesystem is (2:0), I support (1: <= 0) The new driver reads old images without problem. -- Piotr Roszatycki <dexter@debian.org> Mon, 21 Jun 2004 13:06:46 +0200 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-source.README.Debian ================================================ squashfs for Debian ------------------- The Squash filesystem driver isn't [currently] integrated in the official Linux kernel, so to be able to use such a filesystem, you need to use the 'squashfs-modules-*' package if you are using the official Debian kernel, or the 'squashfs-source' package otherwise (by using 'module-assistant': '# m-a install squashfs'). -- Arnaud Fontaine <arnau@debian.org>, Sun, 2 Apr 2006 11:47:00 +0200 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-source.docs ================================================ squashfs3.3/ACKNOWLEDGEMENTS squashfs3.3/PERFORMANCE.README squashfs3.3/README squashfs3.3/README-3.3 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-source.links ================================================ /usr/share/modass/packages/default.sh /usr/share/modass/overrides/squashfs-source ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-tools.README.Debian ================================================ this package from git.grml.org is packaged with topgit AND uses a temporary build branch (which is only tagged on release) # create the build branch git checkout build git reset --hard master for i in $(cat .tmpdeps|xargs); do g merge -n $i; done # building this package git checkout build (create as stated above) git-buildpackage --git-debian-branch=build # want to make your own modifications to the debian packaging just work on build branch and cherry-pick the changes back to master. after that recreate your build branch ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-tools.dirs ================================================ usr/bin ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-tools.install ================================================ squashfs3.3/squashfs-tools/mksquashfs /usr/bin squashfs3.3/squashfs-tools/unsquashfs /usr/bin ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/squashfs-lzma-tools.manpages ================================================ debian/doc/mksquashfs.1 debian/doc/mksquashfs.fr.1 debian/doc/unsquashfs.1 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/debian/watch ================================================ # watch control file for uscan version=3 opts="uversionmangle=s/-r/r/" \ ftp://heanet.dl.sourceforge.net/s/sq/squashfs/squashfs(.*)\.tar\.gz \ debian git-import-orig ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/fs/squashfs/Makefile ================================================ # # Makefile for the linux squashfs routines. # # the environment variables are not inherited since 2.6.23 ifdef SQLZMA_EXTRA_CFLAGS EXTRA_CFLAGS += ${SQLZMA_EXTRA_CFLAGS} endif obj-$(CONFIG_SQUASHFS) += squashfs.o squashfs-y += inode.o squashfs-y += squashfs2_0.o ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/fs/squashfs/inode.c ================================================ /* * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * inode.c */ #include <linux/squashfs_fs.h> #include <linux/module.h> #include <linux/zlib.h> #include <linux/fs.h> #include <linux/squashfs_fs_sb.h> #include <linux/squashfs_fs_i.h> #include <linux/buffer_head.h> #include <linux/vfs.h> #include <linux/vmalloc.h> #include <linux/smp_lock.h> #include <linux/exportfs.h> #include "squashfs.h" #include "sqlzma.h" #include "sqmagic.h" #undef KeepPreemptive #if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt) #define KeepPreemptive #endif struct sqlzma { #ifdef KeepPreemptive struct mutex mtx; #endif unsigned char read_data[SQUASHFS_FILE_MAX_SIZE]; struct sqlzma_un un; }; static DEFINE_PER_CPU(struct sqlzma *, sqlzma); #define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */ #define dpri_un(un) dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \ (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \ (un)->un_a[1].sz, (un)->un_a[1].buf, \ (un)->un_a[2].sz, (un)->un_a[2].buf) static int squashfs_cached_blks; static void vfs_read_inode(struct inode *i); static struct dentry *squashfs_get_parent(struct dentry *child); static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); static int squashfs_statfs(struct dentry *, struct kstatfs *); static int squashfs_symlink_readpage(struct file *file, struct page *page); static long long read_blocklist(struct inode *inode, int index, int readahead_blks, char *block_list, unsigned short **block_p, unsigned int *bsize); static int squashfs_readpage(struct file *file, struct page *page); static int squashfs_readdir(struct file *, void *, filldir_t); static struct dentry *squashfs_lookup(struct inode *, struct dentry *, struct nameidata *); static int squashfs_remount(struct super_block *s, int *flags, char *data); static void squashfs_put_super(struct super_block *); static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, struct vfsmount *); static struct inode *squashfs_alloc_inode(struct super_block *sb); static void squashfs_destroy_inode(struct inode *inode); static int init_inodecache(void); static void destroy_inodecache(void); static struct file_system_type squashfs_fs_type = { .owner = THIS_MODULE, .name = "squashfs", .get_sb = squashfs_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV }; static const unsigned char squashfs_filetype_table[] = { DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK }; static struct super_operations squashfs_super_ops = { .alloc_inode = squashfs_alloc_inode, .destroy_inode = squashfs_destroy_inode, .statfs = squashfs_statfs, .put_super = squashfs_put_super, .remount_fs = squashfs_remount }; static struct super_operations squashfs_export_super_ops = { .alloc_inode = squashfs_alloc_inode, .destroy_inode = squashfs_destroy_inode, .statfs = squashfs_statfs, .put_super = squashfs_put_super, .read_inode = vfs_read_inode }; static struct export_operations squashfs_export_ops = { .get_parent = squashfs_get_parent }; SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { .readpage = squashfs_symlink_readpage }; SQSH_EXTERN const struct address_space_operations squashfs_aops = { .readpage = squashfs_readpage }; static const struct file_operations squashfs_dir_ops = { .read = generic_read_dir, .readdir = squashfs_readdir }; SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { .lookup = squashfs_lookup }; static struct buffer_head *get_block_length(struct super_block *s, int *cur_index, int *offset, int *c_byte) { struct squashfs_sb_info *msblk = s->s_fs_info; unsigned short temp; struct buffer_head *bh; if (!(bh = sb_bread(s, *cur_index))) goto out; if (msblk->devblksize - *offset == 1) { if (msblk->swap) ((unsigned char *) &temp)[1] = *((unsigned char *) (bh->b_data + *offset)); else ((unsigned char *) &temp)[0] = *((unsigned char *) (bh->b_data + *offset)); brelse(bh); if (!(bh = sb_bread(s, ++(*cur_index)))) goto out; if (msblk->swap) ((unsigned char *) &temp)[0] = *((unsigned char *) bh->b_data); else ((unsigned char *) &temp)[1] = *((unsigned char *) bh->b_data); *c_byte = temp; *offset = 1; } else { if (msblk->swap) { ((unsigned char *) &temp)[1] = *((unsigned char *) (bh->b_data + *offset)); ((unsigned char *) &temp)[0] = *((unsigned char *) (bh->b_data + *offset + 1)); } else { ((unsigned char *) &temp)[0] = *((unsigned char *) (bh->b_data + *offset)); ((unsigned char *) &temp)[1] = *((unsigned char *) (bh->b_data + *offset + 1)); } *c_byte = temp; *offset += 2; } if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { if (*offset == msblk->devblksize) { brelse(bh); if (!(bh = sb_bread(s, ++(*cur_index)))) goto out; *offset = 0; } if (*((unsigned char *) (bh->b_data + *offset)) != SQUASHFS_MARKER_BYTE) { ERROR("Metadata block marker corrupt @ %x\n", *cur_index); brelse(bh); goto out; } (*offset)++; } return bh; out: return NULL; } SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, long long index, unsigned int length, long long *next_index, int srclength) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; struct buffer_head **bh; unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); unsigned int cur_index = index >> msblk->devblksize_log2; int bytes, avail_bytes, b = 0, k = 0; unsigned int compressed; unsigned int c_byte = length; bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * sizeof(struct buffer_head *), GFP_KERNEL); if (bh == NULL) goto read_failure; if (c_byte) { bytes = msblk->devblksize - offset; compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte, srclength); if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) goto read_failure; bh[0] = sb_getblk(s, cur_index); if (bh[0] == NULL) goto block_release; for (b = 1; bytes < c_byte; b++) { bh[b] = sb_getblk(s, ++cur_index); if (bh[b] == NULL) goto block_release; bytes += msblk->devblksize; } ll_rw_block(READ, b, bh); } else { if (index < 0 || (index + 2) > sblk->bytes_used) goto read_failure; bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); if (bh[0] == NULL) goto read_failure; bytes = msblk->devblksize - offset; compressed = SQUASHFS_COMPRESSED(c_byte); c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte); if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) goto read_failure; for (b = 1; bytes < c_byte; b++) { bh[b] = sb_getblk(s, ++cur_index); if (bh[b] == NULL) goto block_release; bytes += msblk->devblksize; } ll_rw_block(READ, b - 1, bh + 1); } if (compressed) { int zlib_err = Z_STREAM_END; int start; enum {Src, Dst}; struct sized_buf sbuf[2]; struct sqlzma *percpu; unsigned char *p; /* * uncompress block */ /* mutex_lock(&msblk->read_data_mutex); */ start = k; for (; k < b; k++) { wait_on_buffer(bh[k]); if (!buffer_uptodate(bh[k])) goto release_mutex; } /* it disables preemption */ percpu = get_cpu_var(sqlzma); #ifdef KeepPreemptive put_cpu_var(sqlzma); mutex_lock(&percpu->mtx); #endif p = percpu->read_data; k = start; for (bytes = 0; k < b; k++) { avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); if (k == 0) { /* * keep this block structture to simplify the * diff. */ if (avail_bytes == 0) { offset = 0; brelse(bh[k]); continue; } } memcpy(p, bh[k]->b_data + offset, avail_bytes); p += avail_bytes; #if 0 BUG_ON(percpu->read_data + sizeof(percpu->read_data) < p); #endif bytes += avail_bytes; offset = 0; brelse(bh[k]); } sbuf[Src].buf = percpu->read_data; sbuf[Src].sz = bytes; sbuf[Dst].buf = buffer; sbuf[Dst].sz = srclength; dpri_un(&percpu->un); dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf, sbuf[Dst].sz, sbuf[Dst].buf); zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst); bytes = percpu->un.un_reslen; #ifdef KeepPreemptive mutex_unlock(&percpu->mtx); #else put_cpu_var(sqlzma); #endif if (unlikely(zlib_err)) { dpri("zlib_err %d\n", zlib_err); goto release_mutex; } /* mutex_unlock(&msblk->read_data_mutex); */ } else { int i; for(i = 0; i < b; i++) { wait_on_buffer(bh[i]); if (!buffer_uptodate(bh[i])) goto block_release; } for (bytes = 0; k < b; k++) { avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); bytes += avail_bytes; offset = 0; brelse(bh[k]); } } if (next_index) *next_index = index + c_byte + (length ? 0 : (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); kfree(bh); return bytes; release_mutex: /* mutex_unlock(&msblk->read_data_mutex); */ block_release: for (; k < b; k++) brelse(bh[k]); read_failure: ERROR("sb_bread failed reading block 0x%x\n", cur_index); kfree(bh); return 0; } SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, long long block, unsigned int offset, int length, long long *next_block, unsigned int *next_offset) { struct squashfs_sb_info *msblk = s->s_fs_info; int n, i, bytes, return_length = length; long long next_index; TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); while (1) { for (i = 0; i < squashfs_cached_blks; i++) if (msblk->block_cache[i].block == block) break; mutex_lock(&msblk->block_cache_mutex); if (i == squashfs_cached_blks) { /* read inode header block */ if (msblk->unused_cache_blks == 0) { mutex_unlock(&msblk->block_cache_mutex); wait_event(msblk->waitq, msblk->unused_cache_blks); continue; } i = msblk->next_cache; for (n = 0; n < squashfs_cached_blks; n++) { if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) break; i = (i + 1) % squashfs_cached_blks; } msblk->next_cache = (i + 1) % squashfs_cached_blks; if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); if (msblk->block_cache[i].data == NULL) { ERROR("Failed to allocate cache block\n"); mutex_unlock(&msblk->block_cache_mutex); goto out; } } msblk->block_cache[i].block = SQUASHFS_USED_BLK; msblk->unused_cache_blks --; mutex_unlock(&msblk->block_cache_mutex); msblk->block_cache[i].length = squashfs_read_data(s, msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE); if (msblk->block_cache[i].length == 0) { ERROR("Unable to read cache block [%llx:%x]\n", block, offset); mutex_lock(&msblk->block_cache_mutex); msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; msblk->unused_cache_blks ++; smp_mb(); vfree(msblk->block_cache[i].data); wake_up(&msblk->waitq); mutex_unlock(&msblk->block_cache_mutex); goto out; } mutex_lock(&msblk->block_cache_mutex); msblk->block_cache[i].block = block; msblk->block_cache[i].next_index = next_index; msblk->unused_cache_blks ++; smp_mb(); wake_up(&msblk->waitq); TRACE("Read cache block [%llx:%x]\n", block, offset); } if (msblk->block_cache[i].block != block) { mutex_unlock(&msblk->block_cache_mutex); continue; } bytes = msblk->block_cache[i].length - offset; if (bytes < 1) { mutex_unlock(&msblk->block_cache_mutex); goto out; } else if (bytes >= length) { if (buffer) memcpy(buffer, msblk->block_cache[i].data + offset, length); if (msblk->block_cache[i].length - offset == length) { *next_block = msblk->block_cache[i].next_index; *next_offset = 0; } else { *next_block = block; *next_offset = offset + length; } mutex_unlock(&msblk->block_cache_mutex); goto finish; } else { if (buffer) { memcpy(buffer, msblk->block_cache[i].data + offset, bytes); buffer = (char *) buffer + bytes; } block = msblk->block_cache[i].next_index; mutex_unlock(&msblk->block_cache_mutex); length -= bytes; offset = 0; } } finish: return return_length; out: return 0; } static int get_fragment_location(struct super_block *s, unsigned int fragment, long long *fragment_start_block, unsigned int *fragment_size) { struct squashfs_sb_info *msblk = s->s_fs_info; long long start_block = msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); struct squashfs_fragment_entry fragment_entry; if (msblk->swap) { struct squashfs_fragment_entry sfragment_entry; if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, sizeof(sfragment_entry), &start_block, &offset)) goto out; SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); } else if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, sizeof(fragment_entry), &start_block, &offset)) goto out; *fragment_start_block = fragment_entry.start_block; *fragment_size = fragment_entry.size; return 1; out: return 0; } SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct squashfs_fragment_cache *fragment) { mutex_lock(&msblk->fragment_mutex); fragment->locked --; if (fragment->locked == 0) { msblk->unused_frag_blks ++; smp_mb(); wake_up(&msblk->fragment_wait_queue); } mutex_unlock(&msblk->fragment_mutex); } SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, long long start_block, int length) { int i, n; struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; while (1) { mutex_lock(&msblk->fragment_mutex); for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && msblk->fragment[i].block != start_block; i++); if (i == SQUASHFS_CACHED_FRAGMENTS) { if (msblk->unused_frag_blks == 0) { mutex_unlock(&msblk->fragment_mutex); wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); continue; } i = msblk->next_fragment; for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { if (msblk->fragment[i].locked == 0) break; i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; } msblk->next_fragment = (msblk->next_fragment + 1) % SQUASHFS_CACHED_FRAGMENTS; if (msblk->fragment[i].data == NULL) { msblk->fragment[i].data = vmalloc(sblk->block_size); if (msblk->fragment[i].data == NULL) { ERROR("Failed to allocate fragment cache block\n"); mutex_unlock(&msblk->fragment_mutex); goto out; } } msblk->unused_frag_blks --; msblk->fragment[i].block = SQUASHFS_INVALID_BLK; msblk->fragment[i].locked = 1; mutex_unlock(&msblk->fragment_mutex); msblk->fragment[i].length = squashfs_read_data(s, msblk->fragment[i].data, start_block, length, NULL, sblk->block_size); if (msblk->fragment[i].length == 0) { ERROR("Unable to read fragment cache block [%llx]\n", start_block); msblk->fragment[i].locked = 0; msblk->unused_frag_blks ++; smp_mb(); wake_up(&msblk->fragment_wait_queue); goto out; } mutex_lock(&msblk->fragment_mutex); msblk->fragment[i].block = start_block; TRACE("New fragment %d, start block %lld, locked %d\n", i, msblk->fragment[i].block, msblk->fragment[i].locked); mutex_unlock(&msblk->fragment_mutex); break; } if (msblk->fragment[i].locked == 0) msblk->unused_frag_blks --; msblk->fragment[i].locked++; mutex_unlock(&msblk->fragment_mutex); TRACE("Got fragment %d, start block %lld, locked %d\n", i, msblk->fragment[i].block, msblk->fragment[i].locked); break; } return &msblk->fragment[i]; out: return NULL; } static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, struct squashfs_base_inode_header *inodeb) { i->i_ino = inodeb->inode_number; i->i_mtime.tv_sec = inodeb->mtime; i->i_atime.tv_sec = inodeb->mtime; i->i_ctime.tv_sec = inodeb->mtime; i->i_uid = msblk->uid[inodeb->uid]; i->i_mode = inodeb->mode; i->i_size = 0; if (inodeb->guid == SQUASHFS_GUIDS) i->i_gid = i->i_uid; else i->i_gid = msblk->guid[inodeb->guid]; } static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) { struct squashfs_sb_info *msblk = s->s_fs_info; long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); squashfs_inode_t inode; TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); if (msblk->swap) { squashfs_inode_t sinode; if (!squashfs_get_cached_block(s, &sinode, start, offset, sizeof(sinode), &start, &offset)) goto out; SQUASHFS_SWAP_INODE_T((&inode), &sinode); } else if (!squashfs_get_cached_block(s, &inode, start, offset, sizeof(inode), &start, &offset)) goto out; TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); return inode; out: return SQUASHFS_INVALID_BLK; } static void vfs_read_inode(struct inode *i) { struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); TRACE("Entered vfs_read_inode\n"); if(inode != SQUASHFS_INVALID_BLK) (msblk->read_inode)(i, inode); } static struct dentry *squashfs_get_parent(struct dentry *child) { struct inode *i = child->d_inode; struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); struct dentry *rv; TRACE("Entered squashfs_get_parent\n"); if(parent == NULL) { rv = ERR_PTR(-EACCES); goto out; } rv = d_alloc_anon(parent); if(rv == NULL) rv = ERR_PTR(-ENOMEM); out: return rv; } SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number) { struct squashfs_sb_info *msblk = s->s_fs_info; struct inode *i = iget_locked(s, inode_number); TRACE("Entered squashfs_iget\n"); if(i && (i->i_state & I_NEW)) { (msblk->read_inode)(i, inode); unlock_new_inode(i); } return i; } static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) { struct super_block *s = i->i_sb; struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; unsigned int offset = SQUASHFS_INODE_OFFSET(inode); long long next_block; unsigned int next_offset; union squashfs_inode_header id, sid; struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; TRACE("Entered squashfs_read_inode\n"); if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodeb, block, offset, sizeof(*sinodeb), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); } else if (!squashfs_get_cached_block(s, inodeb, block, offset, sizeof(*inodeb), &next_block, &next_offset)) goto failed_read; squashfs_new_inode(msblk, i, inodeb); switch(inodeb->inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_size; long long frag_blk; struct squashfs_reg_inode_header *inodep = &id.reg; struct squashfs_reg_inode_header *sinodep = &sid.reg; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; frag_blk = SQUASHFS_INVALID_BLK; if (inodep->fragment != SQUASHFS_INVALID_FRAG) if(!get_fragment_location(s, inodep->fragment, &frag_blk, &frag_size)) goto failed_read; i->i_nlink = 1; i->i_size = inodep->file_size; i->i_fop = &generic_ro_fops; i->i_mode |= S_IFREG; i->i_blocks = ((i->i_size - 1) >> 9) + 1; SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; SQUASHFS_I(i)->u.s1.fragment_size = frag_size; SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->u.s1.block_list_start = next_block; SQUASHFS_I(i)->offset = next_offset; i->i_data.a_ops = &squashfs_aops; TRACE("File inode %x:%x, start_block %llx, " "block_list_start %llx, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, next_block, next_offset); break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_size; long long frag_blk; struct squashfs_lreg_inode_header *inodep = &id.lreg; struct squashfs_lreg_inode_header *sinodep = &sid.lreg; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; frag_blk = SQUASHFS_INVALID_BLK; if (inodep->fragment != SQUASHFS_INVALID_FRAG) if (!get_fragment_location(s, inodep->fragment, &frag_blk, &frag_size)) goto failed_read; i->i_nlink = inodep->nlink; i->i_size = inodep->file_size; i->i_fop = &generic_ro_fops; i->i_mode |= S_IFREG; i->i_blocks = ((i->i_size - 1) >> 9) + 1; SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; SQUASHFS_I(i)->u.s1.fragment_size = frag_size; SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->u.s1.block_list_start = next_block; SQUASHFS_I(i)->offset = next_offset; i->i_data.a_ops = &squashfs_aops; TRACE("File inode %x:%x, start_block %llx, " "block_list_start %llx, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, next_block, next_offset); break; } case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header *inodep = &id.dir; struct squashfs_dir_inode_header *sinodep = &sid.dir; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_nlink = inodep->nlink; i->i_size = inodep->file_size; i->i_op = &squashfs_dir_inode_ops; i->i_fop = &squashfs_dir_ops; i->i_mode |= S_IFDIR; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->offset = inodep->offset; SQUASHFS_I(i)->u.s2.directory_index_count = 0; SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; TRACE("Directory inode %x:%x, start_block %x, offset " "%x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, inodep->offset); break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header *inodep = &id.ldir; struct squashfs_ldir_inode_header *sinodep = &sid.ldir; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_nlink = inodep->nlink; i->i_size = inodep->file_size; i->i_op = &squashfs_dir_inode_ops; i->i_fop = &squashfs_dir_ops; i->i_mode |= S_IFDIR; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->offset = inodep->offset; SQUASHFS_I(i)->u.s2.directory_index_start = next_block; SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, inodep->offset); break; } case SQUASHFS_SYMLINK_TYPE: { struct squashfs_symlink_inode_header *inodep = &id.symlink; struct squashfs_symlink_inode_header *sinodep = &sid.symlink; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_nlink = inodep->nlink; i->i_size = inodep->symlink_size; i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &squashfs_symlink_aops; i->i_mode |= S_IFLNK; SQUASHFS_I(i)->start_block = next_block; SQUASHFS_I(i)->offset = next_offset; TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset); break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { struct squashfs_dev_inode_header *inodep = &id.dev; struct squashfs_dev_inode_header *sinodep = &sid.dev; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_nlink = inodep->nlink; i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK; init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { struct squashfs_ipc_inode_header *inodep = &id.ipc; struct squashfs_ipc_inode_header *sinodep = &sid.ipc; if (msblk->swap) { if (!squashfs_get_cached_block(s, sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); } else if (!squashfs_get_cached_block(s, inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_nlink = inodep->nlink; i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK; init_special_inode(i, i->i_mode, 0); break; } default: ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb->inode_type); goto failed_read1; } return 1; failed_read: ERROR("Unable to read inode [%llx:%x]\n", block, offset); failed_read1: make_bad_inode(i); return 0; } static int read_inode_lookup_table(struct super_block *s) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); TRACE("In read_inode_lookup_table, length %d\n", length); /* Allocate inode lookup table */ msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); if (msblk->inode_lookup_table == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, sblk->lookup_table_start, length | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { ERROR("unable to read inode lookup table\n"); return 0; } if (msblk->swap) { int i; long long block; for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { /* XXX */ SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), &msblk->inode_lookup_table[i], 1); msblk->inode_lookup_table[i] = block; } } return 1; } static int read_fragment_index_table(struct super_block *s) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); if(length == 0) return 1; /* Allocate fragment index table */ msblk->fragment_index = kmalloc(length, GFP_KERNEL); if (msblk->fragment_index == NULL) { ERROR("Failed to allocate fragment index table\n"); return 0; } if (!squashfs_read_data(s, (char *) msblk->fragment_index, sblk->fragment_table_start, length | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { ERROR("unable to read fragment index table\n"); return 0; } if (msblk->swap) { int i; long long fragment; for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { /* XXX */ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), &msblk->fragment_index[i], 1); msblk->fragment_index[i] = fragment; } } return 1; } static int readahead_metadata(struct super_block *s) { struct squashfs_sb_info *msblk = s->s_fs_info; int i; squashfs_cached_blks = SQUASHFS_CACHED_BLKS; /* Init inode_table block pointer array */ msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * squashfs_cached_blks, GFP_KERNEL); if (msblk->block_cache == NULL) { ERROR("Failed to allocate block cache\n"); goto failed; } for (i = 0; i < squashfs_cached_blks; i++) msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; msblk->next_cache = 0; msblk->unused_cache_blks = squashfs_cached_blks; return 1; failed: return 0; } static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) { struct squashfs_super_block *sblk = &msblk->sblk; msblk->read_inode = squashfs_read_inode; msblk->read_blocklist = read_blocklist; msblk->read_fragment_index_table = read_fragment_index_table; if (sblk->s_major == 1) { if (!squashfs_1_0_supported(msblk)) { SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " "are unsupported\n"); SERROR("Please recompile with Squashfs 1.0 support enabled\n"); return 0; } } else if (sblk->s_major == 2) { if (!squashfs_2_0_supported(msblk)) { SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " "are unsupported\n"); SERROR("Please recompile with Squashfs 2.0 support enabled\n"); return 0; } } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > SQUASHFS_MINOR) { SERROR("Major/Minor mismatch, trying to mount newer %d.%d " "filesystem\n", sblk->s_major, sblk->s_minor); SERROR("Please update your kernel\n"); return 0; } return 1; } static int squashfs_fill_super(struct super_block *s, void *data, int silent) { struct squashfs_sb_info *msblk; struct squashfs_super_block *sblk; int i, err; char b[BDEVNAME_SIZE]; struct inode *root; TRACE("Entered squashfs_fill_superblock\n"); err = -ENOMEM; s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); if (s->s_fs_info == NULL) { ERROR("Failed to allocate superblock\n"); goto failure; } msblk = s->s_fs_info; sblk = &msblk->sblk; msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); msblk->devblksize_log2 = ffz(~msblk->devblksize); /* mutex_init(&msblk->read_data_mutex); */ mutex_init(&msblk->read_page_mutex); mutex_init(&msblk->block_cache_mutex); mutex_init(&msblk->fragment_mutex); mutex_init(&msblk->meta_index_mutex); init_waitqueue_head(&msblk->waitq); init_waitqueue_head(&msblk->fragment_wait_queue); /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not * beyond filesystem end. As we're using squashfs_read_data to read sblk here, * first set sblk->bytes_used to a useful value */ err = -EINVAL; sblk->bytes_used = sizeof(struct squashfs_super_block); if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, sizeof(struct squashfs_super_block) | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { SERROR("unable to read superblock\n"); goto failed_mount; } /* Check it is a SQUASHFS superblock */ s->s_magic = sblk->s_magic; msblk->swap = 0; dpri("magic 0x%x\n", sblk->s_magic); switch (sblk->s_magic) { struct squashfs_super_block ssblk; case SQUASHFS_MAGIC_SWAP: /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: WARNING("Mounting a different endian SQUASHFS " "filesystem on %s\n", bdevname(s->s_bdev, b)); SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); msblk->swap = 1; /*FALLTHROUGH*/ case SQUASHFS_MAGIC: case SQUASHFS_MAGIC_LZMA: break; default: SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(s->s_bdev, b)); goto failed_mount; } { struct sqlzma *p; dpri("block_size %d, devblksize %d\n", sblk->block_size, msblk->devblksize); BUG_ON(sblk->block_size > sizeof(p->read_data)); } /* Check the MAJOR & MINOR versions */ if(!supported_squashfs_filesystem(msblk, silent)) goto failed_mount; /* Check the filesystem does not extend beyond the end of the block device */ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) goto failed_mount; /* Check the root inode for sanity */ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) goto failed_mount; TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) ? "un" : ""); TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) ? "un" : ""); TRACE("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); TRACE("Block size %d\n", sblk->block_size); TRACE("Number of inodes %d\n", sblk->inodes); if (sblk->s_major > 1) TRACE("Number of fragments %d\n", sblk->fragments); TRACE("Number of uids %d\n", sblk->no_uids); TRACE("Number of gids %d\n", sblk->no_guids); TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); if (sblk->s_major > 1) TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); TRACE("sblk->uid_start %llx\n", sblk->uid_start); s->s_maxbytes = MAX_LFS_FILESIZE; s->s_flags |= MS_RDONLY; s->s_op = &squashfs_super_ops; if (readahead_metadata(s) == 0) goto failed_mount; /* Allocate read_page block */ err = -ENOMEM; msblk->read_page = vmalloc(sblk->block_size); if (msblk->read_page == NULL) { ERROR("Failed to allocate read_page block\n"); goto failed_mount; } /* Allocate uid and gid tables */ msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * sizeof(unsigned int), GFP_KERNEL); if (msblk->uid == NULL) { ERROR("Failed to allocate uid/gid table\n"); goto failed_mount; } msblk->guid = msblk->uid + sblk->no_uids; dpri("swap %d\n", msblk->swap); err = -EINVAL; if (msblk->swap) { unsigned int *suid; err = -ENOMEM; suid = kmalloc(sizeof(*suid) * (sblk->no_uids + sblk->no_guids), GFP_KERNEL); if (unlikely(!suid)) goto failed_mount; err = -EINVAL; if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, ((sblk->no_uids + sblk->no_guids) * sizeof(unsigned int)) | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { ERROR("unable to read uid/gid table\n"); kfree(suid); goto failed_mount; } SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + sblk->no_guids), (sizeof(unsigned int) * 8)); kfree(suid); } else if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, ((sblk->no_uids + sblk->no_guids) * sizeof(unsigned int)) | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { ERROR("unable to read uid/gid table\n"); goto failed_mount; } if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) goto allocate_root; err = -ENOMEM; msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); if (msblk->fragment == NULL) { ERROR("Failed to allocate fragment block cache\n"); goto failed_mount; } for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { msblk->fragment[i].block = SQUASHFS_INVALID_BLK; } msblk->next_fragment = 0; msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; /* Allocate and read fragment index table */ if (msblk->read_fragment_index_table(s) == 0) goto failed_mount; if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) goto allocate_root; /* Allocate and read inode lookup table */ if (read_inode_lookup_table(s) == 0) goto failed_mount; s->s_op = &squashfs_export_super_ops; s->s_export_op = &squashfs_export_ops; allocate_root: dpri("alloate_root\n"); root = new_inode(s); if ((msblk->read_inode)(root, sblk->root_inode) == 0) { iput(root); goto failed_mount; } insert_inode_hash(root); s->s_root = d_alloc_root(root); if (s->s_root == NULL) { ERROR("Root inode create failed\n"); iput(root); goto failed_mount; } TRACE("Leaving squashfs_fill_super\n"); return 0; failed_mount: kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->fragment); kfree(msblk->uid); vfree(msblk->read_page); kfree(msblk->block_cache); kfree(msblk->fragment_index_2); kfree(s->s_fs_info); s->s_fs_info = NULL; failure: return err; } static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; TRACE("Entered squashfs_statfs\n"); buf->f_type = sblk->s_magic; buf->f_bsize = sblk->block_size; buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; buf->f_bfree = buf->f_bavail = 0; buf->f_files = sblk->inodes; buf->f_ffree = 0; buf->f_namelen = SQUASHFS_NAME_LEN; return 0; } static int squashfs_symlink_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; long long block = SQUASHFS_I(inode)->start_block; int offset = SQUASHFS_I(inode)->offset; void *pageaddr = kmap(page); TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " "%llx, offset %x\n", page->index, SQUASHFS_I(inode)->start_block, SQUASHFS_I(inode)->offset); for (length = 0; length < index; length += bytes) { bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, offset, PAGE_CACHE_SIZE, &block, &offset); if (bytes == 0) { ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); goto skip_read; } } if (length != index) { ERROR("(squashfs_symlink_readpage) length != index\n"); bytes = 0; goto skip_read; } avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, avail_bytes, &block, &offset); if (bytes == 0) ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); skip_read: memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); kunmap(page); flush_dcache_page(page); SetPageUptodate(page); unlock_page(page); return 0; } struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) { struct meta_index *meta = NULL; struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; int i; mutex_lock(&msblk->meta_index_mutex); TRACE("locate_meta_index: index %d, offset %d\n", index, offset); if (msblk->meta_index == NULL) goto not_allocated; for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { if (msblk->meta_index[i].inode_number == inode->i_ino && msblk->meta_index[i].offset >= offset && msblk->meta_index[i].offset <= index && msblk->meta_index[i].locked == 0) { TRACE("locate_meta_index: entry %d, offset %d\n", i, msblk->meta_index[i].offset); meta = &msblk->meta_index[i]; offset = meta->offset; } } if (meta) meta->locked = 1; not_allocated: mutex_unlock(&msblk->meta_index_mutex); return meta; } struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) { struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; struct meta_index *meta = NULL; int i; mutex_lock(&msblk->meta_index_mutex); TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); if (msblk->meta_index == NULL) { msblk->meta_index = kmalloc(sizeof(struct meta_index) * SQUASHFS_META_NUMBER, GFP_KERNEL); if (msblk->meta_index == NULL) { ERROR("Failed to allocate meta_index\n"); goto failed; } for (i = 0; i < SQUASHFS_META_NUMBER; i++) { msblk->meta_index[i].inode_number = 0; msblk->meta_index[i].locked = 0; } msblk->next_meta_index = 0; } for (i = SQUASHFS_META_NUMBER; i && msblk->meta_index[msblk->next_meta_index].locked; i --) msblk->next_meta_index = (msblk->next_meta_index + 1) % SQUASHFS_META_NUMBER; if (i == 0) { TRACE("empty_meta_index: failed!\n"); goto failed; } TRACE("empty_meta_index: returned meta entry %d, %p\n", msblk->next_meta_index, &msblk->meta_index[msblk->next_meta_index]); meta = &msblk->meta_index[msblk->next_meta_index]; msblk->next_meta_index = (msblk->next_meta_index + 1) % SQUASHFS_META_NUMBER; meta->inode_number = inode->i_ino; meta->offset = offset; meta->skip = skip; meta->entries = 0; meta->locked = 1; failed: mutex_unlock(&msblk->meta_index_mutex); return meta; } void release_meta_index(struct inode *inode, struct meta_index *meta) { meta->locked = 0; smp_mb(); } static int read_block_index(struct super_block *s, int blocks, char *block_list, long long *start_block, int *offset) { struct squashfs_sb_info *msblk = s->s_fs_info; unsigned int *block_listp; int block = 0; if (msblk->swap) { char *sblock_list; sblock_list = kmalloc(blocks << 2, GFP_KERNEL); if (unlikely(!sblock_list)) goto failure; if (!squashfs_get_cached_block(s, sblock_list, *start_block, *offset, blocks << 2, start_block, offset)) { ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); kfree(sblock_list); goto failure; } SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ((unsigned int *)sblock_list), blocks); kfree(sblock_list); } else { if (!squashfs_get_cached_block(s, block_list, *start_block, *offset, blocks << 2, start_block, offset)) { ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); goto failure; } } for (block_listp = (unsigned int *) block_list; blocks; block_listp++, blocks --) block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); return block; failure: return -1; } #define SIZE 256 static inline int calculate_skip(int blocks) { int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); return skip >= 7 ? 7 : skip + 1; } static int get_meta_index(struct inode *inode, int index, long long *index_block, int *index_offset, long long *data_block, char *block_list) { struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); int offset = 0; struct meta_index *meta; struct meta_entry *meta_entry; long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; int cur_offset = SQUASHFS_I(inode)->offset; long long cur_data_block = SQUASHFS_I(inode)->start_block; int i; index /= SQUASHFS_META_INDEXES * skip; while (offset < index) { meta = locate_meta_index(inode, index, offset + 1); if (meta == NULL) { meta = empty_meta_index(inode, offset + 1, skip); if (meta == NULL) goto all_done; } else { if(meta->entries == 0) goto failed; /* XXX */ offset = index < meta->offset + meta->entries ? index : meta->offset + meta->entries - 1; /* XXX */ meta_entry = &meta->meta_entry[offset - meta->offset]; cur_index_block = meta_entry->index_block + sblk->inode_table_start; cur_offset = meta_entry->offset; cur_data_block = meta_entry->data_block; TRACE("get_meta_index: offset %d, meta->offset %d, " "meta->entries %d\n", offset, meta->offset, meta->entries); TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" " data_block 0x%llx\n", cur_index_block, cur_offset, cur_data_block); } for (i = meta->offset + meta->entries; i <= index && i < meta->offset + SQUASHFS_META_ENTRIES; i++) { int blocks = skip * SQUASHFS_META_INDEXES; while (blocks) { int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; int res = read_block_index(inode->i_sb, block, block_list, &cur_index_block, &cur_offset); if (res == -1) goto failed; cur_data_block += res; blocks -= block; } meta_entry = &meta->meta_entry[i - meta->offset]; meta_entry->index_block = cur_index_block - sblk->inode_table_start; meta_entry->offset = cur_offset; meta_entry->data_block = cur_data_block; meta->entries ++; offset ++; } TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", meta->offset, meta->entries); release_meta_index(inode, meta); } all_done: *index_block = cur_index_block; *index_offset = cur_offset; *data_block = cur_data_block; return offset * SQUASHFS_META_INDEXES * skip; failed: release_meta_index(inode, meta); return -1; } static long long read_blocklist(struct inode *inode, int index, int readahead_blks, char *block_list, unsigned short **block_p, unsigned int *bsize) { long long block_ptr; int offset; long long block; int res = get_meta_index(inode, index, &block_ptr, &offset, &block, block_list); TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); if(res == -1) goto failure; index -= res; while (index) { int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; int res = read_block_index(inode->i_sb, blocks, block_list, &block_ptr, &offset); if (res == -1) goto failure; block += res; index -= blocks; } if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) goto failure; *bsize = *((unsigned int *) block_list); return block; failure: return 0; } static int squashfs_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; unsigned char *block_list = NULL; long long block; unsigned int bsize, i; int bytes; int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); void *pageaddr; struct squashfs_fragment_cache *fragment = NULL; char *data_ptr = msblk->read_page; int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; int start_index = page->index & ~mask; int end_index = start_index | mask; int file_end = i_size_read(inode) >> sblk->block_log; int sparse = 0; TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", page->index, SQUASHFS_I(inode)->start_block); if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)) goto out; if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK || index < file_end) { block_list = kmalloc(SIZE, GFP_KERNEL); if (block_list == NULL) { ERROR("Failed to allocate block_list\n"); goto error_out; } block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); if (block == 0) goto error_out; if (bsize == 0) { /* hole */ bytes = index == file_end ? (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; sparse = 1; } else { mutex_lock(&msblk->read_page_mutex); bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, bsize, NULL, sblk->block_size); if (bytes == 0) { ERROR("Unable to read page, block %llx, size %x\n", block, bsize); mutex_unlock(&msblk->read_page_mutex); goto error_out; } } } else { fragment = get_cached_fragment(inode->i_sb, SQUASHFS_I(inode)-> u.s1.fragment_start_block, SQUASHFS_I(inode)->u.s1.fragment_size); if (fragment == NULL) { ERROR("Unable to read page, block %llx, size %x\n", SQUASHFS_I(inode)->u.s1.fragment_start_block, (int) SQUASHFS_I(inode)->u.s1.fragment_size); goto error_out; } bytes = i_size_read(inode) & (sblk->block_size - 1); data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; } for (i = start_index; i <= end_index && bytes > 0; i++, bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { struct page *push_page; int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); push_page = (i == page->index) ? page : grab_cache_page_nowait(page->mapping, i); if (!push_page) continue; if (PageUptodate(push_page)) goto skip_page; pageaddr = kmap_atomic(push_page, KM_USER0); memcpy(pageaddr, data_ptr, avail); memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); kunmap_atomic(pageaddr, KM_USER0); flush_dcache_page(push_page); SetPageUptodate(push_page); skip_page: unlock_page(push_page); if(i != page->index) page_cache_release(push_page); } if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK || index < file_end) { if (!sparse) mutex_unlock(&msblk->read_page_mutex); kfree(block_list); } else release_cached_fragment(msblk, fragment); return 0; error_out: SetPageError(page); out: pageaddr = kmap_atomic(page, KM_USER0); memset(pageaddr, 0, PAGE_CACHE_SIZE); kunmap_atomic(pageaddr, KM_USER0); flush_dcache_page(page); if (!PageError(page)) SetPageUptodate(page); unlock_page(page); kfree(block_list); return 0; } static int get_dir_index_using_offset(struct super_block *s, long long *next_block, unsigned int *next_offset, long long index_start, unsigned int index_offset, int i_count, long long f_pos) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; int i, length = 0; struct squashfs_dir_index index; TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", i_count, (unsigned int) f_pos); f_pos =- 3; if (f_pos == 0) goto finish; for (i = 0; i < i_count; i++) { if (msblk->swap) { struct squashfs_dir_index sindex; squashfs_get_cached_block(s, &sindex, index_start, index_offset, sizeof(sindex), &index_start, &index_offset); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else squashfs_get_cached_block(s, &index, index_start, index_offset, sizeof(index), &index_start, &index_offset); if (index.index > f_pos) break; squashfs_get_cached_block(s, NULL, index_start, index_offset, index.size + 1, &index_start, &index_offset); length = index.index; *next_block = index.start_block + sblk->directory_table_start; } *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; finish: return length + 3; } static int get_dir_index_using_name(struct super_block *s, long long *next_block, unsigned int *next_offset, long long index_start, unsigned int index_offset, int i_count, const char *name, int size) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; int i, length = 0; struct squashfs_dir_index *index; char *str; TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); str = kmalloc(sizeof(struct squashfs_dir_index) + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); if (str == NULL) { ERROR("Failed to allocate squashfs_dir_index\n"); goto failure; } index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); strncpy(str, name, size); str[size] = '\0'; for (i = 0; i < i_count; i++) { if (msblk->swap) { struct squashfs_dir_index sindex; squashfs_get_cached_block(s, &sindex, index_start, index_offset, sizeof(sindex), &index_start, &index_offset); SQUASHFS_SWAP_DIR_INDEX(index, &sindex); } else squashfs_get_cached_block(s, index, index_start, index_offset, sizeof(struct squashfs_dir_index), &index_start, &index_offset); squashfs_get_cached_block(s, index->name, index_start, index_offset, index->size + 1, &index_start, &index_offset); index->name[index->size + 1] = '\0'; if (strcmp(index->name, str) > 0) break; length = index->index; *next_block = index->start_block + sblk->directory_table_start; } *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; kfree(str); failure: return length + 3; } static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) { struct inode *i = file->f_dentry->d_inode; struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; long long next_block = SQUASHFS_I(i)->start_block + sblk->directory_table_start; int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; struct squashfs_dir_header dirh; struct squashfs_dir_entry *dire; TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); dire = kmalloc(sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); if (dire == NULL) { ERROR("Failed to allocate squashfs_dir_entry\n"); goto finish; } while(file->f_pos < 3) { char *name; int size, i_ino; if(file->f_pos == 0) { name = "."; size = 1; i_ino = i->i_ino; } else { name = ".."; size = 2; i_ino = SQUASHFS_I(i)->u.s2.parent_inode; } TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", (unsigned int) dirent, name, size, (int) file->f_pos, i_ino, squashfs_filetype_table[1]); if (filldir(dirent, name, size, file->f_pos, i_ino, squashfs_filetype_table[1]) < 0) { TRACE("Filldir returned less than 0\n"); goto finish; } file->f_pos += size; } length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, SQUASHFS_I(i)->u.s2.directory_index_start, SQUASHFS_I(i)->u.s2.directory_index_offset, SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); while (length < i_size_read(i)) { /* read directory header */ if (msblk->swap) { struct squashfs_dir_header sdirh; if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, next_offset, sizeof(sdirh), &next_block, &next_offset)) goto failed_read; length += sizeof(sdirh); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else { if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, next_offset, sizeof(dirh), &next_block, &next_offset)) goto failed_read; length += sizeof(dirh); } dir_count = dirh.count + 1; while (dir_count--) { if (msblk->swap) { struct squashfs_dir_entry sdire; if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, next_offset, sizeof(sdire), &next_block, &next_offset)) goto failed_read; length += sizeof(sdire); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else { if (!squashfs_get_cached_block(i->i_sb, dire, next_block, next_offset, sizeof(*dire), &next_block, &next_offset)) goto failed_read; length += sizeof(*dire); } if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, next_offset, dire->size + 1, &next_block, &next_offset)) goto failed_read; length += dire->size + 1; if (file->f_pos >= length) continue; dire->name[dire->size + 1] = '\0'; TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", (unsigned int) dirent, dire->name, dire->size + 1, (int) file->f_pos, dirh.start_block, dire->offset, dirh.inode_number + dire->inode_number, squashfs_filetype_table[dire->type]); if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, dirh.inode_number + dire->inode_number, squashfs_filetype_table[dire->type]) < 0) { TRACE("Filldir returned less than 0\n"); goto finish; } file->f_pos = length; } } finish: kfree(dire); return 0; failed_read: ERROR("Unable to read directory block [%llx:%x]\n", next_block, next_offset); kfree(dire); return 0; } static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, struct nameidata *nd) { const unsigned char *name = dentry->d_name.name; int len = dentry->d_name.len; struct inode *inode = NULL; struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; long long next_block = SQUASHFS_I(i)->start_block + sblk->directory_table_start; int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; struct squashfs_dir_header dirh; struct squashfs_dir_entry *dire; TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); dire = kmalloc(sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); if (dire == NULL) { ERROR("Failed to allocate squashfs_dir_entry\n"); goto exit_lookup; } if (len > SQUASHFS_NAME_LEN) goto exit_lookup; length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, SQUASHFS_I(i)->u.s2.directory_index_start, SQUASHFS_I(i)->u.s2.directory_index_offset, SQUASHFS_I(i)->u.s2.directory_index_count, name, len); while (length < i_size_read(i)) { /* read directory header */ if (msblk->swap) { struct squashfs_dir_header sdirh; if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, next_offset, sizeof(sdirh), &next_block, &next_offset)) goto failed_read; length += sizeof(sdirh); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else { if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, next_offset, sizeof(dirh), &next_block, &next_offset)) goto failed_read; length += sizeof(dirh); } dir_count = dirh.count + 1; while (dir_count--) { if (msblk->swap) { struct squashfs_dir_entry sdire; if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, next_offset, sizeof(sdire), &next_block, &next_offset)) goto failed_read; length += sizeof(sdire); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else { if (!squashfs_get_cached_block(i->i_sb, dire, next_block, next_offset, sizeof(*dire), &next_block, &next_offset)) goto failed_read; length += sizeof(*dire); } if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, next_offset, dire->size + 1, &next_block, &next_offset)) goto failed_read; length += dire->size + 1; if (name[0] < dire->name[0]) goto exit_lookup; if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset); TRACE("calling squashfs_iget for directory entry %s, inode" " %x:%x, %d\n", name, dirh.start_block, dire->offset, dirh.inode_number + dire->inode_number); inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); goto exit_lookup; } } } exit_lookup: kfree(dire); if (inode) return d_splice_alias(inode, dentry); d_add(dentry, inode); return ERR_PTR(0); failed_read: ERROR("Unable to read directory block [%llx:%x]\n", next_block, next_offset); goto exit_lookup; } static int squashfs_remount(struct super_block *s, int *flags, char *data) { *flags |= MS_RDONLY; return 0; } static void squashfs_put_super(struct super_block *s) { int i; if (s->s_fs_info) { struct squashfs_sb_info *sbi = s->s_fs_info; if (sbi->block_cache) for (i = 0; i < squashfs_cached_blks; i++) if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) vfree(sbi->block_cache[i].data); if (sbi->fragment) for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) vfree(sbi->fragment[i].data); kfree(sbi->fragment); kfree(sbi->block_cache); vfree(sbi->read_page); kfree(sbi->uid); kfree(sbi->fragment_index); kfree(sbi->fragment_index_2); kfree(sbi->meta_index); kfree(s->s_fs_info); s->s_fs_info = NULL; } } static int squashfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, mnt); } static void free_sqlzma(void) { int cpu; struct sqlzma *p; for_each_online_cpu(cpu) { p = per_cpu(sqlzma, cpu); if (p) { #ifdef KeepPreemptive mutex_destroy(&p->mtx); #endif sqlzma_fin(&p->un); kfree(p); } } } static int __init init_squashfs_fs(void) { struct sqlzma *p; int cpu; int err = init_inodecache(); if (err) goto out; for_each_online_cpu(cpu) { dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu)); err = -ENOMEM; p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL); if (p) { #ifdef KeepPreemptive mutex_init(&p->mtx); #endif err = sqlzma_init(&p->un, 1, 0); if (unlikely(err)) { ERROR("Failed to intialize uncompress workspace\n"); break; } per_cpu(sqlzma, cpu) = p; err = 0; } else break; } if (unlikely(err)) { free_sqlzma(); goto out; } printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " "Phillip Lougher\n" "squashfs: LZMA suppport for slax.org by jro\n"); err = register_filesystem(&squashfs_fs_type); if (err) { free_sqlzma(); destroy_inodecache(); } out: return err; } static void __exit exit_squashfs_fs(void) { unregister_filesystem(&squashfs_fs_type); free_sqlzma(); destroy_inodecache(); } static struct kmem_cache * squashfs_inode_cachep; static struct inode *squashfs_alloc_inode(struct super_block *sb) { struct squashfs_inode_info *ei; ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); return ei ? &ei->vfs_inode : NULL; } static void squashfs_destroy_inode(struct inode *inode) { kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); } static void init_once(struct kmem_cache *cachep, void *foo) { struct squashfs_inode_info *ei = foo; inode_init_once(&ei->vfs_inode); } static int __init init_inodecache(void) { squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", sizeof(struct squashfs_inode_info), 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); if (squashfs_inode_cachep == NULL) return -ENOMEM; return 0; } static void destroy_inodecache(void) { kmem_cache_destroy(squashfs_inode_cachep); } module_init(init_squashfs_fs); module_exit(exit_squashfs_fs); MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem, and LZMA suppport for slax.org"); MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>, and LZMA suppport for slax.org by jro"); MODULE_LICENSE("GPL"); ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/fs/squashfs/squashfs.h ================================================ /* * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs.h */ #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) #else #define TRACE(s, args...) {} #endif #define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) #define SERROR(s, args...) do { \ if (!silent) \ printk(KERN_ERR "SQUASHFS error: "s, ## args);\ } while(0) #define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) { return list_entry(inode, struct squashfs_inode_info, vfs_inode); } #if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) #define SQSH_EXTERN extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, long long index, unsigned int length, long long *next_index, int srclength); extern int squashfs_get_cached_block(struct super_block *s, void *buffer, long long block, unsigned int offset, int length, long long *next_block, unsigned int *next_offset); extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct squashfs_fragment_cache *fragment); extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, long long start_block, int length); extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); extern const struct address_space_operations squashfs_symlink_aops; extern const struct address_space_operations squashfs_aops; extern struct inode_operations squashfs_dir_inode_ops; #else #define SQSH_EXTERN static #endif #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); #else static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) { return 0; } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); #else static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) { return 0; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/fs/squashfs/squashfs2_0.c ================================================ /* * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs2_0.c */ #include <linux/squashfs_fs.h> #include <linux/module.h> #include <linux/zlib.h> #include <linux/fs.h> #include <linux/squashfs_fs_sb.h> #include <linux/squashfs_fs_i.h> #include "squashfs.h" static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, struct nameidata *); static struct file_operations squashfs_dir_ops_2 = { .read = generic_read_dir, .readdir = squashfs_readdir_2 }; static struct inode_operations squashfs_dir_inode_ops_2 = { .lookup = squashfs_lookup_2 }; static unsigned char squashfs_filetype_table[] = { DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK }; static int read_fragment_index_table_2(struct super_block *s) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 (sblk->fragments), GFP_KERNEL))) { ERROR("Failed to allocate uid/gid table\n"); return 0; } if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && !squashfs_read_data(s, (char *) msblk->fragment_index_2, sblk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2 (sblk->fragments) | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { ERROR("unable to read fragment index table\n"); return 0; } if (msblk->swap) { int i; unsigned int fragment; for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); i++) { SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), &msblk->fragment_index_2[i], 1); msblk->fragment_index_2[i] = fragment; } } return 1; } static int get_fragment_location_2(struct super_block *s, unsigned int fragment, long long *fragment_start_block, unsigned int *fragment_size) { struct squashfs_sb_info *msblk = s->s_fs_info; long long start_block = msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); struct squashfs_fragment_entry_2 fragment_entry; if (msblk->swap) { struct squashfs_fragment_entry_2 sfragment_entry; if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, start_block, offset, sizeof(sfragment_entry), &start_block, &offset)) goto out; SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); } else if (!squashfs_get_cached_block(s, (char *) &fragment_entry, start_block, offset, sizeof(fragment_entry), &start_block, &offset)) goto out; *fragment_start_block = fragment_entry.start_block; *fragment_size = fragment_entry.size; return 1; out: return 0; } static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) { struct squashfs_super_block *sblk = &msblk->sblk; i->i_ino = ino; i->i_mtime.tv_sec = sblk->mkfs_time; i->i_atime.tv_sec = sblk->mkfs_time; i->i_ctime.tv_sec = sblk->mkfs_time; i->i_uid = msblk->uid[inodeb->uid]; i->i_mode = inodeb->mode; i->i_nlink = 1; i->i_size = 0; if (inodeb->guid == SQUASHFS_GUIDS) i->i_gid = i->i_uid; else i->i_gid = msblk->guid[inodeb->guid]; } static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) { struct super_block *s = i->i_sb; struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; unsigned int block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; unsigned int offset = SQUASHFS_INODE_OFFSET(inode); unsigned int ino = SQUASHFS_MK_VFS_INODE(block - sblk->inode_table_start, offset); long long next_block; unsigned int next_offset; union squashfs_inode_header_2 id, sid; struct squashfs_base_inode_header_2 *inodeb = &id.base, *sinodeb = &sid.base; TRACE("Entered squashfs_read_inode_2\n"); if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodeb, block, offset, sizeof(*sinodeb), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, sizeof(*sinodeb)); } else if (!squashfs_get_cached_block(s, (char *) inodeb, block, offset, sizeof(*inodeb), &next_block, &next_offset)) goto failed_read; squashfs_new_inode(msblk, i, inodeb, ino); switch(inodeb->inode_type) { case SQUASHFS_FILE_TYPE: { struct squashfs_reg_inode_header_2 *inodep = &id.reg; struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; long long frag_blk; unsigned int frag_size = 0; if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); } else if (!squashfs_get_cached_block(s, (char *) inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; frag_blk = SQUASHFS_INVALID_BLK; if (inodep->fragment != SQUASHFS_INVALID_FRAG && !get_fragment_location_2(s, inodep->fragment, &frag_blk, &frag_size)) goto failed_read; i->i_size = inodep->file_size; i->i_fop = &generic_ro_fops; i->i_mode |= S_IFREG; i->i_mtime.tv_sec = inodep->mtime; i->i_atime.tv_sec = inodep->mtime; i->i_ctime.tv_sec = inodep->mtime; i->i_blocks = ((i->i_size - 1) >> 9) + 1; SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; SQUASHFS_I(i)->u.s1.fragment_size = frag_size; SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->u.s1.block_list_start = next_block; SQUASHFS_I(i)->offset = next_offset; i->i_data.a_ops = &squashfs_aops; TRACE("File inode %x:%x, start_block %x, " "block_list_start %llx, offset %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, next_block, next_offset); break; } case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header_2 *inodep = &id.dir; struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); } else if (!squashfs_get_cached_block(s, (char *) inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_size = inodep->file_size; i->i_op = &squashfs_dir_inode_ops_2; i->i_fop = &squashfs_dir_ops_2; i->i_mode |= S_IFDIR; i->i_mtime.tv_sec = inodep->mtime; i->i_atime.tv_sec = inodep->mtime; i->i_ctime.tv_sec = inodep->mtime; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->offset = inodep->offset; SQUASHFS_I(i)->u.s2.directory_index_count = 0; SQUASHFS_I(i)->u.s2.parent_inode = 0; TRACE("Directory inode %x:%x, start_block %x, offset " "%x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, inodep->offset); break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, sinodep); } else if (!squashfs_get_cached_block(s, (char *) inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_size = inodep->file_size; i->i_op = &squashfs_dir_inode_ops_2; i->i_fop = &squashfs_dir_ops_2; i->i_mode |= S_IFDIR; i->i_mtime.tv_sec = inodep->mtime; i->i_atime.tv_sec = inodep->mtime; i->i_ctime.tv_sec = inodep->mtime; SQUASHFS_I(i)->start_block = inodep->start_block; SQUASHFS_I(i)->offset = inodep->offset; SQUASHFS_I(i)->u.s2.directory_index_start = next_block; SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; SQUASHFS_I(i)->u.s2.parent_inode = 0; TRACE("Long directory inode %x:%x, start_block %x, " "offset %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->start_block, inodep->offset); break; } case SQUASHFS_SYMLINK_TYPE: { struct squashfs_symlink_inode_header_2 *inodep = &id.symlink; struct squashfs_symlink_inode_header_2 *sinodep = &sid.symlink; if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, sinodep); } else if (!squashfs_get_cached_block(s, (char *) inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_size = inodep->symlink_size; i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &squashfs_symlink_aops; i->i_mode |= S_IFLNK; SQUASHFS_I(i)->start_block = next_block; SQUASHFS_I(i)->offset = next_offset; TRACE("Symbolic link inode %x:%x, start_block %llx, " "offset %x\n", SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset); break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { struct squashfs_dev_inode_header_2 *inodep = &id.dev; struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; if (msblk->swap) { if (!squashfs_get_cached_block(s, (char *) sinodep, block, offset, sizeof(*sinodep), &next_block, &next_offset)) goto failed_read; SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); } else if (!squashfs_get_cached_block(s, (char *) inodep, block, offset, sizeof(*inodep), &next_block, &next_offset)) goto failed_read; i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK; init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK; init_special_inode(i, i->i_mode, 0); break; } default: ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb->inode_type); goto failed_read1; } return 1; failed_read: ERROR("Unable to read inode [%x:%x]\n", block, offset); failed_read1: return 0; } static int get_dir_index_using_offset(struct super_block *s, long long *next_block, unsigned int *next_offset, long long index_start, unsigned int index_offset, int i_count, long long f_pos) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; int i, length = 0; struct squashfs_dir_index_2 index; TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", i_count, (unsigned int) f_pos); if (f_pos == 0) goto finish; for (i = 0; i < i_count; i++) { if (msblk->swap) { struct squashfs_dir_index_2 sindex; squashfs_get_cached_block(s, (char *) &sindex, index_start, index_offset, sizeof(sindex), &index_start, &index_offset); SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); } else squashfs_get_cached_block(s, (char *) &index, index_start, index_offset, sizeof(index), &index_start, &index_offset); if (index.index > f_pos) break; squashfs_get_cached_block(s, NULL, index_start, index_offset, index.size + 1, &index_start, &index_offset); length = index.index; *next_block = index.start_block + sblk->directory_table_start; } *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; finish: return length; } static int get_dir_index_using_name(struct super_block *s, long long *next_block, unsigned int *next_offset, long long index_start, unsigned int index_offset, int i_count, const char *name, int size) { struct squashfs_sb_info *msblk = s->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; int i, length = 0; struct squashfs_dir_index_2 *index; char *str; TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { ERROR("Failed to allocate squashfs_dir_index\n"); goto failure; } index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); strncpy(str, name, size); str[size] = '\0'; for (i = 0; i < i_count; i++) { if (msblk->swap) { struct squashfs_dir_index_2 sindex; squashfs_get_cached_block(s, (char *) &sindex, index_start, index_offset, sizeof(sindex), &index_start, &index_offset); SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); } else squashfs_get_cached_block(s, (char *) index, index_start, index_offset, sizeof(struct squashfs_dir_index_2), &index_start, &index_offset); squashfs_get_cached_block(s, index->name, index_start, index_offset, index->size + 1, &index_start, &index_offset); index->name[index->size + 1] = '\0'; if (strcmp(index->name, str) > 0) break; length = index->index; *next_block = index->start_block + sblk->directory_table_start; } *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; kfree(str); failure: return length; } static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) { struct inode *i = file->f_dentry->d_inode; struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; long long next_block = SQUASHFS_I(i)->start_block + sblk->directory_table_start; int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; struct squashfs_dir_header_2 dirh; struct squashfs_dir_entry_2 *dire; TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { ERROR("Failed to allocate squashfs_dir_entry\n"); goto finish; } length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, SQUASHFS_I(i)->u.s2.directory_index_start, SQUASHFS_I(i)->u.s2.directory_index_offset, SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); while (length < i_size_read(i)) { /* read directory header */ if (msblk->swap) { struct squashfs_dir_header_2 sdirh; if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset, sizeof(sdirh), &next_block, &next_offset)) goto failed_read; length += sizeof(sdirh); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else { if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset, sizeof(dirh), &next_block, &next_offset)) goto failed_read; length += sizeof(dirh); } dir_count = dirh.count + 1; while (dir_count--) { if (msblk->swap) { struct squashfs_dir_entry_2 sdire; if (!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block, next_offset, sizeof(sdire), &next_block, &next_offset)) goto failed_read; length += sizeof(sdire); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else { if (!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block, next_offset, sizeof(*dire), &next_block, &next_offset)) goto failed_read; length += sizeof(*dire); } if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, next_offset, dire->size + 1, &next_block, &next_offset)) goto failed_read; length += dire->size + 1; if (file->f_pos >= length) continue; dire->name[dire->size + 1] = '\0'; TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent, dire->name, dire->size + 1, (int) file->f_pos, dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]); if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE( dirh.start_block, dire->offset), squashfs_filetype_table[dire->type]) < 0) { TRACE("Filldir returned less than 0\n"); goto finish; } file->f_pos = length; } } finish: kfree(dire); return 0; failed_read: ERROR("Unable to read directory block [%llx:%x]\n", next_block, next_offset); kfree(dire); return 0; } static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, struct nameidata *nd) { const unsigned char *name = dentry->d_name.name; int len = dentry->d_name.len; struct inode *inode = NULL; struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; struct squashfs_super_block *sblk = &msblk->sblk; long long next_block = SQUASHFS_I(i)->start_block + sblk->directory_table_start; int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; struct squashfs_dir_header_2 dirh; struct squashfs_dir_entry_2 *dire; int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { ERROR("Failed to allocate squashfs_dir_entry\n"); goto exit_loop; } if (len > SQUASHFS_NAME_LEN) goto exit_loop; length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, SQUASHFS_I(i)->u.s2.directory_index_start, SQUASHFS_I(i)->u.s2.directory_index_offset, SQUASHFS_I(i)->u.s2.directory_index_count, name, len); while (length < i_size_read(i)) { /* read directory header */ if (msblk->swap) { struct squashfs_dir_header_2 sdirh; if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset, sizeof(sdirh), &next_block, &next_offset)) goto failed_read; length += sizeof(sdirh); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else { if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset, sizeof(dirh), &next_block, &next_offset)) goto failed_read; length += sizeof(dirh); } dir_count = dirh.count + 1; while (dir_count--) { if (msblk->swap) { struct squashfs_dir_entry_2 sdire; if (!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block,next_offset, sizeof(sdire), &next_block, &next_offset)) goto failed_read; length += sizeof(sdire); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else { if (!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block,next_offset, sizeof(*dire), &next_block, &next_offset)) goto failed_read; length += sizeof(*dire); } if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, next_offset, dire->size + 1, &next_block, &next_offset)) goto failed_read; length += dire->size + 1; if (sorted && name[0] < dire->name[0]) goto exit_loop; if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset); unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, dire->offset); TRACE("calling squashfs_iget for directory " "entry %s, inode %x:%x, %lld\n", name, dirh.start_block, dire->offset, ino); inode = squashfs_iget(i->i_sb, ino, inode_number); goto exit_loop; } } } exit_loop: kfree(dire); d_add(dentry, inode); return ERR_PTR(0); failed_read: ERROR("Unable to read directory block [%llx:%x]\n", next_block, next_offset); goto exit_loop; } int squashfs_2_0_supported(struct squashfs_sb_info *msblk) { struct squashfs_super_block *sblk = &msblk->sblk; msblk->read_inode = squashfs_read_inode_2; msblk->read_fragment_index_table = read_fragment_index_table_2; sblk->bytes_used = sblk->bytes_used_2; sblk->uid_start = sblk->uid_start_2; sblk->guid_start = sblk->guid_start_2; sblk->inode_table_start = sblk->inode_table_start_2; sblk->directory_table_start = sblk->directory_table_start_2; sblk->fragment_table_start = sblk->fragment_table_start_2; return 1; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/include/linux/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; signed int inode_number:16; /* very important signedness */ char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/include/linux/squashfs_fs_i.h ================================================ #ifndef SQUASHFS_FS_I #define SQUASHFS_FS_I /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs_i.h */ struct squashfs_inode_info { long long start_block; unsigned int offset; union { struct { long long fragment_start_block; unsigned int fragment_size; unsigned int fragment_offset; long long block_list_start; } s1; struct { long long directory_index_start; unsigned int directory_index_offset; unsigned int directory_index_count; unsigned int parent_inode; } s2; } u; struct inode vfs_inode; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/ksquashfs/include/linux/squashfs_fs_sb.h ================================================ #ifndef SQUASHFS_FS_SB #define SQUASHFS_FS_SB /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs_sb.h */ #include <linux/squashfs_fs.h> struct squashfs_cache { long long block; int length; long long next_index; char *data; }; struct squashfs_fragment_cache { long long block; int length; unsigned int locked; char *data; }; struct squashfs_sb_info { struct squashfs_super_block sblk; int devblksize; int devblksize_log2; int swap; struct squashfs_cache *block_cache; struct squashfs_fragment_cache *fragment; int next_cache; int next_fragment; int next_meta_index; unsigned int *uid; unsigned int *guid; long long *fragment_index; unsigned int *fragment_index_2; char *read_page; /* struct mutex read_data_mutex; */ struct mutex read_page_mutex; struct mutex block_cache_mutex; struct mutex fragment_mutex; struct mutex meta_index_mutex; wait_queue_head_t waitq; wait_queue_head_t fragment_wait_queue; struct meta_index *meta_index; /* z_stream stream; */ long long *inode_lookup_table; int unused_cache_blks; int unused_frag_blks; int (*read_inode)(struct inode *i, squashfs_inode_t \ inode); long long (*read_blocklist)(struct inode *inode, int \ index, int readahead_blks, char *block_list, \ unsigned short **block_p, unsigned int *bsize); int (*read_fragment_index_table)(struct super_block *s); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.48 ---------------------- 7z ANSI-C Decoder 4.48 Copyright (C) 1999-2006 Igor Pavlov 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- Read lzma.txt for information about license. Files --------------------- 7zAlloc.* - Allocate and Free 7zBuffer.* - Buffer structure 7zCrc.* - CRC32 code 7zDecode.* - Low level memory->memory decoding 7zExtract.* - High level stream->memory decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application 7zMethodID.* - MethodID structure 7zTypes.h - Base types and constants How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- .7z Decoder can be compiled in one of two modes: 1) Default mode. In that mode 7z Decoder will read full compressed block to RAM before decompressing. 2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read compressed block by parts. And you can specify desired buffer size. So memory requirements can be reduced. But decompressing speed will be 5-10% lower and code size is slightly larger. Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ISzInStream interface */ CArchiveDatabaseEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call InitCrcTable(); function to initialize CRC structures. 3) call SzArDbExInit(&db); function to initialize db structures. 4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined) - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for compressed solid block (if _LZMA_IN_CB is not defined) - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. EXIT codes ----------- 7z Decoder functions can return one of the following codes: #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) LZMA Defines ------------ _LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements _SZ_FILE_SIZE_32 - define it if you need only support for files smaller than 4 GB _SZ_NO_INT_64 - define it if your compiler doesn't support long long int or __int64. _LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs. _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/7zCrcT8.c ================================================ /* 7zCrcT8.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 #define CRC_NUM_TABLES 8 UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; void MY_FAST_CALL CrcGenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } #if CRC_NUM_TABLES > 1 for (; i < 256 * CRC_NUM_TABLES; i++) { UInt32 r = g_CrcTable[i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } #endif } UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { return CrcUpdateT8(v, data, size, g_CrcTable); } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Alloc.c ================================================ /* Alloc.c */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return malloc(size); } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Alloc.h ================================================ /* Alloc.h */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include <stddef.h> #include "../../Types.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c */ #include <memory.h> #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/Lzma/LzmaDecode.h" #include "../../Compress/Branch/BranchX86.h" #include "../../Compress/Branch/BranchX86_2.h" #endif #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; CFileSize Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; size_t curSize = (1 << 20); if (curSize > cb->Size) curSize = (size_t)cb->Size; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize); *size = (SizeT)processedSize; if (processedSize > curSize) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR; } #ifdef _LZMA_IN_CB SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuffer; size_t processedSize, curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)(inSize); RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize)); if (processedSize == 0) return SZE_DATA_ERROR; if (processedSize > curSize) return SZE_FAIL; memcpy(outBuffer, inBuffer, processedSize); outBuffer += processedSize; inSize -= processedSize; } return SZ_OK; } #endif #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SZ_RESULT CheckSupportedFolder(const CFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZE_NOTIMPL; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZE_NOTIMPL; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZE_NOTIMPL; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZE_NOTIMPL; return SZ_OK; } return SZE_NOTIMPL; } CFileSize GetSum(const CFileSize *values, UInt32 index) { CFileSize sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; size_t tempSizes[3] = { 0, 0, 0}; size_t tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; CFileSize offset; CFileSize inSize; Byte *outBufCur = outBuffer; size_t outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; CFileSize unpackSize = folder->UnPackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (size_t)unpackSize; if (outSizeCur != unpackSize) return SZE_OUTOFMEMORY; temp = (Byte *)allocMain->Alloc(outSizeCur); if (temp == 0 && outSizeCur != 0) return SZE_OUTOFMEMORY; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) return SZE_OUTOFMEMORY; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (size_t)unpackSize; } else return SZE_NOTIMPL; } offset = GetSum(packSizes, si); inSize = packSizes[si]; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); #endif if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); #else memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize); #endif } else { SZ_RESULT res = SzDecodeLzma(coder, inSize, #ifdef _LZMA_IN_CB inStream, #else inBuffer + (size_t)offset, #endif outBufCur, outSizeCur, allocMain); RINOK(res) } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZE_NOTIMPL; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { CFileSize offset = GetSum(packSizes, 1); CFileSize s3Size = packSizes[1]; SZ_RESULT res; if (ci != 3) return SZE_NOTIMPL; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); tempSizes[2] = (size_t)s3Size; if (tempSizes[2] != s3Size) return SZE_OUTOFMEMORY; tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZE_OUTOFMEMORY; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) #endif res = x86_2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], #ifdef _LZMA_IN_CB tempBuf[2], tempSizes[2], #else inBuffer + (size_t)offset, (size_t)s3Size, #endif outBuffer, outSize); RINOK(res) } else return SZE_NOTIMPL; } return SZ_OK; } SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SZ_RESULT res = SzDecode2(packSizes, folder, #ifdef _LZMA_IN_CB inStream, startPos, #else inBuffer, #endif outBuffer, outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) allocMain->Free(tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "../../7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder); size_t unPackSize = (size_t)unPackSizeSpec; CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0); #ifndef _LZMA_IN_CB Byte *inBuffer = 0; size_t processedSize; CFileSize packSizeSpec; size_t packSize; RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec)); packSize = (size_t)packSizeSpec; if (packSize != packSizeSpec) return SZE_OUTOFMEMORY; #endif if (unPackSize != unPackSizeSpec) return SZE_OUTOFMEMORY; *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, startOffset)); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc(packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, packSize, &processedSize); if (res == SZ_OK && processedSize != packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc(unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, startOffset, #else inBuffer, #endif *outBuffer, unPackSize, allocTemp); if (res == SZ_OK) { if (folder->UnPackCRCDefined) { if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC) res = SZE_CRC_ERROR; } } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZE_CRC_ERROR; } } } return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zDecode.h" #include "../../7zCrc.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { CFileSize t = size + db->Database.PackSizes[packStreamIndex + i]; if (t < size) return SZE_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { void *inBufferSpec; size_t processedSize; const Byte *inBuffer; RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize)); inBuffer = (const Byte *)inBufferSpec; if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt64)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, allocFunc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); MY_ALLOC(UInt32, *digests, numItems, allocFunc); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZE_NOTIMPL; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, allocFunc); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } case k7zIdLastWriteTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp->Alloc)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->IsLastWriteTimeDefined = defined; f->LastWriteTime.Low = f->LastWriteTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->LastWriteTime.Low)); RINOK(SzReadUInt32(sd, &f->LastWriteTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); allocTemp->Free(lwtVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, dataStartPos, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, allocTemp); RINOK(res) if (folder->UnPackCRCDefined) if (CrcCalc(outBuffer->Items, (size_t)unPackSize) != folder->UnPackCRC) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc = 0; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc)); crc = CRC_INIT_VAL; RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc)); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc)); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc)); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CRC_GET_DIGEST(crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { res = SZE_ARCHIVE_ERROR; if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC) { for (;;) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->IsLastWriteTimeDefined = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); typedef struct _CArchiveFileTime { UInt32 Low; UInt32 High; } CArchiveFileTime; typedef struct _CFileItem { CArchiveFileTime LastWriteTime; /* CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; Byte IsLastWriteTimeDefined; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _WIN32 #define USE_WINDOWS_FUNCTIONS #endif #ifdef USE_WINDOWS_FUNCTIONS #include <windows.h> #endif #include "7zIn.h" #include "7zExtract.h" #include "../../7zCrc.h" #ifdef USE_WINDOWS_FUNCTIONS typedef HANDLE MY_FILE_HANDLE; #else typedef FILE *MY_FILE_HANDLE; #endif void ConvertNumberToString(CFileSize value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) void ConvertFileTimeToString(CArchiveFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } #ifdef USE_WINDOWS_FUNCTIONS /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). */ #define kChunkSizeMax (1 << 24) #endif size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res || processedLoc == 0) break; } while (size > 0); return processedSize; } #else return fread(data, 1, size, file); #endif } size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res) break; } while (size > 0); return processedSize; } #else return fwrite(data, 1, size, file); #endif } int MyCloseFile(MY_FILE_HANDLE file) { #ifdef USE_WINDOWS_FUNCTIONS return (CloseHandle(file) != FALSE) ? 0 : 1; #else return fclose(file); #endif } typedef struct _CFileInStream { ISzInStream InStream; MY_FILE_HANDLE File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = MyReadFile(s->File, buffer, size); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; #ifdef USE_WINDOWS_FUNCTIONS { LARGE_INTEGER value; value.LowPart = (DWORD)pos; value.HighPart = (LONG)((UInt64)pos >> 32); #ifdef _SZ_FILE_SIZE_32 /* VC 6.0 has bug with >> 32 shifts. */ value.HighPart = 0; #endif value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN); if (value.LowPart == 0xFFFFFFFF) if(GetLastError() != NO_ERROR) return SZE_FAIL; return SZ_OK; } #else int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; #endif } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (archiveStream.File == INVALID_HANDLE_VALUE) #else archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) #endif { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->IsLastWriteTimeDefined) ConvertFileTimeToString(&f->LastWriteTime, t); else strcpy(t, " "); printf("%10s %s %s\n", s, t, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { MY_FILE_HANDLE outputHandle; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (outputHandle == INVALID_HANDLE_VALUE) #else fopen(fileName, "wb+"); if (outputHandle == 0) #endif { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (MyCloseFile(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); MyCloseFile(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == (SZ_RESULT)SZE_NOTIMPL) PrintError("decoder doesn't support this archive"); else if (res == (SZ_RESULT)SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else if (res == (SZ_RESULT)SZE_CRC_ERROR) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" /* int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { return (*a1 == *a2) ? 1 : 0; } */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Types.h" typedef UInt64 CMethodID; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/makefile ================================================ PROG = 7zDec.exe !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4 !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** C_OBJS = \ $O\7zCrc.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ $O\BranchX86.obj \ $O\BranchX86_2.obj \ $(C_OBJS) \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c $(COMPL_O2) $O\BranchX86.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c BranchX86.o: ../../Compress/Branch/BranchX86.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchARM.c ================================================ /* BranchARM.c */ #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchARM.h ================================================ /* BranchARM.h */ #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "BranchTypes.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchARMThumb.c ================================================ /* BranchARMThumb.c */ #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchARMThumb.h ================================================ /* BranchARMThumb.h */ #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "BranchTypes.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchIA64.c ================================================ /* BranchIA64.c */ #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 /* && (instNorm & 0x3F)== 0 */ ) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchIA64.h ================================================ /* BranchIA64.h */ #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "BranchTypes.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchPPC.c ================================================ /* BranchPPC.c */ #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */ if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 /* || (data[i+3] & 3) == 3 */ ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchPPC.h ================================================ /* BranchPPC.h */ #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "BranchTypes.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchSPARC.c ================================================ /* BranchSPARC.c */ #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchSPARC.h ================================================ /* BranchSPARC.h */ #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "BranchTypes.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchTypes.h ================================================ /* BranchTypes.h */ #ifndef __BRANCHTYPES_H #define __BRANCHTYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want <stddef.h> */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include <stddef.h> typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *prevMaskMix & 0x7; if (endPos < 5) return 0; nowPos += 5; prevPosT = (SizeT)0 - 1; for(;;) { Byte *p = buffer + bufferPos; Byte *limit = buffer + endPos - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - buffer); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (nowPos + (UInt32)bufferPos) + src; else dest = src - (nowPos + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #include "BranchTypes.h" #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchX86_2.c ================================================ // BranchX86_2.c #include "BranchX86_2.h" #include "../../Alloc.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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; }} #define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; } #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 #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 UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits)); // #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits)); int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *Buffer, *BufferLim; UInt32 Range, Code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; RC_INIT(buf3, size3); if (outSize == 0) return BCJ2_RESULT_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IfBit0(prob) { UpdateBit0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UpdateBit1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return BCJ2_RESULT_DATA_ERROR; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return BCJ2_RESULT_DATA_ERROR; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Branch/BranchX86_2.h ================================================ // BranchX86_2.h #ifndef __BRANCHX86_2_H #define __BRANCHX86_2_H #include "BranchTypes.h" #define BCJ2_RESULT_OK 0 #define BCJ2_RESULT_DATA_ERROR 1 /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). */ int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Huffman/HuffmanEncode.c ================================================ /* Compress/HuffmanEncode.c */ #include "HuffmanEncode.h" #include "../../Sort.h" #define kMaxLen 16 #define NUM_BITS 10 #define MASK ((1 << NUM_BITS) - 1) #define NUM_COUNTERS 64 /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */ #define HUFFMAN_SPEED_OPT void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) { UInt32 num = 0; /* if (maxLen > 10) maxLen = 10; */ { UInt32 i; #ifdef HUFFMAN_SPEED_OPT UInt32 counters[NUM_COUNTERS]; for (i = 0; i < NUM_COUNTERS; i++) counters[i] = 0; for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; } for (i = 1; i < NUM_COUNTERS; i++) { UInt32 temp = counters[i]; counters[i] = num; num += temp; } for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); } counters[0] = 0; HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); #else for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[num++] = i | (freq << NUM_BITS); } HeapSort(p, num); #endif } if (num < 2) { int minCode = 0; int maxCode = 1; if (num == 1) { maxCode = p[0] & MASK; if (maxCode == 0) maxCode++; } p[minCode] = 0; p[maxCode] = 1; lens[minCode] = lens[maxCode] = 1; return; } { UInt32 b, e, i; i = b = e = 0; do { UInt32 n, m, freq; n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq = (p[n] & ~MASK); p[n] = (p[n] & MASK) | (e << NUM_BITS); m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq += (p[m] & ~MASK); p[m] = (p[m] & MASK) | (e << NUM_BITS); p[e] = (p[e] & MASK) | freq; e++; } while (num - e > 1); { UInt32 lenCounters[kMaxLen + 1]; for (i = 0; i <= kMaxLen; i++) lenCounters[i] = 0; p[--e] &= MASK; lenCounters[1] = 2; while (e > 0) { UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; p[e] = (p[e] & MASK) | (len << NUM_BITS); if (len >= maxLen) for (len = maxLen - 1; lenCounters[len] == 0; len--); lenCounters[len]--; lenCounters[len + 1] += 2; } { UInt32 len; i = 0; for (len = maxLen; len != 0; len--) { UInt32 num; for (num = lenCounters[len]; num != 0; num--) lens[p[i++] & MASK] = (Byte)len; } } { UInt32 nextCodes[kMaxLen + 1]; { UInt32 code = 0; UInt32 len; for (len = 1; len <= kMaxLen; len++) nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; } /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ { UInt32 i; for (i = 0; i < numSymbols; i++) p[i] = nextCodes[lens[i]]++; } } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Huffman/HuffmanEncode.h ================================================ /* Compress/HuffmanEncode.h */ #ifndef __COMPRESS_HUFFMANENCODE_H #define __COMPRESS_HUFFMANENCODE_H #include "../../Types.h" /* Conditions: num <= 1024 = 2 ^ NUM_BITS Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) maxLen <= 16 = kMaxLen Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) */ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lz/LzHash.h ================================================ /* LzHash.h */ #ifndef __C_LZHASH_H #define __C_LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \ hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lz/MatchFinder.c ================================================ /* MatchFinder.c */ /* Please call InitCrcTable before */ #include <string.h> #include "MatchFinder.h" #include "LzHash.h" #include "../../7zCrc.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); UInt32 numReadBytes; UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, size, &numReadBytes); if (p->result != SZ_OK) return; if (numReadBytes == 0) { p->streamEndWasReached = 1; return; } p->streamPos += numReadBytes; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, p->streamPos - p->pos + p->keepSizeBefore); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } void MatchFinder_Construct(CMatchFinder *p) { p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); } void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for(i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while(++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lz/MatchFinder.h ================================================ /* MatchFinder.h */ #ifndef __MATCHFINDER_H #define __MATCHFINDER_H #include "../../IStream.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; HRes result; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lz/MatchFinderMt.c ================================================ /* MatchFinderMt.c */ #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif #include "../../7zCrc.h" #include "LzHash.h" #include "MatchFinderMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { HRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads(name, v) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \ for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask) DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #if _MSC_VER >= 1300 #define NO_INLINE __declspec(noinline) __fastcall #else #ifdef _MSC_VER #define NO_INLINE __fastcall #endif #endif Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned StdCall BtThreadFunc2(void *p) { #ifdef USE_ALLOCA alloca(0x180); #endif BtThreadFunc((CMatchFinderMt *)p); return 0; } HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return E_INVALIDARG; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZE_OUTOFMEMORY; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZE_OUTOFMEMORY; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lz/MatchFinderMt.h ================================================ /* MatchFinderMt.h */ #ifndef __MATCHFINDERMT_H #define __MATCHFINDERMT_H #include "../../Threads.h" #include "MatchFinder.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaDecode.c ================================================ /* LzmaDecode.c LZMA Decoder (optimized for Speed version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #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; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaDecode.h ================================================ /* LzmaDecode.h LZMA Decoder interface LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 #include "LzmaTypes.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 */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #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 ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; for (;;) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H #include "LzmaTypes.h" /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/LzmaTypes.h ================================================ /* LzmaTypes.h Types for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.40 (2006-05-01) */ #ifndef __LZMATYPES_H #define __LZMATYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want <stddef.h> */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include <stddef.h> typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/kmod/Makefile ================================================ # Copyright (C) 2006-2008 Junjiro Okajima # Copyright (C) 2006-2008 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: Makefile,v 1.3 2008-03-12 01:49:39 jro Exp $ # # the environment variables are not inherited since 2.6.23 # ifdef SQLZMA_EXTRA_CFLAGS # EXTRA_CFLAGS += ${SQLZMA_EXTRA_CFLAGS} # endif obj-m += unlzma.o sqlzma.o unlzma-y := module.o sqlzma-y := uncomp.o ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/kmod/module.c ================================================ /* * Copyright (C) 2006-2007 Junjiro Okajima * Copyright (C) 2006-2007 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: module.c,v 1.1 2007-11-05 05:43:36 jro Exp $ */ #include <linux/init.h> #include <linux/module.h> #include "../LzmaDecode.c" EXPORT_SYMBOL(LzmaDecodeProperties); EXPORT_SYMBOL(LzmaDecode); #if 0 static int __init unlzma_init(void) { return 0; } static void __exit unlzma_exit(void) { } module_init(unlzma_init); module_exit(unlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_VERSION("$Id: module.c,v 1.1 2007-11-05 05:43:36 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress. " "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/kmod.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: kmod.mk,v 1.1 2007-11-05 05:43:35 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif ifndef KDir $(error KDir is not defined) endif #include makefile.gcc Kmod = kmod EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} # -D_LZMA_PROB32 EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) all: ${Kmod}/uncomp.c ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ -C ${KDir} C=0 V=0 modules ${Kmod}/uncomp.c: uncomp.c ln $< $@ clean: clean_kmod clean_kmod: ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean ${RM} ${Kmod}/*~ -@test -e ${Kmod}/uncomp.c && \ diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif #include makefile.gcc CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 ifdef KDir include kmod.mk endif ifdef UseDebugFlags DebugFlags = -O0 -g -UNDEBUG endif CFLAGS += -DNDEBUG ${DebugFlags} Tgt = libunlzma.a libunlzma_r.a all: ${Tgt} %_r.c: %.c ln $< $@ # -pthread %_r.o: CFLAGS += -D_REENTRANT -include pthread.h uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h libunlzma.a: uncomp.o LzmaDecode.o ${AR} cr $@ $^ libunlzma_r.a: uncomp_r.o LzmaDecode_r.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o LzmaDecode.o *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/testflags.c ================================================ #ifdef _LZMA_PROB32 -D_LZMA_PROB32 #else -U_LZMA_PROB32 #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Compress/Lzma/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> #include <pthread.h> #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/vmalloc.h> #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (unlikely(err)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima <sfjro at users dot sf dot net>"); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/CpuArch.h ================================================ /* CpuArch.h */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/IStream.h ================================================ /* IStream.h */ #ifndef __C_ISTREAM_H #define __C_ISTREAM_H #include "Types.h" typedef struct _ISeqInStream { HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize); } ISeqInStream; typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Sort.c ================================================ /* Sort.c */ #include "Sort.h" #define HeapSortDown(p, k, size, temp) \ { for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && p[s + 1] > p[s]) s++; \ if (temp >= p[s]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSort(UInt32 *p, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; UInt32 k = i; HeapSortDown(p, k, size, temp) } while(--i != 0); } /* do { UInt32 k = 1; UInt32 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) } while (size > 1); */ while (size > 3) { UInt32 temp = p[size]; UInt32 k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) } { UInt32 temp = p[size]; p[size] = p[1]; if (size > 2 && p[2] < temp) { p[1] = p[2]; p[2] = temp; } else p[1] = temp; } } /* #define HeapSortRefDown(p, vals, n, size, temp) \ { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ if (val >= vals[p[s]]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; HeapSortRefDown(p, vals, i, size, temp); } while(--i != 0); } do { UInt32 temp = p[size]; p[size--] = p[1]; HeapSortRefDown(p, vals, 1, size, temp); } while (size > 1); } */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Sort.h ================================================ /* Sort.h */ #ifndef __7Z_Sort_H #define __7Z_Sort_H #include "Types.h" void HeapSort(UInt32 *p, UInt32 size); /* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Threads.c ================================================ /* Threads.c */ #include "Threads.h" #include <process.h> HRes GetError() { DWORD res = GetLastError(); return (res) ? (HRes)(res) : SZE_FAIL; } HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); } HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); } HRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return SZ_OK; } HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return BoolToHRes(thread->handle != 0); } HRes WaitObject(HANDLE h) { return (HRes)WaitForSingleObject(h, INFINITE); } HRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } HRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } HRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return BoolToHRes(p->handle != 0); } HRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); } HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); } HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return BoolToHRes(p->handle != 0); } HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } HRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } HRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; } return SZ_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Threads.h ================================================ /* Threads.h */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include <windows.h> #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE StdCall #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); HRes Thread_Wait(CThread *thread); HRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) HRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); HRes Event_Set(CEvent *event); HRes Event_Reset(CEvent *event); HRes Event_Wait(CEvent *event); HRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); HRes Semaphore_Release1(CSemaphore *p); HRes Semaphore_Wait(CSemaphore *p); HRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; HRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/C/Types.h ================================================ /* 7zTypes.h */ #ifndef __C_TYPES_H #define __C_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED #ifdef _LZMA_INT32_IS_ULONG typedef long Int32; #else typedef int Int32; #endif #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _SZ_FILE_SIZE_32 */ /* You can define _SZ_FILE_SIZE_32, if you don't need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_32 typedef UInt32 CFileSize; #else typedef UInt64 CFileSize; #endif #endif #define SZ_RESULT int typedef int HRes; #define RES_OK (0) #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_CRC_ERROR (3) #define SZE_ARCHIVE_ERROR (6) #define SZE_OUTOFMEMORY (0x8007000EL) #define SZE_NOTIMPL (0x80004001L) #define SZE_FAIL (0x80004005L) #define SZE_INVALIDARG (0x80070057L) #ifndef RINOK #define RINOK(x) { HRes __result_ = (x); if(__result_ != 0) return __result_; } #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #define StdCall __stdcall #else #define StdCall #endif #if _MSC_VER >= 1300 #define MY_FAST_CALL __declspec(noinline) __fastcall #elif defined( _MSC_VER) #define MY_FAST_CALL __fastcall #else #define MY_FAST_CALL #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "7zDecode.h" #include "../../IPassword.h" #include "../../Common/LockedStream.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unPackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &properties = coderInfo.Properties; size_t size = properties.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); CByteBuffer buffer; UString unicodePassword(password); const UInt32 sizeInBytes = unicodePassword.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < unicodePassword.Length(); i++) { wchar_t c = unicodePassword[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword( (const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unPackSizesPointers; packSizesPointers.Reserve(numInStreams); unPackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unPackStreamIndex++) unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unPackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Properties.SetCapacity(size); memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnPackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnPackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnPackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnPacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _database.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &database = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &database = _database; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = database.Folders[folderIndex]; UInt64 unPackSize = folderInfo.GetUnPackSize(); importantTotalUnPacked += unPackSize; extractFolderInfoVector.Back().UnPackSize = unPackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = database.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize; // Count partial_folder_size // efi.UnPackSize += unPackSize; // importantTotalUnPacked += unPackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnPacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnPacked = 0; UInt64 totalFolderUnPacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnPacked += totalFolderUnPacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnPacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnPacked = efi.UnPackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; #else const CArchiveDatabaseEx &database = _database; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = database.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&database, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = database.Folders[folderIndex]; totalFolderPacked = _database.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &database.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; UInt64 fileSize = fileInfo.UnPackSize; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fileInfo.IsFileCRCDefined && _checkCrc) digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zProperties.h" #include "../../../Common/IntToString.h" #include "../../../Common/ComTry.h" #include "../../../Windows/Defs.h" #include "../Common/ItemNameUtils.h" #ifdef _7Z_VOL #include "../Common/MultiStream.h" #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = #ifdef _7Z_VOL _refs.Size(); #else *numItems = _database.Files.Size(); #endif return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _database.Folders.Size(); i++) { const CFolder &f = _database.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _database.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop) { if (timeDefined) prop = unixTime; } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; #ifndef _SFX static inline UInt32 GetUInt32FromMemLE(const Byte *p) { return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); } #endif bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ #ifdef _7Z_VOL const CRef &ref = _refs[index]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &_database = volume.Database; UInt32 index2 = ref.ItemIndex; const CFileItem &item = _database.Files[index2]; #else const CFileItem &item = _database.Files[index]; UInt32 index2 = index; #endif switch(propID) { case kpidPath: { if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; } case kpidIsFolder: prop = item.IsDirectory; break; case kpidSize: { prop = item.UnPackSize; // prop = ref2.UnPackSize; break; } case kpidPosition: { /* if (ref2.Refs.Size() > 1) prop = ref2.StartPos; else */ if (item.IsStartPosDefined) prop = item.StartPos; break; } case kpidPackedSize: { // prop = ref2.PackSize; { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _database.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidLastAccessTime: MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop); break; case kpidCreationTime: MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop); break; case kpidLastWriteTime: MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop); break; case kpidAttributes: if (item.AreAttributesDefined) prop = item.Attributes; break; case kpidCRC: if (item.IsFileCRCDefined) prop = item.FileCRC; break; case kpidEncrypted: { prop = IsEncrypted(index2); break; } #ifndef _SFX case kpidMethod: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Properties.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Properties.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Properties; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Properties.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Properties; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Properties.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Properties.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Properties[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif case kpidIsAnti: prop = item.IsAnti; break; } prop.Detach(value); return S_OK; COM_TRY_END } #ifdef _7Z_VOL static const wchar_t *kExt = L"7z"; static const wchar_t *kAfterPart = L".7z"; class CVolumeName { bool _first; UString _unchangedPart; UString _changedPart; UString _afterPart; public: bool InitName(const UString &name) { _first = true; int dotPos = name.ReverseFind('.'); UString basePart = name; if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (ext.CompareNoCase(kExt)==0 || ext.CompareNoCase(L"EXE") == 0) { _afterPart = kAfterPart; basePart = name.Left(dotPos); } } int numLetters = 1; bool splitStyle = false; if (basePart.Right(numLetters) == L"1") { while (numLetters < basePart.Length()) { if (basePart[basePart.Length() - numLetters - 1] != '0') break; numLetters++; } } else return false; _unchangedPart = basePart.Left(basePart.Length() - numLetters); _changedPart = basePart.Right(numLetters); return true; } UString GetNextName() { UString newName; // if (_newStyle || !_first) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = UString(c) + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } _changedPart = newName; } _first = false; return _unchangedPart + _changedPart + _afterPart; } }; #endif STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifdef _7Z_VOL CVolumeName seqName; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; #endif #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif #ifdef _7Z_VOL if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); } for (;;) { CMyComPtr<IInStream> inStream; if (!_volumes.IsEmpty()) { if (!openVolumeCallback) break; if(_volumes.Size() == 1) { UString baseName; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; baseName = prop.bstrVal; } seqName.InitName(baseName); } UString fullName = seqName.GetNextName(); HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; } else inStream = stream; CInArchive archive; RINOK(archive.Open(inStream, maxCheckStartPosition)); _volumes.Add(CVolume()); CVolume &volume = _volumes.Back(); CArchiveDatabaseEx &database = volume.Database; volume.Stream = inStream; volume.StartRef2Index = _refs.Size(); HRESULT result = archive.ReadDatabase(database #ifndef _NO_CRYPTO , getTextPassword #endif ); if (result != S_OK) { _volumes.Clear(); return result; } database.Fill(); for(int i = 0; i < database.Files.Size(); i++) { CRef refNew; refNew.VolumeIndex = _volumes.Size() - 1; refNew.ItemIndex = i; _refs.Add(refNew); /* const CFileItem &file = database.Files[i]; int j; */ /* for (j = _refs.Size() - 1; j >= 0; j--) { CRef2 &ref2 = _refs[j]; const CRef &ref = ref2.Refs.Back(); const CVolume &volume2 = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database2 = volume2.Database; const CFileItem &file2 = database2.Files[ref.ItemIndex]; if (file2.Name.CompareNoCase(file.Name) == 0) { if (!file.IsStartPosDefined) continue; if (file.StartPos != ref2.StartPos + ref2.UnPackSize) continue; ref2.Refs.Add(refNew); break; } } */ /* j = -1; if (j < 0) { CRef2 ref2New; ref2New.Refs.Add(refNew); j = _refs.Add(ref2New); } CRef2 &ref2 = _refs[j]; ref2.UnPackSize += file.UnPackSize; ref2.PackSize += database.GetFilePackSize(i); if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) ref2.StartPos = file.StartPos; */ } if (database.Files.Size() != 1) break; const CFileItem &file = database.Files.Front(); if (!file.IsStartPosDefined) break; } #else CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _database #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); _database.Fill(); _inStream = stream; #endif } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN #ifdef _7Z_VOL _volumes.Clear(); _refs.Clear(); #else _inStream.Release(); _database.Clear(); #endif return S_OK; COM_TRY_END } #ifdef _7Z_VOL STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; UInt64 pos = 0; const UString *fileName; for (int i = 0; i < _refs.Size(); i++) { const CRef &ref = _refs[i]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; const CFileItem &file = database.Files[ref.ItemIndex]; if (i == 0) fileName = &file.Name; else if (fileName->Compare(file.Name) != 0) return S_FALSE; if (!file.IsStartPosDefined) return S_FALSE; if (file.StartPos != pos) return S_FALSE; CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; if (folderIndex == kNumNoIndex) { if (file.UnPackSize != 0) return E_FAIL; continue; } if (database.NumUnPackStreamsVector[folderIndex] != 1) return S_FALSE; const CFolder &folder = database.Folders[folderIndex]; if (folder.Coders.Size() != 1) return S_FALSE; const CCoderInfo &coder = folder.Coders.Front(); if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) return S_FALSE; if (coder.MethodID != k_Copy) return S_FALSE; pos += file.UnPackSize; CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = volume.Stream; subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); subStreamInfo.Size = file.UnPackSize; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifdef _7Z_VOL struct CRef { int VolumeIndex; int ItemIndex; }; struct CVolume { int StartRef2Index; CMyComPtr<IInStream> Stream; CArchiveDatabaseEx Database; }; #endif #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef _7Z_VOL public IInArchiveGetStream, #endif #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef _7Z_VOL MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) #endif #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef _7Z_VOL STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); #endif #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: #ifdef _7Z_VOL CObjectVector<CVolume> _volumes; CObjectVector<CRef> _refs; #else CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _database; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = UInt32(kNumFastBytesForHeaders); oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = UInt32(kDictionaryForHeaders); oneMethodInfo.Properties.Add(property); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Properties = oneMethodInfo.Properties; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Properties.Size(); j++) { const CProp &prop = methodFull.Properties[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(index, propID, &propVariant)); if (propVariant.vt == VT_FILETIME) { filetime = propVariant.filetime; filetimeIsDefined = true; } else if (propVariant.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *database = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); database = &volume->Database; } #else if (_inStream != 0) database = &_database; #endif // CRecordVector<bool> compressStatuses; CObjectVector<CUpdateItem> updateItems; // CRecordVector<UInt32> copyIndices; // CMyComPtr<IUpdateCallback2> updateCallback2; // updateCallback->QueryInterface(&updateCallback2); for(UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem updateItem; updateItem.NewProperties = IntToBool(newProperties); updateItem.NewData = IntToBool(newData); updateItem.IndexInArchive = indexInArchive; updateItem.IndexInClient = i; updateItem.IsAnti = false; updateItem.Size = 0; if (updateItem.IndexInArchive != -1) { const CFileItem &fileItem = database->Files[updateItem.IndexInArchive]; updateItem.Name = fileItem.Name; updateItem.IsDirectory = fileItem.IsDirectory; updateItem.Size = fileItem.UnPackSize; updateItem.IsAnti = fileItem.IsAnti; updateItem.CreationTime = fileItem.CreationTime; updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined; updateItem.LastWriteTime = fileItem.LastWriteTime; updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined; updateItem.LastAccessTime = fileItem.LastAccessTime; updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined; } if (updateItem.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.AttributesAreDefined = false; else if (propVariant.vt != VT_UI4) return E_INVALIDARG; else { updateItem.Attributes = propVariant.ulVal; updateItem.AttributesAreDefined = true; } } RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined)); { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant)); if (propVariant.vt == VT_EMPTY) nameIsDefined = false; else if (propVariant.vt != VT_BSTR) return E_INVALIDARG; else { updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant)); if (propVariant.vt == VT_EMPTY) folderStatusIsDefined = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else { updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.IsAnti = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE); } if (updateItem.IsAnti) { updateItem.AttributesAreDefined = false; updateItem.IsCreationTimeDefined = false; updateItem.IsLastWriteTimeDefined = false; updateItem.IsLastAccessTimeDefined = false; updateItem.Size = 0; } if (!folderStatusIsDefined && updateItem.AttributesAreDefined) updateItem.SetDirectoryStatusFromAttributes(); } if (updateItem.NewData) { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant)); if (propVariant.vt != VT_UI8) return E_INVALIDARG; updateItem.Size = (UInt64)propVariant.uhVal.QuadPart; if (updateItem.Size != 0 && updateItem.IsAnti) return E_INVALIDARG; } updateItems.Add(updateItem); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it if (methodMode.PasswordIsDefined) { compressMainHeader = true; if(_encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || (methodMode.PasswordIsDefined && _encryptHeaders)) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteModified = WriteModified; options.HeaderOptions.WriteCreated = WriteCreated; options.HeaderOptions.WriteAccessed = WriteAccessed; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; return Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? database: 0, #else _inStream, database, #endif updateItems, outStream, updateCallback, options); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnPackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnPackSize, kNumUnPackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCreationTime, kLastAccessTime, kLastWriteTime, kWinAttributes, kComment, kEncodedHeader, kStartPos }; } }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" #include "7zIn.h" #include "7zDecode.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" extern "C" { #include "../../../../C/7zCrc.h" } // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define SZ_LITTLE_ENDIAN_UNALIGN #endif #ifdef SZ_LITTLE_ENDIAN_UNALIGN static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; } static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; } static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; } #else static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); } static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); } static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); } #endif Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = GetUInt32FromMem(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = GetUInt64FromMem(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)GetUInt16FromMem(buf); p[i] = 0; s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { UInt32 processedSize; RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize)); if (processedSize != kHeaderSize) return S_FALSE; if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; UInt32 numReadBytes = kBufferSize - numPrevBytes; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); UInt32 numBytesInBuffer = numPrevBytes + processedSize; if (numBytesInBuffer < kHeaderSize) break; UInt32 numTests = numBytesInBuffer - kHeaderSize + 1; for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) { if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } numPrevBytes = numBytesInBuffer - numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propertiesSize = ReadNum(); coder.Properties.SetCapacity((size_t)propertiesSize); ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs; numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bindPair; bindPair.InIndex = ReadNum(); bindPair.OutIndex = ReadNum(); folder.BindPairs.Add(bindPair); } CNum numPackedStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackedStreams); if (numPackedStreams == 1) { for (CNum j = 0; j < numInStreams; j++) if (folder.FindBindPairForInStream(j) < 0) { folder.PackStreams.Add(j); break; } } else for(i = 0; i < numPackedStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for(int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { packCRCsDefined.Reserve(numPackStreams); packCRCsDefined.Clear(); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for(CNum i = 0; i < numPackStreams; i++) { packCRCsDefined.Add(false); packCRCs.Add(0); } } } void CInArchive::ReadUnPackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for(CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnPackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnPackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnPackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CRecordVector<bool> crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for(i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnPackCRCDefined = crcsDefined[i]; folder.UnPackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { numUnPackStreamsInFolders.Clear(); numUnPackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnPackStream) { for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnPackStreamsInFolders.IsEmpty()) for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(1); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unPackSizes.Add(size); sum += size; } unPackSizes.Add(folders[i].GetUnPackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for(i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnPackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnPackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { digestsDefined.Clear(); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) { digestsDefined.Add(false); digests.Add(0); } } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnPackInfo: { ReadUnPackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for(int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt32 type) { CBoolVector boolVector; ReadBoolVector2(files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; fileTime.dwLowDateTime = 0; fileTime.dwHighDateTime = 0; bool defined = boolVector[i]; if (defined) { fileTime.dwLowDateTime = ReadUInt32(); fileTime.dwHighDateTime = ReadUInt32(); } switch(type) { case NID::kCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case NID::kLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case NID::kLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { CRecordVector<UInt64> packSizes; CRecordVector<bool> packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnPackStreamsInFolders; CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for(int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unPackSize64 = folder.GetUnPackSize(); size_t unPackSize = (size_t)unPackSize64; if (unPackSize != unPackSize64) ThrowUnsupported(); data.SetCapacity(unPackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unPackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnPackCRCDefined) if (CrcCalc(data, unPackSize) != folder.UnPackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) dataStartPos += packSizes[packIndex++]; } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(database.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, database.ArchiveInfo.DataStartPosition, database.PackSizes, database.PackCRCsDefined, database.PackCRCs, database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests); database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for(int i = 0; i < database.Folders.Size(); i++) { database.NumUnPackStreamsVector.Add(1); CFolder &folder = database.Folders[i]; unPackSizes.Add(folder.GetUnPackSize()); digestsDefined.Add(folder.UnPackCRCDefined); digests.Add(folder.UnPackCRC); } } database.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); database.Files.Reserve(numFiles); CNum i; for(i = 0; i < numFiles; i++) database.Files.Add(CFileItem()); database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!database.PackSizes.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; emptyStreamVector.Reserve((int)numFiles); for(i = 0; i < numFiles; i++) emptyStreamVector.Add(false); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < database.Files.Size(); i++) _inByteBack->ReadString(database.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.AreAttributesDefined = boolVector[i]; if (file.AreAttributesDefined) file.Attributes = ReadUInt32(); } break; } case NID::kStartPos: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.IsStartPosDefined = boolVector[i]; if (file.IsStartPosDefined) file.StartPos = ReadUInt64(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; emptyFileVector.Reserve(numEmptyStreams); antiFileVector.Reserve(numEmptyStreams); for (i = 0; i < numEmptyStreams; i++) { emptyFileVector.Add(false); antiFileVector.Add(false); } break; } case NID::kEmptyFile: { ReadBoolVector(numEmptyStreams, emptyFileVector); break; } case NID::kAnti: { ReadBoolVector(numEmptyStreams, antiFileVector); break; } case NID::kCreationTime: case NID::kLastWriteTime: case NID::kLastAccessTime: { ReadTime(dataVector, database.Files, (UInt32)type); break; } default: isKnownType = false; } if (isKnownType) database.ArchiveInfo.FileInfoPopIDs.Add(type); else SkeepData(size); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.HasStream = !emptyStreamVector[i]; if(file.HasStream) { file.IsDirectory = false; file.IsAnti = false; file.UnPackSize = unPackSizes[sizeIndex]; file.FileCRC = digests[sizeIndex]; file.IsFileCRCDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDirectory = !emptyFileVector[emptyFileIndex]; file.IsAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.UnPackSize = 0; file.IsFileCRCDefined = false; } } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for(int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for(int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnPackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnPackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { database.Clear(); database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; database.ArchiveInfo.Version.Major = _header[6]; database.ArchiveInfo.Version.Minor = _header[7]; if (database.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = GetUInt32FromMem(_header + 8); UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC); UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14); UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); UInt32 realProcessedSize; RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize)); int i; for (i = (int)realProcessedSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = realProcessedSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); UInt32 realProcessedSize; RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize)); if (realProcessedSize != (UInt32)nextHeaderSize) return S_FALSE; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; for (;;) { UInt64 type = ReadID(); if (type == NID::kHeader) break; if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); } return ReadHeader( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../IPassword.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; size_t _pos; public: void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnPackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadTime(const CObjectVector<CByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt32 type); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Properties; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnPackSizes; UInt32 UnPackCRC; bool UnPackCRCDefined; CFolder(): UnPackCRCDefined(false) {} UInt64 GetUnPackSize() const // test it { if (UnPackSizes.IsEmpty()) return 0; for (int i = UnPackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnPackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } }; typedef FILETIME CArchiveFileTime; class CFileItem { public: CArchiveFileTime CreationTime; CArchiveFileTime LastWriteTime; CArchiveFileTime LastAccessTime; UInt64 UnPackSize; UInt64 StartPos; UInt32 Attributes; UInt32 FileCRC; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDirectory; bool IsAnti; bool IsFileCRCDefined; bool AreAttributesDefined; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsStartPosDefined; /* const bool HasStream() const { return !IsDirectory && !IsAnti && UnPackSize != 0; } */ CFileItem(): HasStream(true), IsDirectory(false), IsAnti(false), IsFileCRCDefined(false), AreAttributesDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false), IsStartPosDefined(false) {} void SetAttributes(UInt32 attributes) { AreAttributesDefined = true; Attributes = attributes; } void SetCreationTime(const CArchiveFileTime &creationTime) { IsCreationTimeDefined = true; CreationTime = creationTime; } void SetLastWriteTime(const CArchiveFileTime &lastWriteTime) { IsLastWriteTimeDefined = true; LastWriteTime = lastWriteTime; } void SetLastAccessTime(const CArchiveFileTime &lastAccessTime) { IsLastAccessTimeDefined = true; LastAccessTime = lastAccessTime; } }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnPackStreamsVector; CObjectVector<CFileItem> Files; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnPackStreamsVector.Clear(); Files.Clear(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnPackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool IsSolid() const { for (int i = 0; i < NumUnPackStreamsVector.Size(); i++) if (NumUnPackStreamsVector[i] > 1) return true; return false; } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if(processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 value) { for (int i = 0; i < 4; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } UInt32 CrcUpdateUInt64(UInt32 crc, UInt64 value) { for (int i = 0; i < 8; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } HRESULT COutArchive::WriteDirectUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteDirectUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteSignature() { RINOK(WriteDirect(kSignature, kSignatureSize)); RINOK(WriteDirectByte(kMajorVersion)); return WriteDirectByte(2); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { UInt32 crc = CRC_INIT_VAL; crc = CrcUpdateUInt64(crc, h.NextHeaderOffset); crc = CrcUpdateUInt64(crc, h.NextHeaderSize); crc = CrcUpdateUInt32(crc, h.NextHeaderCRC); RINOK(WriteDirectUInt32(CRC_GET_DIGEST(crc))); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); return WriteDirectUInt32(h.NextHeaderCRC); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } HRESULT COutArchive::WriteBytes(const void *data, size_t size) { if (_mainMode) { if (_dynamicMode) _dynamicBuffer.Write(data, size); else _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else { if (_countMode) _countSize += size; else RINOK(_outByte2.Write(data, size)); } return S_OK; } HRESULT COutArchive::WriteBytes(const CByteBuffer &data) { return WriteBytes(data, data.GetCapacity()); } HRESULT COutArchive::WriteByte(Byte b) { return WriteBytes(&b, 1); } HRESULT COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } RINOK(WriteByte(firstByte)); for (;i > 0; i--) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } #ifdef _7Z_VOL static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 0; i < 8; i++) if (value < ((UInt64(1) << ( 7 * (i + 1))))) break; return 1 + i; } UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif HRESULT COutArchive::WriteFolder(const CFolder &folder) { RINOK(WriteNumber(folder.Coders.Size())); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propertiesSize = coder.Properties.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propertiesSize != 0) ? 0x20 : 0 ); RINOK(WriteByte(b)); RINOK(WriteBytes(longID, idSize)); if (isComplex) { RINOK(WriteNumber(coder.NumInStreams)); RINOK(WriteNumber(coder.NumOutStreams)); } if (propertiesSize == 0) continue; RINOK(WriteNumber(propertiesSize)); RINOK(WriteBytes(coder.Properties, propertiesSize)); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; RINOK(WriteNumber(bindPair.InIndex)); RINOK(WriteNumber(bindPair.OutIndex)); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { RINOK(WriteNumber(folder.PackStreams[i])); } return S_OK; } HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for(int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { RINOK(WriteByte(b)); mask = 0x80; b = 0; } } if (mask != 0x80) { RINOK(WriteByte(b)); } return S_OK; } HRESULT COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for(i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return S_OK; RINOK(WriteByte(NID::kCRC)); if (numDefined == digestsDefined.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(digestsDefined)); } for(i = 0; i < digests.Size(); i++) { if(digestsDefined[i]) RINOK(WriteUInt32(digests[i])); } return S_OK; } HRESULT COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kPackInfo)); RINOK(WriteNumber(dataOffset)); RINOK(WriteNumber(packSizes.Size())); RINOK(WriteByte(NID::kSize)); for(int i = 0; i < packSizes.Size(); i++) RINOK(WriteNumber(packSizes[i])); RINOK(WriteHashDigests(packCRCsDefined, packCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteUnPackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kUnPackInfo)); RINOK(WriteByte(NID::kFolder)); RINOK(WriteNumber(folders.Size())); { RINOK(WriteByte(0)); for(int i = 0; i < folders.Size(); i++) RINOK(WriteFolder(folders[i])); } RINOK(WriteByte(NID::kCodersUnPackSize)); int i; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnPackSizes.Size(); j++) RINOK(WriteNumber(folder.UnPackSizes[j])); } CRecordVector<bool> unPackCRCsDefined; CRecordVector<UInt32> unPackCRCs; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unPackCRCsDefined.Add(folder.UnPackCRCDefined); unPackCRCs.Add(folder.UnPackCRC); } RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { RINOK(WriteByte(NID::kSubStreamsInfo)); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { if (numUnPackStreamsInFolders[i] != 1) { RINOK(WriteByte(NID::kNumUnPackStream)); for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) RINOK(WriteNumber(numUnPackStreamsInFolders[i])); break; } } bool needFlag = true; CNum index = 0; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++) { if (j + 1 != numUnPackStreamsInFolders[i]) { if (needFlag) RINOK(WriteByte(NID::kSize)); needFlag = false; RINOK(WriteNumber(unPackSizes[index])); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnPackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnPackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } RINOK(WriteHashDigests(digestsDefined2, digests2)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteTime( const CObjectVector<CFileItem> &files, Byte type) { ///////////////////////////////////////////////// // CreationTime CBoolVector boolVector; boolVector.Reserve(files.Size()); bool thereAreDefined = false; bool allDefined = true; int i; for(i = 0; i < files.Size(); i++) { const CFileItem &item = files[i]; bool defined; switch(type) { case NID::kCreationTime: defined = item.IsCreationTimeDefined; break; case NID::kLastWriteTime: defined = item.IsLastWriteTimeDefined; break; case NID::kLastAccessTime: defined = item.IsLastAccessTimeDefined; break; default: throw 1; } boolVector.Add(defined); thereAreDefined = (thereAreDefined || defined); allDefined = (allDefined && defined); } if (!thereAreDefined) return S_OK; RINOK(WriteByte(type)); size_t dataSize = 1 + 1; dataSize += files.Size() * 8; if (allDefined) { RINOK(WriteNumber(dataSize)); WriteByte(1); } else { RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize)); WriteByte(0); RINOK(WriteBoolVector(boolVector)); } RINOK(WriteByte(0)); for(i = 0; i < files.Size(); i++) { if (boolVector[i]) { const CFileItem &item = files[i]; CArchiveFileTime timeValue; timeValue.dwLowDateTime = 0; timeValue.dwHighDateTime = 0; switch(type) { case NID::kCreationTime: timeValue = item.CreationTime; break; case NID::kLastWriteTime: timeValue = item.LastWriteTime; break; case NID::kLastAccessTime: timeValue = item.LastAccessTime; break; } RINOK(WriteUInt32(timeValue.dwLowDateTime)); RINOK(WriteUInt32(timeValue.dwHighDateTime)); } } return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnPackCRCDefined = true; folderItem.UnPackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } static void WriteUInt32ToBuffer(Byte *data, UInt32 value) { for (int i = 0; i < 4; i++) { *data++ = (Byte)value; value >>= 8; } } static void WriteUInt64ToBuffer(Byte *data, UInt64 value) { for (int i = 0; i < 8; i++) { *data++ = (Byte)value; value >>= 8; } } HRESULT COutArchive::WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; ///////////////////////////////// // Names CNum numDefinedNames = 0; size_t namesDataSize = 0; for(i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; if (!name.IsEmpty()) numDefinedNames++; namesDataSize += (name.Length() + 1) * 2; } CByteBuffer namesData; if (numDefinedNames > 0) { namesData.SetCapacity((size_t)namesDataSize); size_t pos = 0; for(int i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; for (int t = 0; t < name.Length(); t++) { wchar_t c = name[t]; namesData[pos++] = Byte(c); namesData[pos++] = Byte(c >> 8); } namesData[pos++] = 0; namesData[pos++] = 0; } } ///////////////////////////////// // Write Attributes CBoolVector attributesBoolVector; attributesBoolVector.Reserve(database.Files.Size()); int numDefinedAttributes = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].AreAttributesDefined; attributesBoolVector.Add(defined); if (defined) numDefinedAttributes++; } CByteBuffer attributesData; if (numDefinedAttributes > 0) { attributesData.SetCapacity(numDefinedAttributes * 4); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.AreAttributesDefined) { WriteUInt32ToBuffer(attributesData + pos, file.Attributes); pos += 4; } } } ///////////////////////////////// // Write StartPos CBoolVector startsBoolVector; startsBoolVector.Reserve(database.Files.Size()); int numDefinedStarts = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].IsStartPosDefined; startsBoolVector.Add(defined); if (defined) numDefinedStarts++; } CByteBuffer startsData; if (numDefinedStarts > 0) { startsData.SetCapacity(numDefinedStarts * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsStartPosDefined) { WriteUInt64ToBuffer(startsData + pos, file.StartPos); pos += 8; } } } ///////////////////////////////// // Write Last Write Time // /* CNum numDefinedLastWriteTimes = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].IsLastWriteTimeDefined) numDefinedLastWriteTimes++; if (numDefinedLastWriteTimes > 0) { CByteBuffer lastWriteTimeData; lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsLastWriteTimeDefined) { WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime); pos += 4; WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime); pos += 4; } } } // */ UInt64 packedSize = 0; for(i = 0; i < database.PackSizes.Size(); i++) packedSize += database.PackSizes[i]; headerOffset = packedSize; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; RINOK(WriteByte(NID::kHeader)); // Archive Properties if (database.Folders.Size() > 0) { RINOK(WriteByte(NID::kMainStreamsInfo)); RINOK(WritePackInfo(0, database.PackSizes, database.PackCRCsDefined, database.PackCRCs)); RINOK(WriteUnPackInfo(database.Folders)); CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) continue; unPackSizes.Add(file.UnPackSize); digestsDefined.Add(file.IsFileCRCDefined); digests.Add(file.FileCRC); } RINOK(WriteSubStreamsInfo( database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests)); RINOK(WriteByte(NID::kEnd)); } if (database.Files.IsEmpty()) { RINOK(WriteByte(NID::kEnd)); return _outByte.Flush(); } RINOK(WriteByte(NID::kFilesInfo)); RINOK(WriteNumber(database.Files.Size())); CBoolVector emptyStreamVector; emptyStreamVector.Reserve(database.Files.Size()); int numEmptyStreams = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { RINOK(WriteByte(NID::kEmptyStream)); RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyStreamVector)); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDirectory); if (!file.IsDirectory) numEmptyFiles++; antiVector.Add(file.IsAnti); if (file.IsAnti) numAntiItems++; } } if (numEmptyFiles > 0) { RINOK(WriteByte(NID::kEmptyFile)); RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyFileVector)); } if (numAntiItems > 0) { RINOK(WriteByte(NID::kAnti)); RINOK(WriteNumber((antiVector.Size() + 7) / 8)); RINOK(WriteBoolVector(antiVector)); } } if (numDefinedNames > 0) { ///////////////////////////////////////////////// RINOK(WriteByte(NID::kName)); { RINOK(WriteNumber(1 + namesData.GetCapacity())); RINOK(WriteByte(0)); RINOK(WriteBytes(namesData)); } } if (headerOptions.WriteCreated) { RINOK(WriteTime(database.Files, NID::kCreationTime)); } if (headerOptions.WriteModified) { RINOK(WriteTime(database.Files, NID::kLastWriteTime)); } if (headerOptions.WriteAccessed) { RINOK(WriteTime(database.Files, NID::kLastAccessTime)); } if (numDefinedAttributes > 0) { RINOK(WriteByte(NID::kWinAttributes)); size_t size = 2; if (numDefinedAttributes != database.Files.Size()) size += (attributesBoolVector.Size() + 7) / 8 + 1; size += attributesData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedAttributes == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(attributesBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(attributesData)); } } if (numDefinedStarts > 0) { RINOK(WriteByte(NID::kStartPos)); size_t size = 2; if (numDefinedStarts != database.Files.Size()) size += (startsBoolVector.Size() + 7) / 8 + 1; size += startsData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedStarts == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(startsBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(startsData)); } } RINOK(WriteByte(NID::kEnd)); // for files RINOK(WriteByte(NID::kEnd)); // for headers return _outByte.Flush(); } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (database.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { _dynamicBuffer.Init(); _dynamicMode = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) _dynamicMode = true; RINOK(WriteHeader(database, headerOptions, headerOffset)); if (_dynamicMode) { CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, _dynamicBuffer, _dynamicBuffer.GetSize(), packSizes, folders)); _dynamicMode = false; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; if (folders.Size() == 0) throw 1; RINOK(WriteID(NID::kEncodedHeader)); RINOK(WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>())); RINOK(WriteUnPackInfo(folders)); RINOK(WriteByte(NID::kEnd)); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; RINOK(_outByte.Flush()); } headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" #include "../../../Common/DynamicBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _pos = 0; _data = data; _size = size; } HRESULT Write(const void *data, size_t size) { if (_pos + size > _size) return E_FAIL; memmove(_data + _pos, data, size); _pos += size; return S_OK; } }; class CWriteDynamicBuffer { CByteDynamicBuffer _buffer; size_t _pos; public: CWriteDynamicBuffer(): _pos(0) {} void Init() { _pos = 0; } void Write(const void *data, size_t size) { if (_pos + size > _buffer.GetCapacity()) _buffer.EnsureCapacity(_pos + size); memmove(((Byte *)_buffer) +_pos, data, size); _pos += size; } operator Byte *() { return (Byte *)_buffer; }; operator const Byte *() const { return (const Byte *)_buffer; }; size_t GetSize() const { return _pos; } }; struct CHeaderOptions { // bool UseAdditionalHeaderStreams; bool CompressMainHeader; bool WriteModified; bool WriteCreated; bool WriteAccessed; CHeaderOptions(): // UseAdditionalHeaderStreams(false), CompressMainHeader(true), WriteModified(true), WriteCreated(false), WriteAccessed(false) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); } HRESULT WriteDirectUInt32(UInt32 value); HRESULT WriteDirectUInt64(UInt64 value); HRESULT WriteBytes(const void *data, size_t size); HRESULT WriteBytes(const CByteBuffer &data); HRESULT WriteByte(Byte b); HRESULT WriteUInt32(UInt32 value); HRESULT WriteNumber(UInt64 value); HRESULT WriteID(UInt64 value) { return WriteNumber(value); } HRESULT WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); HRESULT WriteBoolVector(const CBoolVector &boolVector); HRESULT WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); HRESULT WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); HRESULT WriteUnPackInfo(const CObjectVector<CFolder> &folders); HRESULT WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); /* HRESULT WriteStreamsInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs, bool externalFolders, UInt64 externalFoldersStreamIndex, const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); */ HRESULT WriteTime(const CObjectVector<CFileItem> &files, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _mainMode; bool _dynamicMode; bool _countMode; size_t _countSize; COutBuffer _outByte; CWriteBufferLoc _outByte2; CWriteDynamicBuffer _dynamicBuffer; UInt32 _crc; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME}, { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME}, { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, // { 97, NULL, kpidSolid, VT_BOOL}, #ifndef _SFX { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // UpdateMain.cpp #include "StdAfx.h" #include "7zUpdate.h" #include "7zFolderInStream.h" #include "7zEncode.h" #include "7zHandler.h" #include "7zOut.h" #include "../../Compress/Copy/CopyCoder.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h" #include "../Common/ItemNameUtils.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Properties, c2.Properties); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnPackStreamsVector[i1], db.NumUnPackStreamsVector[i2])); if (db.NumUnPackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { UInt32 Index; const CUpdateItem *UpdateItem; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType): Index(index), UpdateItem(&updateItem), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(updateItem.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = updateItem.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = updateItem.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = updateItem.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined) RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kMatchFinderForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = kDictionaryForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Properties.Add(property); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (!updateItem.NewData) continue; if (!updateItem.HasStream()) continue; if (useFilters) { const UString name = updateItem.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &updateItem, CFileItem &file) { file.Name = NItemName::MakeLegalName(updateItem.Name); if (updateItem.AttributesAreDefined) file.SetAttributes(updateItem.Attributes); if (updateItem.IsCreationTimeDefined) file.SetCreationTime(updateItem.CreationTime); if (updateItem.IsLastWriteTimeDefined) file.SetLastWriteTime(updateItem.LastWriteTime); if (updateItem.IsLastAccessTimeDefined) file.SetLastAccessTime(updateItem.LastAccessTime); file.UnPackSize = updateItem.Size; file.IsDirectory = updateItem.IsDirectory; file.IsAnti = updateItem.IsAnti; file.HasStream = updateItem.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = database != 0 ? database->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (database != 0) { fileIndexToUpdateIndexMap.Reserve(database->Files.Size()); for (int i = 0; i < database->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (database != 0) { for(i = 0; i < database->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnPackStreams = database->NumUnPackStreamsVector[i]; for (CNum fileIndex = database->FolderStartFileIndex[i]; indexInFolder < numUnPackStreams; fileIndex++) { if (database->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnPackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)database); } CArchiveDatabase newDatabase; //////////////////////////// COutArchive archive; RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += database->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { complexity += updateItem.Size; if (numSolidFiles == 1) { if (updateItem.Size > inSizeForReduce) inSizeForReduce = updateItem.Size; } else inSizeForReduce += updateItem.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = database->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, database->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = database->Folders[folderIndex]; CNum startIndex = database->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex]; newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); CNum indexInFolder = 0; for (CNum fi = database->FolderStartFileIndex[folderIndex]; indexInFolder < numUnPackStreams; fi++) { CFileItem file = database->Files[fi]; if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &updateItem = updateItems[updateIndex]; if (updateItem.NewProperties) { CFileItem file2; FromUpdateItemToFileItem(updateItem, file2); file2.UnPackSize = file.UnPackSize; file2.FileCRC = file.FileCRC; file2.IsFileCRCDefined = file.IsFileCRCDefined; file2.HasStream = file.HasStream; file = file2; } } newDatabase.Files.Add(file); } } } ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &updateItem = updateItems[index]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database.Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]]; totalSize += updateItem.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = updateItem.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnPackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnPackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &updateItem = updateItems[indices[i + subIndex]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.FileCRC = inStreamSpec->CRCs[subIndex]; file.UnPackSize = inStreamSpec->Sizes[subIndex]; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { file.IsFileCRCDefined = false; file.HasStream = false; } newDatabase.Files.Add(file); } // numUnPackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); i += numSubFiles; } } { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { if (updateItem.HasStream()) continue; } else if (updateItem.IndexInArchive != -1) if (database->Files[updateItem.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for(i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &updateItem = updateItems[emptyRefs[i]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; newDatabase.Files.Add(file); } } /* if (newDatabase.Files.Size() != updateItems.Size()) return E_FAIL; */ return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); } #ifdef _7Z_VOL static const UInt64 k_Copy = 0x0; static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options) { CCoderInfo coder; coder.NumInStreams = coder.NumOutStreams = 1; coder.MethodID = k_Copy; CFolder folder; folder.Coders.Add(coder); folder.PackStreams.Add(0); CNum numUnPackStreams = 0; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { throw 1; file.IsFileCRCDefined = false; file.HasStream = false; } folder.UnPackSizes.Add(file.UnPackSize); CArchiveDatabase newDatabase; newDatabase.Files.Add(file); newDatabase.Folders.Add(folder); newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); newDatabase.PackSizes.Add(file.UnPackSize); newDatabase.PackCRCsDefined.Add(false); newDatabase.PackCRCs.Add(file.FileCRC); return archive.WriteDatabase(newDatabase, options.HeaderMethod, false, false); } HRESULT UpdateVolume( IInStream *inStream, const CArchiveDatabaseEx *database, CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { if (updateItems.Size() != 1) return E_NOTIMPL; CMyComPtr<IArchiveUpdateCallback2> volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; CMyComPtr<ISequentialInStream> fileStream; HRESULT result = updateCallback->GetStream(0, &fileStream); if (result != S_OK && result != S_FALSE) return result; if (result == S_FALSE) return E_FAIL; CFileItem file; const CUpdateItem &updateItem = updateItems[0]; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; UInt64 complexity = 0; file.IsStartPosDefined = true; file.StartPos = 0; for (UInt64 volumeIndex = 0; true; volumeIndex++) { UInt64 volSize; RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize)); UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true); CMyComPtr<ISequentialOutStream> volumeStream; RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream)); COutArchive archive; RINOK(archive.Create(volumeStream, true)); RINOK(archive.SkeepPrefixArchiveHeader()); CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC; CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec; inCrcStreamSpec->Init(fileStream); RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity)); file.UnPackSize = inCrcStreamSpec->GetSize(); if (file.UnPackSize == 0) break; file.FileCRC = inCrcStreamSpec->GetCRC(); RINOK(WriteVolumeHeader(archive, file, options)); file.StartPos += file.UnPackSize; if (file.UnPackSize < pureSize) break; } return S_OK; } class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (!_volumeStream) { RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize)); RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream)); _volIndex++; _curPos = 0; RINOK(_archive.Create(_volumeStream, true)); RINOK(_archive.SkeepPrefixArchiveHeader()); _crc.Init(); continue; } UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length()); UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos); _crc.Update(data, curSize); UInt32 realProcessed; RINOK(_volumeStream->Write(data, curSize, &realProcessed)) data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _curPos += realProcessed; if (realProcessed != curSize && realProcessed == 0) return E_FAIL; if (_curPos == pureSize) { RINOK(Flush()); } } return S_OK; } #endif HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { #ifdef _7Z_VOL if (seqOutStream) #endif return Update2( EXTERNAL_CODECS_LOC_VARS inStream, database, updateItems, seqOutStream, updateCallback, options); #ifdef _7Z_VOL if (options.VolumeMode) return UpdateVolume(inStream, database, updateItems, seqOutStream, updateCallback, options); COutVolumeStream *volStreamSpec = new COutVolumeStream; CMyComPtr<ISequentialOutStream> volStream = volStreamSpec; CMyComPtr<IArchiveUpdateCallback2> volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; volStreamSpec->Init(volumeCallback, L"a.7z"); volStreamSpec->_options = options; RINOK(Update2(inStream, database, updateItems, volStream, updateCallback, options)); return volStreamSpec->Flush(); #endif } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { bool NewData; bool NewProperties; int IndexInArchive; int IndexInClient; UInt32 Attributes; FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt64 Size; UString Name; bool IsAnti; bool IsDirectory; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool AttributesAreDefined; bool HasStream() const { return !IsDirectory && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), AttributesAreDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false) {} void SetDirectoryStatusFromAttributes() { IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (UInt32 i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL) return result; } for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOutCommon.cpp #include "StdAfx.h" #include "HandlerOut.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ParseProperties.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Properties.Size(); j++) if (oneMethodInfo.Properties[j].Id == propID) return; CProp property; property.Id = propID; property.Value = value; oneMethodInfo.Properties.Add(property); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp property; if ( name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); if (name.CompareNoCase(L"D") == 0) property.Id = NCoderPropID::kDictionarySize; else property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { bool res; if (StringToBool(s, res)) { if (res) InitSolid(); else _numSolidFiles = 1; return S_OK; } UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: InitSolid(); return S_OK; case VT_BSTR: return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeaders = false; WriteModified = true; WriteCreated = false; WriteAccessed = false; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) return SetBoolProperty(_encryptHeaders, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteModified, value); if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCreated, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteAccessed, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp property; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); property.Id = NCoderPropID::kDictionarySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } } return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../Common/MethodProps.h" #include "../../Common/CreateCoder.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Properties; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeaders; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; DECL_EXTERNAL_CODECS_VARS }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUTSTREAMWITHCRC_H #define __OUTSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) PURE; // GetStream OUT: S_OK - OK, S_FALSE - skeep this file STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE; }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, // 1 - new data, 0 - old data Int32 *newProperties, // 1 - new properties, 0 - old properties UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter ) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE; }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.h # End Source File # End Group # Begin Group "Copy" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyRegister.cpp # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMARegister.cpp # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(C_OBJS) \ $(C_BRANCH_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BZIP2_OBJS) \ $(BZIP2_OPT_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(DEFLATE_OPT_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(PPMD_OPT_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return lastError; #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return File.SetTime(creationTime, lastAccessTime, lastWriteTime); } bool SetLastWriteTime(const FILETIME *lastWriteTime) { return File.SetLastWriteTime(lastWriteTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } UInt32 processedSize = 0; RINOK(WriteStream(outStream, _buffer, size, &processedSize)); if (size != processedSize) return E_FAIL; _nowPos64 += processedSize; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { UInt32 processedSize; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize)); UInt32 endPos = bufferPos + processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } UInt32 processedSize; RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize)); if (_bufferPos != processedSize) return E_FAIL; _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; UInt32 processedSizeTemp; UInt32 size0 = kBufferSize - _bufferPos; // Optimize it: RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp)); _bufferPos = _bufferPos + processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "MethodProps.h" #include "../../Common/MyCom.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProperties = method.Properties.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProperties != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties]; HRESULT res = S_OK; try { for (int i = 0; i < numProperties; i++) { const CProp &prop = method.Properties[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "MethodId.h" #include "../../Windows/PropVariant.h" #include "../../Common/MyVector.h" #include "../ICoder.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Properties; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { MoveMemory(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 numBytesToRead = (UInt32)(MyMin(_pos + size, _size) - _pos); memmove(data, _dataPointer + _pos, numBytesToRead); _pos += numBytesToRead; if(processedSize != NULL) *processedSize = numBytesToRead; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memmove(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 newSize = size; if (_pos + size > _size) newSize = (UInt32)(_size - _pos); memmove(_buffer + _pos, data, newSize); if(processedSize != NULL) *processedSize = newSize; _pos += newSize; if (newSize != size) return E_FAIL; return S_OK; } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } HRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); HRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARM.h" } UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARMThumb.h" } UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86_2.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "PPC.h" #include "IA64.h" #include "ARM.h" #include "ARMThumb.h" #include "SPARC.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC_B) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMThumb) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC_B, 0x02, 0x05, L"BC_PPC_B"), METHOD_ITEM(BC_IA64, 0x04, 1, L"BC_IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"BC_ARM"), METHOD_ITEM(BC_ARMThumb,0x07, 1, L"BC_ARMThumb"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"BC_SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" extern "C" { #include "../../../../C/Compress/Branch/BranchIA64.h" } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchPPC.h" } UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchSPARC.h" } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" extern "C" { #include "../../../../C/Alloc.h" } namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h ================================================ // ByteSwap.h #ifndef __BYTESWAP_H #define __BYTESWAP_H #include "../../ICoder.h" #include "Common/MyCom.h" // {23170F69-40C1-278B-0203-020000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap2, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); // {23170F69-40C1-278B-0203-040000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap4, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00); class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (UInt32 i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/Alloc.h" } #include "CopyCoder.h" #include "../../Common/StreamUtils.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Copy/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPYCODER_H #define __COMPRESS_COPYCODER_H #include "../../ICoder.h" #include "../../../Common/MyCom.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Copy/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/Copy/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS typedef COutBufferException CLZOutWindowException; #endif class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (distance >= _pos) { if (!_overDict || distance >= _bufferSize) return false; pos += _bufferSize; } if (_limitPos - _pos > len && _bufferSize - pos > len) { const Byte *src = _buffer + pos; Byte *dest = _buffer + _pos; _pos += len; do *dest++ = *src++; while(--len != 0); } else do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); for (;;) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" extern "C" { #include "../../../../C/Alloc.h" } #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include <stdio.h> #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // extern "C" { #include "../../../../C/7zCrc.h" } // #define SHOW_STAT namespace NCompress { namespace NLZMA { // struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit; const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = kNumLogBits * 2; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; #endif void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < kNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < kNumLowSymbols + kNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); } for (; i < numSymbols; i++) prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _matchFinderCycles(0), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { MatchFinder_Construct(&_matchFinderBase); // _maxMode = false; _fastMode = false; #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&_matchFinderMt); _matchFinderMt.MatchFinder = &_matchFinderBase; #endif } static void *SzAlloc(size_t size) { return BigAlloc(size); } static void SzFree(void *address) { BigFree(address); } ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::~CEncoder() { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc); #endif MatchFinder_Free(&_matchFinderBase, &g_Alloc); } static const UInt32 kBigHashDicLimit = (UInt32)1 << 24; HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; bool btMode = (_matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT _mtMode = (_multiThread && !_fastMode && btMode); #endif if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit); UInt32 numCycles = 16 + (_numFastBytes >> 1); if (!btMode) numCycles >>= 1; if (_matchFinderCycles != 0) numCycles = _matchFinderCycles; _matchFinderBase.cutValue = numCycles; #ifdef COMPRESS_MF_MT if (_mtMode) { RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)); _matchFinderObj = &_matchFinderMt; MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder); } else #endif { if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)) return E_OUTOFMEMORY; _matchFinderObj = &_matchFinderBase; MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder); } return S_OK; } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); /* int skipModeBitsLoc = 0; if (c == L'D') { skipModeBitsLoc = 2; c = GetUpperChar(*s++); } */ if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; // *skipModeBits = skipModeBitsLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kMatchFinderCycles: { if (prop.vt != VT_UI4) return E_INVALIDARG; _matchFinderCycles = prop.ulVal; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); // _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; } case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kNumThreads: { if (prop.vt != VT_UI4) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.ulVal > 1) ? True : False; if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } #ifdef SHOW_STAT static int ttt = 0; #endif void CEncoder::MovePos(UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { _additionalOffset += num; _matchFinder.Skip(_matchFinderObj, num); } } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; const Byte *data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = *data; Byte matchByte = *(data - (reps[0] + 1)); if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)-1; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while(--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > matchDistances[offs]) offs += 2; for(; ; len++) { UInt32 distance = matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); COptimal &optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + kNumRepDistances; optimum.Prev1IsChar = false; } if (len == matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; for (;;) { cur++; if(cur == lenEnd) { return Backward(backRes, cur); } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 newLen, numDistancePairs; newLen = ReadMatchDistances(numDistancePairs); if(newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; const Byte currentByte = *data; const Byte matchByte = *(data - (reps[0] + 1)); UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } /* if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) // speed optimization { // try Literal + rep0 const Byte *data2 = data - (reps[0] + 1); UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 lenTestTemp = lenTest; UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while(startLen > matchDistances[offs]) offs += 2; UInt32 curBack = matchDistances[offs + 1]; UInt32 posSlot = GetPosSlot2(curBack); for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice; UInt32 lenToPosState = GetLenToPosState(lenTest); if (curBack < kNumFullDistances) curAndLenPrice += _distancesPrices[lenToPosState][curBack]; else curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (/*_maxMode && */lenTest == matchDistances[offs]) { // Try Match + Literal + Rep0 const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (posStateNext + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; curBack = matchDistances[offs + 1]; if (curBack >= kNumFullDistances) posSlot = GetPosSlot2(curBack); } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { return ((bigDist >> 7) > smallDist); } UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs) { UInt32 lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2); if (ttt >= 61994) ttt = ttt; ttt++; for (UInt32 i = 0; i < numDistancePairs; i += 2) printf("%2d %6d | ", _matchDistances[i], _matchDistances[i + 1]); #endif if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) { UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1; const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; UInt32 distance = _matchDistances[numDistancePairs - 1] + 1; if (numAvail > kMatchMaxLen) numAvail = kMatchMaxLen; const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } _additionalOffset++; return lenRes; } UInt32 CEncoder::GetOptimumFast(UInt32 &backRes) { UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if(len >= _numFastBytes) { backRes = i; MovePos(len - 1); return len; } repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } UInt32 backMain = 0; // for GCC if (lenMain >= 2) { backMain = matchDistances[numDistancePairs - 1]; while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) { if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) break; numDistancePairs -= 2; lenMain = matchDistances[numDistancePairs - 2]; backMain = matchDistances[numDistancePairs - 1]; } if (lenMain == 2 && backMain >= 0x80) lenMain = 1; } if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2 && numAvailableBytes > 2) { numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); _longestMatchLength = ReadMatchDistances(_numDistancePairs); if (_longestMatchLength >= 2) { UInt32 newDistance = matchDistances[_numDistancePairs - 1]; if (_longestMatchLength >= lenMain && newDistance < backMain || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[1] != data2[1] || data[2] != data2[2]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if (len + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } backRes = backMain + kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = UInt32(-1); return 1; } HRESULT CEncoder::Flush(UInt32 nowPos) { // ReleaseMFStream(); if (_matchFinderBase.result != SZ_OK) return _matchFinderBase.result; WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { // _needReleaseMFStream = false; #ifdef COMPRESS_MF_MT #ifdef USE_ALLOCA alloca(0x300); #endif #endif CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); for (;;) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) break; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } return S_OK; } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; return S_OK; } static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize) { return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize); } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { _seqInStream.RealStream = _inStream; _seqInStream.SeqInStream.Read = MyRead; _matchFinderBase.stream = &_seqInStream.SeqInStream; _matchFinder.Init(_matchFinderObj); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return _matchFinderBase.result; _finished = true; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush((UInt32)nowPos64); UInt32 len, numDistancePairs; len = ReadMatchDistances(numDistancePairs); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } UInt32 nowPos32 = (UInt32)nowPos64; UInt32 progressPosValuePrev = nowPos32; if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); for (;;) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos, len; if (_fastMode) len = GetOptimumFast(pos); else len = GetOptimum(nowPos32, pos); UInt32 posState = nowPos32 & _posStateMask; if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); if(_state.IsCharState()) subCoder->Encode(&_rangeEncoder, curByte); else { Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); } else { UInt32 distance = _repDistances[pos]; _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); if (pos == 3) _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; } _repDistances[1] = _repDistances[0]; _repDistances[0] = distance; } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); _state.UpdateRep(); } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); _alignPriceCount++; } } _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; _repDistances[1] = _repDistances[0]; _repDistances[0] = pos; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos32 += len; if (_additionalOffset == 0) { if (!_fastMode) { if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= kAlignTableSize) FillAlignPrices(); } if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); if (nowPos32 - progressPosValuePrev >= (1 << 14)) { nowPos64 += nowPos32 - progressPosValuePrev; *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); _finished = false; *finished = 0; return _matchFinderBase.result; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillDistancesPrices() { UInt32 tempPrices[kNumFullDistances]; for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] = encoder.GetPrice(posSlot); for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); UInt32 *distancesPrices = _distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/Compress/Lz/MatchFinder.h" #ifdef COMPRESS_MF_MT #include "../../../../C/Compress/Lz/MatchFinderMt.h" #endif } #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; // #define LZMA_LOG_BRANCH #if _MSC_VER >= 1400 // Must give gain in core 2. but slower ~2% on k8. // #define LZMA_LOG_BSR #endif #ifndef LZMA_LOG_BSR static const int kNumLogBits = 13; // don't change it ! extern Byte g_FastPos[]; #endif inline UInt32 GetPosSlot(UInt32 pos) { #ifdef LZMA_LOG_BSR if (pos < 2) return pos; unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else if (pos < (1 << kNumLogBits)) return g_FastPos[pos]; if (pos < (1 << (kNumLogBits * 2 - 1))) return g_FastPos[pos >> (kNumLogBits - 1)] + (kNumLogBits - 1) * 2; return g_FastPos[pos >> (kNumLogBits - 1) * 2] + (kNumLogBits - 1) * 4; #endif } inline UInt32 GetPosSlot2(UInt32 pos) { #ifdef LZMA_LOG_BSR unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else #ifdef LZMA_LOG_BRANCH if (pos < (1 << (kNumLogBits + 6))) return g_FastPos[pos >> 6] + 12; if (pos < (1 << (kNumLogBits * 2 + 5))) return g_FastPos[pos >> (kNumLogBits + 5)] + (kNumLogBits + 5) * 2; return g_FastPos[pos >> (kNumLogBits * 2 + 4)] + (kNumLogBits * 2 + 4) * 2; #else // it's faster with VC6-32bit. UInt32 s = 6 + ((kNumLogBits - 1) & (UInt32)((Int32)(((1 << (kNumLogBits + 6)) - 1) - pos) >> 31)); return g_FastPos[pos >> s] + (s * 2); #endif #endif } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices[posState]); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) { CEncoder::Encode(rangeEncoder, symbol, posState); if (updatePrice) if (--_counters[posState] == 0) UpdateTable(posState); } }; } typedef struct _CSeqInStream { ISeqInStream SeqInStream; CMyComPtr<ISequentialInStream> RealStream; } CSeqInStream; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { NRangeCoder::CEncoder _rangeEncoder; IMatchFinder _matchFinder; void *_matchFinderObj; #ifdef COMPRESS_MF_MT Bool _multiThread; Bool _mtMode; CMatchFinderMt _matchFinderMt; #endif CMatchFinder _matchFinderBase; #ifdef COMPRESS_MF_MT Byte _pad1[kMtCacheLineDummy]; #endif COptimal _optimum[kNumOpts]; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; bool _fastMode; // bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _matchPriceCount; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; CSeqInStream _seqInStream; UInt32 _matchFinderCycles; // int _numSkip bool _writeEndMark; bool _needReleaseMFStream; void ReleaseMatchFinder() { _matchFinder.Init = 0; _seqInStream.RealStream.Release(); } void ReleaseMFStream() { if (_matchFinderObj && _needReleaseMFStream) { #ifdef COMPRESS_MF_MT if (_mtMode) MatchFinderMt_ReleaseStream(&_matchFinderMt); #endif _needReleaseMFStream = false; } _seqInStream.RealStream.Release(); } UInt32 ReadMatchDistances(UInt32 &numDistancePairs); void MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const { UInt32 price; if(repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + GetPureRepPrice(repIndex, state, posState); } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); UInt32 GetOptimum(UInt32 position, UInt32 &backRes); UInt32 GetOptimumFast(UInt32 &backRes); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "LZMADecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CDecoder); } #ifndef EXTRACT_ONLY #include "LZMAEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C-Lz" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBenchCon.h" #include "LzmaRam.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif #include "../../MyVersion.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kMatchFinderCycles, kLitContext, kLitPos, kPosBits, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary - [0,30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = (UInt32)-1; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dictionary); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 1; UInt32 numFastBytes = 128; UInt32 matchFinderCycles = 16 + numFastBytes / 2; bool matchFinderCyclesDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs; if (matchFinderCyclesDefined) if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionary; properties[1].ulVal = (UInt32)posStateBits; properties[2].ulVal = (UInt32)litContextBits; properties[3].ulVal = (UInt32)litPosBits; properties[4].ulVal = (UInt32)algorithm; properties[5].ulVal = (UInt32)numFastBytes; properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; properties[8].vt = VT_UI4; properties[8].ulVal = (UInt32)numThreads; // it must be last in property list properties[9].vt = VT_UI4; properties[9].ulVal = (UInt32)matchFinderCycles; int numProps = kNumPropsMax; if (!matchFinderCyclesDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/7zCrc.h" } #include "../../../Common/MyCom.h" #include "../../ICoder.h" #ifdef BENCH_MT #include "../../../Windows/Thread.h" #include "../../../Windows/Synchronization.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #else #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); // UInt64 numCommandsForOne = 1000 + ((t * t * 7) >> (2 * kSubBits)); // AMD K8 UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); // Intel Core2 UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { // UInt64 numCommands = (inSize * 216 + outSize * 14) * numIterations; // AMD K8 UInt64 numCommands = (inSize * 220 + outSize * 8) * numIterations; // Intel Core2 return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLZMA::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLZMA::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { size_t allocaSize = ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF; HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , allocaSize #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { if (size > (Size - Pos)) size = (UInt32)(Size - Pos); for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZ_RAM_E_FAIL (1) #define SZ_RAM_E_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZ_RAM_E_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1); } size_t minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZ_RAM_E_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZ_RAM_E_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZ_RAM_E_OUTOFMEMORY; } #endif } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include <stdlib.h> #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../../../../C/Compress/Lzma/LzmaDecode.h" #include "../../../../C/Compress/Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(outBuffer, (SizeT)outSizeProcessedLoc, 0, &x86State, 0); } return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include <stdlib.h> /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/comp.cc ================================================ /* * Copyright (C) 2006-2007 Junjiro Okajima * Copyright (C) 2006-2007 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: comp.cc,v 1.3 2007-11-13 13:27:23 jro Exp $ */ // extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <errno.h> #include "StdAfx.h" #include "../../../Common/MyInitGuid.h" //#include "../../../Common/MyWindows.h" #include "../../../Common/StringConvert.h" //#include "../../../Common/StringToInt.h" //#include "../../Common/StreamUtils.h" #include "../LZMA/LZMAEncoder.h" #include <pthread.h> #include <zlib.h> #include "sqlzma.h" ////////////////////////////////////////////////////////////////////// class CMemoryStream { protected: Bytef *m_data; UInt64 m_limit; UInt64 m_pos; public: CMemoryStream(Bytef *data, UInt64 size) : m_data(data), m_limit(size), m_pos(0) {} virtual ~CMemoryStream() {} }; class CInMemoryStream : public CMemoryStream, public IInStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialInStream> m_stream; public: MY_UNKNOWN_IMP1(IInStream); CInMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~CInMemoryStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { UInt64 room = m_limit - m_pos; if (size > room) size = room; if (size) { memcpy(data, m_data + m_pos, size); m_pos += size; } if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } }; class COutMemoryStream : public CMemoryStream, public IOutStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialOutStream> m_stream; public: MY_UNKNOWN_IMP1(IOutStream); COutMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~COutMemoryStream() {} UInt32 GetSize() {return m_pos;} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (m_pos + size > m_limit) return -ENOSPC; memcpy(m_data + m_pos, data, size); m_pos += size; if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } STDMETHOD(SetSize)(Int64 newSize) { assert(0); return E_NOTIMPL; } }; ////////////////////////////////////////////////////////////////////// static int LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, struct sqlzma_opts *opts, uLong *total_out) { int err; HRESULT res; const Byte a[] = { avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, 0, 0, 0, 0 }; NCompress::NLZMA::CEncoder encoderSpec; CMyComPtr<ICompressCoder> encoder = &encoderSpec; encoder->AddRef(); CInMemoryStream inStreamSpec(next_in, avail_in); CMyComPtr<ISequentialInStream> inStream = &inStreamSpec; inStream->AddRef(); COutMemoryStream outStreamSpec(next_out, avail_out); CMyComPtr<ISequentialOutStream> outStream = &outStreamSpec; outStream->AddRef(); // these values are dpending upon is_lzma() macro in sqlzma.h const UInt32 dictionary = opts->dicsize; //fprintf(stderr, "dic %u\n", dictionary); const UString mf = L"BT4"; const UInt32 posStateBits = 2; const UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data const UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data //const UInt32 algorithm = 2; const UInt32 algorithm = 1; const UInt32 numFastBytes = 128; const UInt32 matchFinderCycles = 16 + numFastBytes / 2; //const bool matchFinderCyclesDefined = false; const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_FALSE; // EOS properties[8].vt = VT_UI4; properties[8].ulVal = 1; // numThreads properties[9].vt = VT_UI4; properties[9].ulVal = UInt32(matchFinderCycles); err = -EINVAL; res = encoderSpec.SetCoderProperties(propIDs, properties, kNumPropsMax - 1); if (res) goto out; res = encoderSpec.WriteCoderProperties(outStream); if (res) goto out; UInt32 r; res = outStream->Write(a, sizeof(a), &r); if (res || r != sizeof(a)) goto out; err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); if (err) goto out; *total_out = outStreamSpec.GetSize(); out: return err; } ////////////////////////////////////////////////////////////////////// #define Failure(p) do { \ fprintf(stderr, "%s:%d: please report to jro " \ "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ __func__, __LINE__, \ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ abort(); \ } while(0) extern "C" int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out) { int err; Bytef *p = next_out; uInt l = avail_out; stream->next_in = next_in; stream->avail_in = avail_in; stream->next_out = p; stream->avail_out = l; err = deflate(stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) goto out_err; if (avail_in < stream->total_out) return err; if (is_lzma(*p)) Failure(p); if (opts->try_lzma) { unsigned char a[stream->total_out]; uLong processed; memcpy(a, p, stream->total_out); // malloc family in glibc and stdc++ seems to be thread-safe err = LzmaCompress(next_in, avail_in, p, l, opts, &processed); if (!err && processed <= stream->total_out) { if (!is_lzma(*next_out)) Failure(next_out); stream->total_out = processed; err = Z_STREAM_END; } else { //puts("by zlib"); memcpy(p, a, stream->total_out); err = Z_STREAM_END; } } return err; out_err: fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); return err; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LIBS = $(LIBS) oleaut32.lib user32.lib !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -W4 -Wp64 -DUNICODE -D_UNICODE !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../../../../C/Compress/Lzma/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../../../../C/Compress/Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaRam.o \ LZMADecoder.o \ LZMAEncoder.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ BranchX86.o \ MatchFinder.o \ LzmaDecode.o \ LzmaRamDecode.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c BranchX86.o: ../../../../C/Compress/Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Branch/BranchX86.c MatchFinder.o: ../../../../C/Compress/Lz/MatchFinder.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lz/MatchFinder.c LzmaDecode.o: ../../../../C/Compress/Lzma/LzmaDecode.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lzma/LzmaDecode.c LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef UseDebugFlags DebugFlags = -Wall -O0 -g -UNDEBUG endif # -pthread CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} Tgt = liblzma_r.a all: ${Tgt} RObjs = LZMAEncoder_r.o Alloc_r.o StreamUtils_r.o MatchFinder_r.o \ RangeCoderBit_r.o OutBuffer_r.o 7zCrc_r.o %_r.cc: ../LZMA/%.cpp ln $< $@ %_r.c: ../../../../C/%.c ln $< $@ %_r.c: ../../../../C/Compress/Lz/%.c ln $< $@ %_r.cc: ../../Common/%.cpp ln $< $@ %_r.cc: ../RangeCoder/%.cpp ln $< $@ LZMAEncoder_r.o: CXXFLAGS += -I../LZMA Alloc_r.o: CFLAGS += -I../../../../C StreamUtils_r.o: CXXFLAGS += -I../../Common MatchFinder_r.o: CFLAGS += -I../../../../C/Compress/Lz RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder OutBuffer_r.o: CXXFLAGS += -I../../Common 7zCrc_r.o: CFLAGS += -I../../../../C comp.o: CXXFLAGS += -I${Sqlzma} comp.o: comp.cc ${Sqlzma}/sqlzma.h liblzma_r.a: ${RObjs} comp.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) comp.o *_r.o ${Tgt} *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template <int numMoveBits, int NumBitLevels> class CBitTreeEncoder { CBitEncoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template <int numMoveBits, int NumBitLevels> class CBitTreeDecoder { CBitDecoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template <int numMoveBits> void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template <int numMoveBits> UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template <int numMoveBits> UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" DECL_INTERFACE(IProgress, 0, 5) { STDMETHOD(SetTotal)(UInt64 total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 57 #define MY_VER_BUILD 0 #define MY_VERSION "4.57" #define MY_7ZIP_VERSION "7-Zip 4.57" #define MY_DATE "2007-12-06" #define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/PropID.h ================================================ // Interface/PropID.h #ifndef __INTERFACE_PROPID_H #define __INTERFACE_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsFolder, kpidSize, kpidPackedSize, kpidAttributes, kpidCreationTime, kpidLastAccessTime, kpidLastWriteTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubFolders, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME UTCLastWriteTime; UInt32 Attributes; bool IsDirectory; bool AttributesAreDefined; bool UTCLastWriteTimeIsDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant)); UString fullPath; if(propVariant.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if(propVariant.vt != VT_BSTR) return E_FAIL; fullPath = propVariant.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attributes NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) { _processedFileInfo.Attributes = 0; _processedFileInfo.AttributesAreDefined = false; } else { if (propVariant.vt != VT_UI4) throw "incorrect item"; _processedFileInfo.Attributes = propVariant.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); { // Get Modified Time NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant)); _processedFileInfo.UTCLastWriteTimeIsDefined = false; switch(propVariant.vt) { case VT_EMPTY: // _processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault; break; case VT_FILETIME: _processedFileInfo.UTCLastWriteTime = propVariant.filetime; _processedFileInfo.UTCLastWriteTimeIsDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant)); bool newFileSizeDefined = (propVariant.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(propVariant); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.IsDirectory) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.UTCLastWriteTimeIsDefined) _outFileStreamSpec->SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if(newData != NULL) *newData = BoolToInt(true); if(newProperties != NULL) *newProperties = BoolToInt(true); if(indexInArchive != NULL) *indexInArchive = UInt32(-1); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = false; propVariant.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } propVariant.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if(dirItem.IsDirectory()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////////////////// // Main function int #ifdef _MSC_VER __cdecl #endif main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.CompareNoCase("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem item; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(name, fileInfo)) { PrintString(UString(L"Can't find file") + name); return 1; } item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = name; item.FullPath = name; dirItems.Add(item); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.CompareNoCase("l") == 0) listCommand = true; else if (command.CompareNoCase("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidSize, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidPath, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, kPassword, kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for(int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for(int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for(int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for(int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if(options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if(postString.IsEmpty()) { if(options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if(parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if(parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if(numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if(curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if(options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); CObjectVector<CDirItem> dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } UStringVector archivePaths; int i; for (i = 0; i < dirItems.Size(); i++) { const CDirItem &dirItem = dirItems[i]; if (!dirItem.IsDirectory()) archivePaths.Add(dirItem.FullPath); } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if(parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if(parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if(options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; if(parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if(updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if(options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if(options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; bool PasswordEnabled; UString Password; bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcLastWriteTimeDefault = utcLastWriteTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCreationTime, _processedFileInfo.CreationTime, _processedFileInfo.IsCreationTimeDefined)); RINOK(GetTime(index, kpidLastWriteTime, _processedFileInfo.LastWriteTime, _processedFileInfo.IsLastWriteTimeDefined)); RINOK(GetTime(index, kpidLastAccessTime, _processedFileInfo.LastAccessTime, _processedFileInfo.IsLastAccessTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDirectory) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDirectory) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDirectory) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size, fullPath, _processedFileInfo.IsLastWriteTimeDefined ? &_processedFileInfo.LastWriteTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDirectory, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDirectory) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IExtractCallBack STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _encrypted; struct CProcessedFileInfo { FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt32 Attributes; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsDirectory; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcLastWriteTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteModified(true), WriteCreated(false), WriteAccessed(false), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == '\\') { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDirectory() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant propVariant; if (_subArchiveMode) { switch(propID) { case kpidName: propVariant = _subArchiveName; break; } propVariant.Detach(value); return S_OK; } switch(propID) { case kpidName: propVariant = _fileInfo.Name; break; case kpidIsFolder: propVariant = _fileInfo.IsDirectory(); break; case kpidSize: propVariant = _fileInfo.Size; break; case kpidAttributes: propVariant = (UInt32)_fileInfo.Attributes; break; case kpidLastAccessTime: propVariant = _fileInfo.LastAccessTime; break; case kpidCreationTime: propVariant = _fileInfo.CreationTime; break; case kpidLastWriteTime: propVariant = _fileInfo.LastWriteTime; break; } propVariant.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDirectory()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!Callback) return E_NOTIMPL; return Callback->CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" struct IOpenCallbackUI { virtual HRESULT CheckBreak() = 0; virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0; virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0; #ifndef _NO_CRYPTO virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0; virtual HRESULT GetPasswordIfAny(UString &password) = 0; virtual bool WasPasswordAsked() = 0; virtual void ClearPasswordWasAskedFlag() = 0; #endif }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); // IArchiveOpenVolumeCallback STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); #ifndef _NO_CRYPTO // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static const wchar_t *kEmptyFileAlias = L"[Content]"; UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; return kEmptyFileAlias; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; struct CArchiveItem { bool IsDirectory; // DWORD Attributes; // NWindows::NCOM::CPropVariant LastWriteTime; FILETIME LastWriteTime; bool SizeIsDefined; UInt64 Size; UString Name; bool Censored; int IndexInServer; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo( const UString &prefix, // prefix for logical path const UString &fullPathName, // path on disk: can be relative to some basePrefix const NFind::CFileInfoW &fileInfo, CObjectVector<CDirItem> &dirItems) { CDirItem item; item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = prefix + fileInfo.Name; item.FullPath = fullPathName; dirItems.Add(item); } static void EnumerateDirectory( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UString &directory, // additional disk prefix starting from baseFolderPrefix const UString &prefix, // logical prefix CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + directory); return; } if (!found) break; AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } void EnumerateDirItems( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UStringVector &fileNames, // names relative to baseFolderPrefix const UString &archiveNamePrefix, CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for(int i = 0; i < fileNames.Size(); i++) { const UString &fileName = fileNames[i]; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + fileName); continue; } AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const UString &diskPrefix, // full disk path prefix const UString &archivePrefix, // prefix from root const UStringVector &addArchivePrefix, // prefix from curNode CObjectVector<CDirItem> &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->CheckBreak()); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = diskPrefix + name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fileInfo.IsDirectory(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } const UString realName = fileInfo.Name; const UString realDiskPath = diskPrefix + realName; { UStringVector pathParts; pathParts.Add(fileInfo.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support } RINOK(EnumerateDirItems(*nextNode, realDiskPath + wchar_t(kDirDelimiter), archivePrefix + realName + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = diskPrefix + nextNode.Name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fileInfo.IsDirectory()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems(nextNode, diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter), archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter), UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(diskPrefix); break; } if (!found) break; if (callback) RINOK(callback->CheckBreak()); const UString &name = fileInfo.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory())) { AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems); if (fileInfo.IsDirectory()) enterToSubFolders2 = true; } if (!fileInfo.IsDirectory()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems(*nextNode, diskPrefix + name + wchar_t(kDirDelimiter), archivePrefix + name + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "DirItem.h" #include "Windows/FileFind.h" void AddDirFileInfo( const UString &prefix, const UString &fullPathName, const NWindows::NFile::NFind::CFileInfoW &fileInfo, CObjectVector<CDirItem> &dirItems); void EnumerateDirItems( const UString &baseFolderPrefix, const UStringVector &fileNames, const UString &archiveNamePrefix, CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); struct IEnumDirItemCallback { virtual HRESULT CheckBreak() { return S_OK; } }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const UString &defaultName, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", defaultName); if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.LastWriteTime, options.ArchiveFileInfo.Attributes, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "can't decompress folder"; archiveSizes.Add(archiveFileInfo.Size); totalPackSize += archiveFileInfo.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; options.ArchiveFileInfo = archiveFileInfo; #ifndef _NO_CRYPTO openCallback->ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback); bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), archiveFileInfo.Size + archiveLink.VolumesSize, archiveLink.GetDefaultItemName(), wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; virtual HRESULT SetPassword(const UString &password) = 0; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software\\7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fileInfo; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fileInfo)) if (!fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDirectory()) continue; RINOK(LoadDll(folderPrefix + fileInfo.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } int CCodecs::FindFormatForArchiveName(const UString &archivePath) const { int slashPos1 = archivePath.ReverseFind(L'\\'); int slashPos2 = archivePath.ReverseFind(L'.'); int dotPos = archivePath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = archivePath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(arcType) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UINT32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UINT32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); int FindFormatForArchiveName(const UString &archivePath) const; int FindFormatForArchiveType(const UString &arcType) const; MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UINT32 *numMethods); STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UINT32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UINT32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) result = defaultName; return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const UInt32 kBufferSize = (200 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); for (UInt32 pos = 0; pos < processedSize; pos++) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() == 0) continue; if (pos + sig.GetCapacity() > processedSize) continue; if (TestSignature(buffer + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices.Delete(i--); } } } orderIndices2 += orderIndices; orderIndices = orderIndices2; } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] && 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif HRESULT badResult = S_OK; for(i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; if(result != S_OK) { badResult = result; if(result == E_ABORT) break; continue; } *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } if (badResult != S_OK) return badResult; return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { HRESULT result = OpenArchive(codecs, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || getStream == 0) return S_OK; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK) return S_OK; CMyComPtr<IInStream> subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK) return S_OK; if (!subStream) return S_OK; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return S_OK; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, openCallback); int formatInfo; return OpenArchive(codecs, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(fileName, NULL, openCallback); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } bool IsOpen; CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCreationTime: case kpidLastWriteTime: case kpidLastAccessTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttributes: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDirectory(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; if (!property.Value.IsEmpty()) ParseNumberString(property.Value, propVariant); realNames.Add(property.Name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #ifdef _WIN32 #include <mapi.h> #endif #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Common/CommandLineParser.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" // #include "Windows/Synchronization.h" #include "../../Common/FileStreams.h" #include "../../Compress/Copy/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/UpdateProduce.h" #include "../Common/OpenArchive.h" #include "TempFiles.h" #include "UpdateCallback.h" #include "EnumDirItems.h" #include "SetProperties.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NCommandLineParser; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType) { if (!arcType.IsEmpty()) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(arcType); else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArchiveItem> &archiveItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CObjectVector<CDirItem> &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kDOS: case NFileTimeType::kUnix: fileTimeType = NFileTimeType::EEnum(value); break; default: return E_FAIL; } CObjectVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!! CObjectVector<CUpdatePair2> updatePairs2; UpdateProduce(updatePairs, actionSet, updatePairs2); UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArchiveItems = &archiveItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArchiveItem> &archiveItems) { archiveItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); archiveItems.Reserve(numItems); for(UInt32 i = 0; i < numItems; i++) { CArchiveItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory)); ai.Censored = censor.CheckPath(ai.Name.IsEmpty() ? defaultItemName : ai.Name, !ai.IsDirectory); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.LastWriteTime, ai.LastWriteTime)); CPropVariant propertySize; RINOK(archive->GetProperty(i, kpidSize, &propertySize)); ai.SizeIsDefined = (propertySize.vt != VT_EMPTY); if (ai.SizeIsDefined) ai.Size = ConvertPropVariantToUInt64(propertySize); ai.IndexInServer = i; archiveItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArchiveItem> &archiveItems, const CObjectVector<CDirItem> &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, archiveItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT CheckBreak() { return Callback->CheckBreak(); } }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, openCallback); RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CObjectVector<CDirItem> dirItems; if (options.StdInMode) { CDirItem item; item.FullPath = item.Name = options.StdInFileName; item.Size = (UInt64)(Int64)-1; item.Attributes = 0; SYSTEMTIME st; FILETIME ft; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft; dirItems.Add(item); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if(res != S_OK) { errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArchiveItem> archiveItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, archiveItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, archiveItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArchiveItems(0), UpdatePairs(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsFolder, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidLastAccessTime, VT_FILETIME}, { NULL, kpidCreationTime, VT_FILETIME}, { NULL, kpidLastWriteTime, VT_FILETIME}, { NULL, kpidAttributes, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; */ STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return E_NOTIMPL; /* return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); */ } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(newData != NULL) *newData = BoolToInt(updatePair.NewData); if(newProperties != NULL) *newProperties = BoolToInt(updatePair.NewProperties); if(indexInArchive != NULL) { if (updatePair.ExistInArchive) { if (ArchiveItems == 0) *indexInArchive = updatePair.ArchiveItemIndex; else *indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; } else *indexInArchive = UInt32(-1); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = updatePair.IsAnti; propVariant.Detach(value); return S_OK; } if (updatePair.IsAnti) { switch(propID) { case kpidIsFolder: case kpidPath: break; case kpidSize: propVariant = (UInt64)0; propVariant.Detach(value); return S_OK; default: propVariant.Detach(value); return S_OK; } } if(updatePair.ExistOnDisk) { const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } else { if (propID == kpidPath) { if (updatePair.NewNameIsDefined) { propVariant = updatePair.NewName; propVariant.Detach(value); return S_OK; } } if (updatePair.ExistInArchive && Archive) { UInt32 indexInArchive; if (ArchiveItems == 0) indexInArchive = updatePair.ArchiveItemIndex; else indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } propVariant.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(!updatePair.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if(updatePair.IsAnti) { return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true); } const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; RINOK(Callback->GetStream(dirItem.Name, false)); if(dirItem.IsDirectory()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IUpdateCallback STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; UString DirPrefix; bool ShareForWrite; bool StdInMode; const CObjectVector<CDirItem> *DirItems; const CObjectVector<CArchiveItem> *ArchiveItems; const CObjectVector<CUpdatePair2> *UpdatePairs; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; if (!FileTimeToUnixTime(time1, unixTime1)) { unixTime1 = 0; // throw 4191614; } if (!FileTimeToUnixTime(time2, unixTime2)) { unixTime2 = 0; // throw 4191615; } return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); /* if (!FileTimeToDosTime(time1, dosTime1)) throw 4191616; if (!FileTimeToDosTime(time2, dosTime2)) throw 4191617; */ return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; /* static const char *kNotCensoredCollisionMessaged = "Internal file name collision:\n"; static const char *kSameTimeChangedSizeCollisionMessaged = "Collision between files with same date/time and different sizes:\n"; */ static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) { UString message = kDuplicateFileNameMessage; message += L"\n"; message += strings[indices[i]]; message += L"\n"; message += strings[indices[i + 1]]; throw message; } } void GetUpdatePairInfoList( const CObjectVector<CDirItem> &dirItems, const CObjectVector<CArchiveItem> &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, archiveIndices; UStringVector dirNames, archiveNames; int numDirItems = dirItems.Size(); int i; for(i = 0; i < numDirItems; i++) dirNames.Add(dirItems[i].Name); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); int numArchiveItems = archiveItems.Size(); for(i = 0; i < numArchiveItems; i++) archiveNames.Add(archiveItems[i].Name); SortFileNames(archiveNames, archiveIndices); TestDuplicateString(archiveNames, archiveIndices); int dirItemIndex = 0, archiveItemIndex = 0; CUpdatePair pair; while(dirItemIndex < numDirItems && archiveItemIndex < numArchiveItems) { int dirItemIndex2 = dirIndices[dirItemIndex], archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CDirItem &dirItem = dirItems[dirItemIndex2]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; int compareResult = CompareFileNames(dirItem.Name, archiveItem.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirItemIndex2; dirItemIndex++; } else if (compareResult > 0) { pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; archiveItemIndex++; } else { if (!archiveItem.Censored) throw 1082022;; // TTString(kNotCensoredCollisionMessaged + dirItem.Name); pair.DirItemIndex = dirItemIndex2; pair.ArchiveItemIndex = archiveItemIndex2; switch (MyCompareTime(fileTimeType, dirItem.LastWriteTime, archiveItem.LastWriteTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (archiveItem.SizeIsDefined) if (dirItem.Size != archiveItem.Size) // throw 1082034; // kSameTimeChangedSizeCollisionMessaged; pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirItemIndex++; archiveItemIndex++; } updatePairs.Add(pair); } for(;dirItemIndex < numDirItems; dirItemIndex++) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirIndices[dirItemIndex]; updatePairs.Add(pair); } for(;archiveItemIndex < numArchiveItems; archiveItemIndex++) { int archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; updatePairs.Add(pair); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArchiveItemIndex; int DirItemIndex; }; void GetUpdatePairInfoList( const CObjectVector<CDirItem> &dirItems, const CObjectVector<CArchiveItem> &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CObjectVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector<CUpdatePair2> &operationChain) { for(int i = 0; i < updatePairs.Size(); i++) { // CUpdateArchiveRange aRange; const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 pair2; pair2.IsAnti = false; pair2.ArchiveItemIndex = pair.ArchiveItemIndex; pair2.DirItemIndex = pair.DirItemIndex; pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk); pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive && pair.State != NPairState::kNotMasked); switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]); // cout << "deleting"; */ break; case NPairAction::kCopy: { if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = false; operationChain.Add(pair2); break; } case NPairAction::kCompress: { if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } case NPairAction::kCompressAsAnti: { pair2.IsAnti = true; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { // bool OperationIsCompress; bool NewData; bool NewProperties; bool ExistInArchive; bool ExistOnDisk; bool IsAnti; int ArchiveItemIndex; int DirItemIndex; bool NewNameIsDefined; UString NewName; CUpdatePair2(): NewNameIsDefined(false) {} }; void UpdateProduce( const CObjectVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector<CUpdatePair2> &operationChain); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRename: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractingString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestingString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkippingString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (encrypted) (*OutStream) << "Can not open encrypted archive. Wrong password?"; else (*OutStream) << "Can not open file as archive"; (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword) STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); HRESULT SetPassword(const UString &password); public: bool PasswordIsDefined; UString Password; UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsFolder, L"Folder" }, { kpidSize, L"Size" }, { kpidPackedSize, L"Packed Size" }, { kpidAttributes, L"Attributes" }, { kpidCreationTime, L"Created" }, { kpidLastAccessTime, L"Accessed" }, { kpidLastWriteTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubFolders, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" } }; static const char kEmptyAttributeChar = '.'; static const char kDirectoryAttributeChar = 'D'; static const char kReadonlyAttributeChar = 'R'; static const char kHiddenAttributeChar = 'H'; static const char kSystemAttributeChar = 'S'; static const char kArchiveAttributeChar = 'A'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttributesString(DWORD wa, bool directory, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? kDirectoryAttributeChar: kEmptyAttributeChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? kReadonlyAttributeChar: kEmptyAttributeChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? kHiddenAttributeChar: kEmptyAttributeChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? kSystemAttributeChar: kEmptyAttributeChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? kArchiveAttributeChar: kEmptyAttributeChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidLastWriteTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; return L"?"; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &propVariant) { if (propVariant.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&propVariant.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant)); if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (propVariant.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: propVariant = defaultItemName; break; case kpidLastWriteTime: propVariant = archiveFileInfo.LastWriteTime; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidLastWriteTime) { PrintTime(propVariant); } else if (fieldInfo.PropID == kpidAttributes) { if (propVariant.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = propVariant.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttributesString(attributes, isFolder, s); g_StdOut << s; } else if (propVariant.vt == VT_BSTR) { if (techMode) g_StdOut << propVariant.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal); } else { UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackedSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant propVariant; if (archive->GetProperty(index, propID, &propVariant) != S_OK) throw "GetPropertyValue error"; if (propVariant.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(propVariant); return true; } HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl; numErrors++; continue; } if (archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback); if (result != S_OK) { g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackedSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" " -p{Password}: set Password\n" " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UINT32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, options.PasswordEnabled, options.Password, numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, options.ArchiveName, options.ArcType)) throw "Unsupported archive type"; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int #ifdef _MSC_VER __cdecl #endif main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/XP/2003/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::SetTotal(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR temp(Password); *password = temp.Detach(); return S_OK; } HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: HRESULT CheckBreak(); HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes); HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes); HRESULT CryptoGetTextPassword(BSTR *password); HRESULT GetPasswordIfAny(UString &password); bool WasPasswordAsked(); void ClearPasswordWasAskedFlag(); CStdOutStream *OutStream; bool PasswordIsDefined; UString Password; bool PasswordWasAsked; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { /* if (NConsoleClose::TestBreakSignal()) return E_ABORT; */ return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; bool PasswordIsDefined; UString Password; bool AskPassword; CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), PasswordIsDefined(false), AskPassword(false), StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRename = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? "; // return true if pressed Quite; // in: anAll // out: anAll, anYes; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRename: return NUserAnswerMode::kAutoRename; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRename, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/7zip/UI/Console/afxres.h ================================================ #include <winresrc.h> ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Build.mak ================================================ !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -EHsc -Gz -WX -Gy !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS_O1 = $(CFLAGS) -O1 -W4 -Wp64 CFLAGS_O2 = $(CFLAGS) -O2 -W4 -Wp64 !ELSE CFLAGS_O1 = $(CFLAGS) -O1 -W3 CFLAGS_O2 = $(CFLAGS) -O2 -W3 !ENDIF LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if(_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } class CCRCTableInit { public: CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for(int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include <ctype.h> #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { Free(); } void CBaseRecordVector::Free() { delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if (newCapacity <= _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void Free(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while(--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if(!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if(intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if(c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if(c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if(!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; char defaultChar = '_'; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_INT16_DEFINED #define _7ZIP_INT16_DEFINED typedef short Int16; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED typedef int Int32; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED typedef unsigned int UInt32; #endif #ifdef _MSC_VER #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef __int64 Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned __int64 UInt64; #endif #else #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef long long int Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned long long int UInt64; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; // These functions are for UTF8 <-> UTF16 conversion. bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { Byte c = (Byte)src[i++]; if (c < 0x80) { dest += (wchar_t)c; continue; } if(c < 0xC0) return false; int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { if (i >= src.Length()) return false; Byte c2 = (Byte)src[i++]; if (c2 < 0x80 || c2 >= 0xC0) return false; value <<= 6; value |= (c2 - 0x80); numAdds--; } while(numAdds > 0); if (value < 0x10000) dest += (wchar_t)(value); else { value -= 0x10000; if (value >= 0x100000) return false; dest += (wchar_t)(0xD800 + (value >> 10)); dest += (wchar_t)(0xDC00 + (value & 0x3FF)); } } return true; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { UInt32 value = (UInt32)src[i++]; if (value < 0x80) { dest += (char)value; continue; } if (value >= 0xD800 && value < 0xE000) { if (value >= 0xDC00) return false; if (i >= src.Length()) return false; UInt32 c2 = (UInt32)src[i++]; if (c2 < 0xDC00 || c2 >= 0xE000) return false; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; dest += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; dest += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); } return true; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if(CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if(!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if(::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for(int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if(string.IsEmpty()) { if(i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if(errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfo &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATAW &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA findData; _handle = ::FindFirstFile(wildcard, &findData); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW findData; _handle = ::FindFirstFileW(wildcard, &findData); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &findData); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA findData; bool result = BOOLToBool(::FindNextFile(_handle, &findData)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW findData; if (!::FindNextFileW(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; if (!::FindNextFileA(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for(UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for(UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDirectory(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attributes & mask) != 0); } public: DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDirectory() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif #ifdef _WIN32 const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } #endif }}} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif #ifdef _WIN32 void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if(hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if(vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" // #include <stdio.h> #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(UInt32 value, char *s, int numPos) { char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if(!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(st.wYear, s, 4); *s++ = '-'; s = UIntToStringSpec(st.wMonth, s, 2); *s++ = '-'; s = UIntToStringSpec(st.wDay, s, 2); if (includeTime) { *s++ = ' '; s = UIntToStringSpec(st.wHour, s, 2); *s++ = ':'; s = UIntToStringSpec(st.wMinute, s, 2); if (includeSeconds) { *s++ = ':'; UIntToStringSpec(st.wSecond, s, 2); } } /* sprintf(s, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay); if (includeTime) { sprintf(s + strlen(s), " %02d:%02d", st.wHour, st.wMinute); if (includeSeconds) sprintf(s + strlen(s), ":%02d", st.wSecond); } */ return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return propVariant.bstrVal; case VT_UI1: return ConvertUInt64ToString(propVariant.bVal); case VT_UI2: return ConvertUInt64ToString(propVariant.uiVal); case VT_UI4: return ConvertUInt64ToString(propVariant.ulVal); case VT_UI8: return ConvertUInt64ToString(propVariant.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(propVariant.filetime, true, true); /* case VT_I1: return ConvertInt64ToString(propVariant.cVal); */ case VT_I2: return ConvertInt64ToString(propVariant.iVal); case VT_I4: return ConvertInt64ToString(propVariant.lVal); case VT_I8: return ConvertInt64ToString(propVariant.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(propVariant.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_UI1: return propVariant.bVal; case VT_UI2: return propVariant.uiVal; case VT_UI4: return propVariant.ulVal; case VT_UI8: return (UInt64)propVariant.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } HRes Close() { return Event_Close(&_object); } #ifdef _WIN32 HRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif HRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } HRes Reset() { return Event_Reset(&_object); } HRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: HRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 HRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: HRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: HRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: HRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } HRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } HRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } HRes Release() { return Semaphore_Release1(&_object); } HRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } HRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } HRes Close() { return Thread_Close(&thread); } HRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } HRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { inline bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime(UInt16(dosTime >> 16), UInt16(dosTime & 0xFFFF), &fileTime)); } const UInt32 kHighDosTime = 0xFF9FBF7D; const UInt32 kLowDosTime = 0x210000; inline bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { if (fileTime.dwHighDateTime >= 0x01C00000) // 2000 dosTime = kHighDosTime; else dosTime = kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } const UInt32 kNumTimeQuantumsInSecond = 10000000; const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; inline void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } inline bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } }} #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.49 Copyright (c) 1999-2007 Igor Pavlov 2006-07-05\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-15\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/LGPL.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the library's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. <signature of Ty Coon>, 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/Methods.txt ================================================ 7-Zip method IDs (4.56) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 7F ZZ ZZ ZZ ZZ ZZ MM MM 7F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 01 - Reserved 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 04 Delta (subject to change) 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - BC_PPC_B (Big Endian) 03 - Alpha 01 - BC_Alpha 04 - IA64 01 - BC_IA64 05 - ARM 01 - BC_ARM 06 - M68 05 - BC_M68_B (Big Endian) 07 - ARM Thumb 01 - BC_ARMThumb 08 - SPARC 05 - BC_SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 80 - reserved for independent developers E0 - Random IDs 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - Bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - Bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - Bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - Bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - Bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2007: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-3.3-grml-lzma/lzma/lzma.txt ================================================ LZMA SDK 4.57 ------------- LZMA SDK Copyright (C) 1999-2007 Igor Pavlov LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is available under any of the following licenses: 1) GNU Lesser General Public License (GNU LGPL) 2) Common Public License (CPL) 3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 4) Proprietary license It means that you can select one of these four options and follow rules of that license. 1,2) GNU LGPL and CPL licenses are pretty similar and both these licenses are classified as - "Free software licenses" at http://www.gnu.org/ - "OSI-approved" at http://www.opensource.org/ 3) 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 files from LZMA SDK without subjecting your linked code to the terms of the CPL or GNU LGPL. Any modifications or additions to files from LZMA SDK, however, are subject to the GNU LGPL or CPL terms. SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, while you keep LZMA SDK code unmodified. SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits you to use this code under the same terms and conditions contained in the License Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov. SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version of LZMA SDK as update for previous versions. SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits you to use code of the following files: BranchTypes.h, LzmaTypes.h, LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, LzmaAlone.cs, LzmaAlone.java as public domain code. 4) Proprietary license LZMA SDK also can be available under a proprietary license which can include: 1) Right to modify code without subjecting modified code to the terms of the CPL or GNU LGPL 2) Technical support for code To request such proprietary license or any additional consultations, send email message from that page: http://www.7-zip.org/support.html You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You should have received a copy of the Common Public License along with this library. LZMA SDK Contents ----------------- LZMA SDK includes: - C++ source code of LZMA compressing and decompressing - ANSI-C compatible source code for LZMA decompressing - C# source code for LZMA compressing and decompressing - Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system ANSI-C LZMA decompression code was ported from original C++ sources to C. Also it was simplified and optimized for code size. But it is fully compatible with LZMA from 7-Zip. UNIX/Linux version ------------------ To compile C++ version of file->file LZMA, go to directory C/7zip/Compress/LZMA_Alone and type "make" or "make clean all" to recompile all. In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, change string in makefile LIB = -lm to string LIB = -lm -static Files --------------------- C - C source code CPP - CPP source code CS - C# source code Java - Java source code lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description (this file) methods.txt - Compression method IDs for .7z LGPL.txt - GNU Lesser General Public License CPL.html - Common Public License lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C - C files Compress - files related to compression/decompression Lz - files related to LZ (Lempel-Ziv) compression algorithm Lzma - ANSI-C compatible LZMA decompressor LzmaDecode.h - interface for LZMA decoding on ANSI-C LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version) LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version) LzmaTest.c - test application that decodes LZMA encoded file LzmaTypes.h - basic types for LZMA Decoder LzmaStateDecode.h - interface for LZMA decoding (State version) LzmaStateDecode.c - LZMA decoding on ANSI-C (State version) LzmaStateTest.c - test application (State version) Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving 7z_C - 7z ANSI-C Decoder CPP -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. You can find ANSI-C LZMA decompressing code at folder C/7zip/Compress/Lzma 7-Zip doesn't use that ANSI-C LZMA code and that code was developed specially for this SDK. And files from C/7zip/Compress/Lzma do not need files from other directories of SDK for compiling. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 1 MB/s on 1 GHz CPU - Estimated decompressing speed: - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (8-32 KB + DictionarySize) - Small code size for decompressing: 2-8 KB (depending from speed optimizations) LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect to speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations Speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with AMD Athlon 64 X2 CPU results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you can change number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Using Filters ------------- You can increase compression ratio for some data types, using special filters before compressing. For example, it's possible to increase compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C/C++ source code of such filters in folder "7zip/Compress/Branch" You can check compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=bc_arm -m1=lzma With filter for big-endian ARM code (using additional Swap4 filter): 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. Source code of these CALL filters is pretty simple (about 20 lines of C++), so you can convert it from C++ version yourself. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties for compressed data 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ To compile ANSI-C LZMA Decoder you can use one of the following files sets: 1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version) 2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version) 3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface) Memory requirements for LZMA decoding ------------------------------------- LZMA decoder doesn't allocate memory itself, so you must allocate memory and send it to LZMA. Stack usage of LZMA decoding function for local variables is not larger than 200 bytes. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 5 interfaces: 1) Single-call Decompressing 2) Single-call Decompressing with input stream callback 3) Multi-call Decompressing with output buffer 4) Multi-call Decompressing with input callback and output buffer 5) Multi-call State Decompressing (zlib-like interface) Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions. Decompressing steps ------------------- 1) read LZMA properties (5 bytes): unsigned char properties[LZMA_PROPERTIES_SIZE]; 2) read uncompressed size (8 bytes, little-endian) 3) Decode properties: CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); 4) Allocate memory block for internal Structures: state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); LZMA decoder uses array of CProb variables as internal structure. By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make it unsigned_int. It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case. 5) Main Decompressing You must use one of the following interfaces: 5.1 Single-call Decompressing ----------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: int res = LzmaDecode(&state, inStream, compressedSize, &inProcessed, outStream, outSize, &outProcessed); 5.2 Single-call Decompressing with input stream callback -------------------------------------------------------- When to use: File->RAM or Flash->RAM decompressing. Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) { CBuffer *bo = (CBuffer *)object; *buffer = bo->Buffer; *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize); return LZMA_RESULT_OK; } CBuffer g_InBuffer; g_InBuffer.File = inFile; g_InBuffer.InCallback.Read = LzmaReadCompressed; int res = LzmaDecode(&state, &g_InBuffer.InCallback, outStream, outSize, &outProcessed); 5.3 Multi-call decompressing with output buffer ----------------------------------------------- When to use: RAM->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_OUT_READ Memory Requirements: - Input buffer: compressed size - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaTest.c for more details. 5.4 Multi-call decompressing with input callback and output buffer ------------------------------------------------------------------ When to use: File->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, &bo.InCallback, g_OutBuffer, outAvail, &outProcessed); } while you need more bytes see LzmaTest.c for more details: 5.5 Multi-call State Decompressing (zlib-like interface) ------------------------------------------------------------------ When to use: file->file decompressing Compile files: LzmaStateDecode.h, LzmaStateDecode.c Compile defines: Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaStateTest.c for more details: 6) Free all allocated blocks Note ---- LzmaDecodeSize.c is size-optimized version of LzmaDecode.c. But compiled code of LzmaDecodeSize.c can be larger than compiled code of LzmaDecode.c. So it's better to use LzmaDecode.c in most cases. EXIT codes ----------- LZMA decoder can return one of the following codes: #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 If you use callback function for input data and you return some error code, LZMA Decoder also returns that code. LZMA Defines ------------ _LZMA_IN_CB - Use callback for input data _LZMA_OUT_READ - Use read function for output data _LZMA_LOC_OPT - Enable local speed optimizations inside code. _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version). _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version) and LzmaStateDecode.c _LZMA_PROB32 - It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t. You can use it to enable 64-bit sizes supporting C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. By default, LZMA Encoder contains all Match Finders. But for compressing it's enough to have just one of them. So for reducing size of compressing code you can define: #define COMPRESS_MF_BT #define COMPRESS_MF_BT4 and it will use only bt4 match finder. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqlzma.h ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma. */ /* $Id: sqlzma.h,v 1.20 2008-03-12 16:58:34 jro Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include <stdlib.h> #include <string.h> #include <zlib.h> #ifdef _REENTRANT #include <pthread.h> #endif #else #include <linux/zlib.h> #endif #define _7ZIP_BYTE_DEFINED /* * detect the compression method automatically by the first byte of compressed * data. * according to rfc1950, the first byte of zlib compression must be 0x?8. */ #define is_lzma(c) (c == 0x5d) /* ---------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif #ifndef __KERNEL__ /* for mksquashfs only */ struct sqlzma_opts { unsigned int try_lzma; unsigned int dicsize; }; int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out); #endif /* ---------------------------------------------------------------------- */ /* * Three patterns for sqlzma uncompression. very dirty code. * - kernel space (squashfs kernel module) * - user space with pthread (mksquashfs) * - user space without pthread (unsquashfs) */ struct sized_buf { unsigned int sz; unsigned char *buf; }; enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST}; struct sqlzma_un { int un_lzma; struct sized_buf un_a[SQUN_LAST]; unsigned char un_prob[31960]; /* unlzma 64KB - 1MB */ z_stream un_stream; #define un_cmbuf un_stream.next_in #define un_cmlen un_stream.avail_in #define un_resbuf un_stream.next_out #define un_resroom un_stream.avail_out #define un_reslen un_stream.total_out }; int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz); int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst); void sqlzma_fin(struct sqlzma_un *un); /* ---------------------------------------------------------------------- */ #ifdef __cplusplus }; #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqlzma.txt ================================================ # Copyright (C) 2006-2008 Junjiro Okajima # Copyright (C) 2006-2008 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: sqlzma.txt,v 1.37 2008-03-12 15:16:50 jro Exp $ LZMA patch for squashfs Junjiro Okajima o What is this? This is a patch against lzma449.tar.bz2 and squashfs3.3.tar.gz, and makes squashfs to support both of LZMA compression and ZLIB compression. The new squashfs image file (generated without '-nolzma' option) has no backward compatibility, while the patched squashfs and its tools can handle the old squashfs image generated by the unpatched squashfs-tools. This patch is developed and tested on linux-2.6.24.3. o Files - Makefile a toplevel makefile which builds everything. it is recommended to use this makefile. - sqlzma.h a global header file. this file is used from kernel and userspace utilities. - sqmagic.h defines patched squashfs magic number. - sqlzma1-XXX.patch a patch against lzma package. currently it is lzma449.tar.bz2 and the 'XXX in filename is '449'. - sqlzma2k-YYY.patch a patch against squashfs kernel source. currently it is squashfs3.3.tar.gz and the 'YYY' in filename is '3.3'. - sqlzma2u-YYY.patch a patch against squashfs utility. o Download, Extract, Patch and Build - choose the lzma version you use, and modify ./Makefile. - mkdir lzmaXXX, get SourceForge/sevenzip/lzmaXXX.tar.bz2, and extract it into lzmaXXX dir. - apply sqlzma1-XXX.patch to lzmaXXX. - get SourceForge/squashfs/squashfsYYY.tar.gz, extract, and get squashfsYYY/. - apply squashfsYYY/kernel-patches/linux-2.6.24.3/squashfsYYY-patch to your kernel source, and then also apply sqlzma2k-YYY.patch to it. - apply sqlzma2u-YYY.patch to squashfsYYY. - make them. if you have lzmaXXX and squashfsYYY in the same dir, a toplevel Makefile in this patchset builds everything for you. If you want to change their path, edit the variable definitions in ./Makefile. - It builds these things. + ${Squashfs}/kernel-patches/${KVer}/fs/squashfs/ * squashfs.ko a patched squashfs which supports LZMA uncompression. If you didn't load unlzma.ko and sqlzma.ko before compilation of squashfs.ko, the linker may produce some warnings about the functions in sqlzma.ko. But you can ignore them in safe. + ${Lzma}/C/7zip/Compress/LZMA_C/ * libunlzma.a LZMA uncompression user library for squashfs utilities. * libunlzma_r.a thread-safe one. + ${Lzma}/C/7zip/Compress/LZMA_C/kmod/ * unlzma.ko generic LZMA uncompression module for linux kernel. * sqlzma.ko LZMA uncompression kernel module for squashfs, a bridge library between squashfs and unlzma.ko. + ${Lzma}/C/7zip/Compress/LZMA_Alone/ * liblzma_r.a thread-safe LZMA compression user library for squashfs utilities. + ${Squashfs}/squashfs-tools/ * mksquashfs, unsquashfs patched squashfs utilities which support LZMA compression. - copy the modules squashfs.ko, unlzma.ko and sqlzma.ko to wherever you like. - load these modules. - create your filesystem image by mksquashfs. - mount it and enjoy. o Added options - mksquashfs -lzmadic N This option sets the dictionary size for LZMA compression. The default value is same as the block size, even if you change the block size by specifying -b (block size) option for mksquashfs. The dictionary size always follows it by default. If you want to set a different value from the block size, then use this option ALONE or AFTER -b option. In append mode, you can't change the block size, but the LZMA dictionary size since the compression is done for every and each block. The syntax is equivalent ot -b option, ie. you can use K (kilobyte) or M (megabyte). - mksquashfs -nolzma This option makes mksquashfs not to try LZMA compression. And it uses only ZLIB compression, as it was unpatched. - no options are added to unsquashfs. the patched unsquashfs automatically detects whether the given squashfs image uses LZMA compression or not. o LZMA and ZLIB There are three groups of byte stream in compression. - both of LZMA and ZLIB cannot compress. - LZMA gets better compression. - ZLIB gets better compression. This patch supports both compression methods. The patched mksquashfs tries ZLIB compression first. If the data cannot be compressed, store the data uncompressed as unpatched mksquashfs does. If it succeeds and -nolzma option is not specified, then keep the compressed data and try LZMA compression. After LZMA compression, compares the sizes of the two compressed data and discard the larger one. Honestly speaking, I do know nothing about the compression theory. This is the fact I got from using these libraries. (What is this thing called in English? a rule of thumb?) o Multi-call decompression and parallel decompression While squashfs3.1-r2 took the approach of single-call ZLIB decompression, squashfs3.2 and later takes the approach of multi-call which has an advantage of memory consumption. So I tried implementing multi-call LZMA decompression too, but I gave up. Because of memory usage. While single-call LZMA decompression doesn't require a dictionary, multi-call does. And its size can be mega-bytes (the dictionary size which I checked was 8388608). In the case of single-call LZMA decompression, it requires 64KB buffer at maximum to store the compressed squashfs block. Finally I decided to implement the parallel single-call LZMA decompression. The parallel decompression is also applied to ZLIB decompression. It also requires more memory than multi-call ZLIB decompression, but less than multi-call LZMA decompression. And it can take an advantage of speed performance, especially on SMP machine. o Backporting A user, dystryk, had backported this patch (previous version) to linux-2.6.17. His URL is, https://sourceforge.net/project/showfiles.php?group_id=116780&package_id=222970 Enjoy your smaller squashfs. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqlzma1-449.patch ================================================ Index: lzma449/C/Compress/Lzma/kmod.mk =================================================================== RCS file: lzma449/C/Compress/Lzma/kmod.mk diff -N lzma449/C/Compress/Lzma/kmod.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/kmod.mk 5 Nov 2007 05:43:35 -0000 1.1 @@ -0,0 +1,40 @@ + +# Copyright (C) 2006-2007 Junjiro Okajima +# Copyright (C) 2006-2007 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: kmod.mk,v 1.1 2007-11-05 05:43:35 jro Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif +ifndef KDir +$(error KDir is not defined) +endif + +#include makefile.gcc + +Kmod = kmod +EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} +# -D_LZMA_PROB32 +EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) + +all: ${Kmod}/uncomp.c + ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ + -C ${KDir} C=0 V=0 modules + +${Kmod}/uncomp.c: uncomp.c + ln $< $@ + +clean: clean_kmod +clean_kmod: + ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean + ${RM} ${Kmod}/*~ + -@test -e ${Kmod}/uncomp.c && \ + diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ + find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: lzma449/C/Compress/Lzma/sqlzma.mk =================================================================== RCS file: lzma449/C/Compress/Lzma/sqlzma.mk diff -N lzma449/C/Compress/Lzma/sqlzma.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/sqlzma.mk 5 Nov 2007 05:43:36 -0000 1.1 @@ -0,0 +1,47 @@ + +# Copyright (C) 2006-2007 Junjiro Okajima +# Copyright (C) 2006-2007 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + +#include makefile.gcc +CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 + +ifdef KDir +include kmod.mk +endif + +ifdef UseDebugFlags +DebugFlags = -O0 -g -UNDEBUG +endif +CFLAGS += -DNDEBUG ${DebugFlags} +Tgt = libunlzma.a libunlzma_r.a + +all: ${Tgt} + +%_r.c: %.c + ln $< $@ +# -pthread +%_r.o: CFLAGS += -D_REENTRANT -include pthread.h + +uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} +uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h + +libunlzma.a: uncomp.o LzmaDecode.o + ${AR} cr $@ $^ +libunlzma_r.a: uncomp_r.o LzmaDecode_r.o + ${AR} cr $@ $^ + +clean: clean_sqlzma +clean_sqlzma: + $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o LzmaDecode.o *~ + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: lzma449/C/Compress/Lzma/testflags.c =================================================================== RCS file: lzma449/C/Compress/Lzma/testflags.c diff -N lzma449/C/Compress/Lzma/testflags.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/testflags.c 5 Nov 2007 05:43:36 -0000 1.1 @@ -0,0 +1,5 @@ +#ifdef _LZMA_PROB32 +-D_LZMA_PROB32 +#else +-U_LZMA_PROB32 +#endif Index: lzma449/C/Compress/Lzma/uncomp.c =================================================================== RCS file: lzma449/C/Compress/Lzma/uncomp.c diff -N lzma449/C/Compress/Lzma/uncomp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/uncomp.c 12 Mar 2008 16:58:34 -0000 1.7 @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2006-2008 Junjiro Okajima + * Copyright (C) 2006-2008 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ + +/* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ + +#ifndef __KERNEL__ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <pthread.h> +#define unlikely(x) __builtin_expect(!!(x), 0) +#define BUG_ON(x) assert(!(x)) +/* sqlzma buffers are always larger than a page. true? */ +#define kmalloc(sz,gfp) malloc(sz) +#define kfree(p) free(p) +#define zlib_inflate(s, f) inflate(s, f) +#define zlib_inflateInit(s) inflateInit(s) +#define zlib_inflateReset(s) inflateReset(s) +#define zlib_inflateEnd(s) inflateEnd(s) +#else +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/vmalloc.h> +#ifndef WARN_ON_ONCE +#define WARN_ON_ONCE(b) WARN_ON(b) +#endif +#endif /* __KERNEL__ */ + +#include "sqlzma.h" +#include "LzmaDecode.h" + +static int LzmaUncompress(struct sqlzma_un *un) +{ + int err, i, ret; + SizeT outSize, inProcessed, outProcessed, srclen; + /* it's about 24-80 bytes structure, if int is 32-bit */ + CLzmaDecoderState state; + unsigned char *dst, *src, a[8]; + struct sized_buf *sbuf; + + /* Decode LZMA properties and allocate memory */ + err = -EINVAL; + src = (void *)un->un_cmbuf; + ret = LzmaDecodeProperties(&state.Properties, src, + LZMA_PROPERTIES_SIZE); + src += LZMA_PROPERTIES_SIZE; + if (unlikely(ret != LZMA_RESULT_OK)) + goto out; + i = LzmaGetNumProbs(&state.Properties); + if (unlikely(i <= 0)) + i = 1; + i *= sizeof(CProb); + sbuf = un->un_a + SQUN_PROB; + if (unlikely(sbuf->sz < i)) { + if (sbuf->buf && sbuf->buf != un->un_prob) + kfree(sbuf->buf); +#ifdef __KERNEL__ + printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); +#else + printf("%d --> %d\n", sbuf->sz, i); +#endif + err = -ENOMEM; + sbuf->sz = 0; + sbuf->buf = kmalloc(i, GFP_ATOMIC); + if (unlikely(!sbuf->buf)) + goto out; + sbuf->sz = i; + } + state.Probs = (void *)sbuf->buf; + + /* Read uncompressed size */ + memcpy(a, src, sizeof(a)); + src += sizeof(a); + outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); + + err = -EINVAL; + dst = un->un_resbuf; + if (unlikely(!dst || outSize > un->un_reslen)) + goto out; + un->un_reslen = outSize; + srclen = un->un_cmlen - (src - un->un_cmbuf); + + /* Decompress */ + err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, + &outProcessed); + if (unlikely(err)) + err = -EINVAL; + + out: +#ifndef __KERNEL__ + if (err) + fprintf(stderr, "err %d\n", err); +#endif + return err; +} + +int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, + struct sized_buf *dst) +{ + int err, by_lzma = 1; + if (un->un_lzma && is_lzma(*src->buf)) { + un->un_cmbuf = src->buf; + un->un_cmlen = src->sz; + un->un_resbuf = dst->buf; + un->un_reslen = dst->sz; + + /* this library is thread-safe */ + err = LzmaUncompress(un); + goto out; + } + + by_lzma = 0; + err = zlib_inflateReset(&un->un_stream); + if (unlikely(err != Z_OK)) + goto out; + un->un_stream.next_in = src->buf; + un->un_stream.avail_in = src->sz; + un->un_stream.next_out = dst->buf; + un->un_stream.avail_out = dst->sz; + err = zlib_inflate(&un->un_stream, Z_FINISH); + if (err == Z_STREAM_END) + err = 0; + + out: + if (unlikely(err)) { +#ifdef __KERNEL__ + WARN_ON_ONCE(1); +#else + char a[64] = "ZLIB "; + if (by_lzma) { + strcpy(a, "LZMA "); +#ifdef _REENTRANT + strerror_r(err, a + 5, sizeof(a) - 5); +#else + strncat(a, strerror(err), sizeof(a) - 5); +#endif + } else + strncat(a, zError(err), sizeof(a) - 5); + fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); +#endif + } + return err; +} + +int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) +{ + int err; + + err = -ENOMEM; + un->un_lzma = do_lzma; + memset(un->un_a, 0, sizeof(un->un_a)); + un->un_a[SQUN_PROB].buf = un->un_prob; + un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); + if (res_sz) { + un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); + if (unlikely(!un->un_a[SQUN_RESULT].buf)) + return err; + un->un_a[SQUN_RESULT].sz = res_sz; + } + + un->un_stream.next_in = NULL; + un->un_stream.avail_in = 0; +#ifdef __KERNEL__ + un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), + GFP_KERNEL); + if (unlikely(!un->un_stream.workspace)) + return err; +#else + un->un_stream.opaque = NULL; + un->un_stream.zalloc = Z_NULL; + un->un_stream.zfree = Z_NULL; +#endif + err = zlib_inflateInit(&un->un_stream); + if (unlikely(err == Z_MEM_ERROR)) + return -ENOMEM; + BUG_ON(err); + return err; +} + +void sqlzma_fin(struct sqlzma_un *un) +{ + int i; + for (i = 0; i < SQUN_LAST; i++) + if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) + kfree(un->un_a[i].buf); + BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); +} + +#ifdef __KERNEL__ +EXPORT_SYMBOL(sqlzma_un); +EXPORT_SYMBOL(sqlzma_init); +EXPORT_SYMBOL(sqlzma_fin); + +#if 0 +static int __init sqlzma_init(void) +{ + return 0; +} + +static void __exit sqlzma_exit(void) +{ +} + +module_init(sqlzma_init); +module_exit(sqlzma_exit); +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junjiro Okajima <sfjro at users dot sf dot net>"); +MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); +MODULE_DESCRIPTION("LZMA uncompress for squashfs. " + "Some functions for squashfs to support LZMA and " + "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); +#endif Index: lzma449/C/Compress/Lzma/kmod/Makefile =================================================================== RCS file: lzma449/C/Compress/Lzma/kmod/Makefile diff -N lzma449/C/Compress/Lzma/kmod/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/kmod/Makefile 12 Mar 2008 01:49:39 -0000 1.3 @@ -0,0 +1,16 @@ + +# Copyright (C) 2006-2008 Junjiro Okajima +# Copyright (C) 2006-2008 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: Makefile,v 1.3 2008-03-12 01:49:39 jro Exp $ + +# # the environment variables are not inherited since 2.6.23 +# ifdef SQLZMA_EXTRA_CFLAGS +# EXTRA_CFLAGS += ${SQLZMA_EXTRA_CFLAGS} +# endif + +obj-m += unlzma.o sqlzma.o +unlzma-y := module.o +sqlzma-y := uncomp.o Index: lzma449/C/Compress/Lzma/kmod/module.c =================================================================== RCS file: lzma449/C/Compress/Lzma/kmod/module.c diff -N lzma449/C/Compress/Lzma/kmod/module.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/C/Compress/Lzma/kmod/module.c 5 Nov 2007 05:43:36 -0000 1.1 @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2006-2007 Junjiro Okajima + * Copyright (C) 2006-2007 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: module.c,v 1.1 2007-11-05 05:43:36 jro Exp $ */ + +#include <linux/init.h> +#include <linux/module.h> + +#include "../LzmaDecode.c" + +EXPORT_SYMBOL(LzmaDecodeProperties); +EXPORT_SYMBOL(LzmaDecode); + +#if 0 +static int __init unlzma_init(void) +{ + return 0; +} + +static void __exit unlzma_exit(void) +{ +} + +module_init(unlzma_init); +module_exit(unlzma_exit); +#endif + +MODULE_LICENSE("GPL"); +MODULE_VERSION("$Id: module.c,v 1.1 2007-11-05 05:43:36 jro Exp $"); +MODULE_DESCRIPTION("LZMA uncompress. " + "A tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); Index: lzma449/CPP/7zip/Compress/LZMA_Alone/comp.cc =================================================================== RCS file: lzma449/CPP/7zip/Compress/LZMA_Alone/comp.cc diff -N lzma449/CPP/7zip/Compress/LZMA_Alone/comp.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/CPP/7zip/Compress/LZMA_Alone/comp.cc 13 Nov 2007 13:27:23 -0000 1.3 @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2006-2007 Junjiro Okajima + * Copyright (C) 2006-2007 Tomas Matejicek, slax.org + * + * LICENSE follows the described one in lzma.txt. + */ + +/* $Id: comp.cc,v 1.3 2007-11-13 13:27:23 jro Exp $ */ + +// extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +#include "StdAfx.h" +#include "../../../Common/MyInitGuid.h" +//#include "../../../Common/MyWindows.h" +#include "../../../Common/StringConvert.h" +//#include "../../../Common/StringToInt.h" +//#include "../../Common/StreamUtils.h" +#include "../LZMA/LZMAEncoder.h" + +#include <pthread.h> +#include <zlib.h> +#include "sqlzma.h" + +////////////////////////////////////////////////////////////////////// + +class CMemoryStream { +protected: + Bytef *m_data; + UInt64 m_limit; + UInt64 m_pos; + +public: + CMemoryStream(Bytef *data, UInt64 size) + : m_data(data), m_limit(size), m_pos(0) {} + + virtual ~CMemoryStream() {} +}; + +class CInMemoryStream : public CMemoryStream, public IInStream, + public CMyUnknownImp { +//protected: + CMyComPtr<ISequentialInStream> m_stream; + +public: + MY_UNKNOWN_IMP1(IInStream); + + CInMemoryStream(Bytef *data, UInt64 size) + : CMemoryStream(data, size), m_stream(this) {} + + virtual ~CInMemoryStream() {} + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) + { + UInt64 room = m_limit - m_pos; + if (size > room) + size = room; + if (size) { + memcpy(data, m_data + m_pos, size); + m_pos += size; + } + if (processedSize) + *processedSize = size; + return S_OK; + } + + // disabled all + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { + assert(0); + return E_NOTIMPL; + } +}; + +class COutMemoryStream : public CMemoryStream, public IOutStream, + public CMyUnknownImp { +//protected: + CMyComPtr<ISequentialOutStream> m_stream; + +public: + MY_UNKNOWN_IMP1(IOutStream); + + COutMemoryStream(Bytef *data, UInt64 size) + : CMemoryStream(data, size), m_stream(this) {} + + virtual ~COutMemoryStream() {} + + UInt32 GetSize() {return m_pos;} + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { + if (m_pos + size > m_limit) + return -ENOSPC; + memcpy(m_data + m_pos, data, size); + m_pos += size; + if (processedSize) + *processedSize = size; + return S_OK; + } + + // disabled all + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { + assert(0); + return E_NOTIMPL; + } + STDMETHOD(SetSize)(Int64 newSize) { + assert(0); + return E_NOTIMPL; + } +}; + +////////////////////////////////////////////////////////////////////// + +static int +LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, + struct sqlzma_opts *opts, uLong *total_out) +{ + int err; + HRESULT res; + const Byte a[] = { + avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, + 0, 0, 0, 0 + }; + + NCompress::NLZMA::CEncoder encoderSpec; + CMyComPtr<ICompressCoder> encoder = &encoderSpec; + encoder->AddRef(); + CInMemoryStream inStreamSpec(next_in, avail_in); + CMyComPtr<ISequentialInStream> inStream = &inStreamSpec; + inStream->AddRef(); + COutMemoryStream outStreamSpec(next_out, avail_out); + CMyComPtr<ISequentialOutStream> outStream = &outStreamSpec; + outStream->AddRef(); + + // these values are dpending upon is_lzma() macro in sqlzma.h + const UInt32 dictionary = opts->dicsize; + //fprintf(stderr, "dic %u\n", dictionary); + const UString mf = L"BT4"; + const UInt32 posStateBits = 2; + const UInt32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + const UInt32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + //const UInt32 algorithm = 2; + const UInt32 algorithm = 1; + const UInt32 numFastBytes = 128; + const UInt32 matchFinderCycles = 16 + numFastBytes / 2; + //const bool matchFinderCyclesDefined = false; + const PROPID propIDs[] = { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker, + NCoderPropID::kNumThreads, + NCoderPropID::kMatchFinderCycles + }; + const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT properties[kNumPropsMax]; + for (int p = 0; p < 6; p++) + properties[p].vt = VT_UI4; + properties[0].ulVal = UInt32(dictionary); + properties[1].ulVal = UInt32(posStateBits); + properties[2].ulVal = UInt32(litContextBits); + properties[3].ulVal = UInt32(litPosBits); + properties[4].ulVal = UInt32(algorithm); + properties[5].ulVal = UInt32(numFastBytes); + + properties[6].vt = VT_BSTR; + properties[6].bstrVal = (BSTR)(const wchar_t *)mf; + properties[7].vt = VT_BOOL; + properties[7].boolVal = VARIANT_FALSE; // EOS + properties[8].vt = VT_UI4; + properties[8].ulVal = 1; // numThreads + properties[9].vt = VT_UI4; + properties[9].ulVal = UInt32(matchFinderCycles); + + err = -EINVAL; + res = encoderSpec.SetCoderProperties(propIDs, properties, + kNumPropsMax - 1); + if (res) + goto out; + res = encoderSpec.WriteCoderProperties(outStream); + if (res) + goto out; + + UInt32 r; + res = outStream->Write(a, sizeof(a), &r); + if (res || r != sizeof(a)) + goto out; + + err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); + if (err) + goto out; + *total_out = outStreamSpec.GetSize(); + + out: + return err; +} + +////////////////////////////////////////////////////////////////////// + +#define Failure(p) do { \ + fprintf(stderr, "%s:%d: please report to jro " \ + "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ + __func__, __LINE__, \ + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ + abort(); \ +} while(0) + +extern "C" int +sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt + avail_in, Bytef *next_out, uInt avail_out) +{ + int err; + Bytef *p = next_out; + uInt l = avail_out; + + stream->next_in = next_in; + stream->avail_in = avail_in; + stream->next_out = p; + stream->avail_out = l; + err = deflate(stream, Z_FINISH); + if (err != Z_STREAM_END && err != Z_OK) + goto out_err; + if (avail_in < stream->total_out) + return err; + if (is_lzma(*p)) + Failure(p); + + if (opts->try_lzma) { + unsigned char a[stream->total_out]; + uLong processed; + + memcpy(a, p, stream->total_out); + + // malloc family in glibc and stdc++ seems to be thread-safe + err = LzmaCompress(next_in, avail_in, p, l, opts, &processed); + if (!err && processed <= stream->total_out) { + if (!is_lzma(*next_out)) + Failure(next_out); + stream->total_out = processed; + err = Z_STREAM_END; + } else { + //puts("by zlib"); + memcpy(p, a, stream->total_out); + err = Z_STREAM_END; + } + } + return err; + + out_err: + fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); + return err; +} Index: lzma449/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk =================================================================== RCS file: lzma449/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk diff -N lzma449/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lzma449/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk 5 Nov 2007 05:43:36 -0000 1.1 @@ -0,0 +1,57 @@ + +# Copyright (C) 2006-2007 Junjiro Okajima +# Copyright (C) 2006-2007 Tomas Matejicek, slax.org +# +# LICENSE follows the described one in lzma.txt. + +# $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ + +ifndef Sqlzma +$(error Sqlzma is not defined) +endif + +include makefile.gcc + +ifdef UseDebugFlags +DebugFlags = -Wall -O0 -g -UNDEBUG +endif +# -pthread +CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} +Tgt = liblzma_r.a + +all: ${Tgt} + +RObjs = LZMAEncoder_r.o Alloc_r.o StreamUtils_r.o MatchFinder_r.o \ + RangeCoderBit_r.o OutBuffer_r.o 7zCrc_r.o + +%_r.cc: ../LZMA/%.cpp + ln $< $@ +%_r.c: ../../../../C/%.c + ln $< $@ +%_r.c: ../../../../C/Compress/Lz/%.c + ln $< $@ +%_r.cc: ../../Common/%.cpp + ln $< $@ +%_r.cc: ../RangeCoder/%.cpp + ln $< $@ +LZMAEncoder_r.o: CXXFLAGS += -I../LZMA +Alloc_r.o: CFLAGS += -I../../../../C +StreamUtils_r.o: CXXFLAGS += -I../../Common +MatchFinder_r.o: CFLAGS += -I../../../../C/Compress/Lz +RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder +OutBuffer_r.o: CXXFLAGS += -I../../Common +7zCrc_r.o: CFLAGS += -I../../../../C + +comp.o: CXXFLAGS += -I${Sqlzma} +comp.o: comp.cc ${Sqlzma}/sqlzma.h + +liblzma_r.a: ${RObjs} comp.o + ${AR} cr $@ $^ + +clean: clean_sqlzma +clean_sqlzma: + $(RM) comp.o *_r.o ${Tgt} *~ + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqlzma2k-3.3.patch ================================================ Index: linux-2.6.24.3/fs/squashfs/Makefile =================================================================== RCS file: /proj/sqlzma/repository/linux-2.6.24.3/fs/squashfs/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- linux-2.6.24.3/fs/squashfs/Makefile 12 Mar 2008 14:18:02 -0000 1.1 +++ linux-2.6.24.3/fs/squashfs/Makefile 12 Mar 2008 14:49:49 -0000 1.2 @@ -2,6 +2,11 @@ # Makefile for the linux squashfs routines. # +# the environment variables are not inherited since 2.6.23 +ifdef SQLZMA_EXTRA_CFLAGS +EXTRA_CFLAGS += ${SQLZMA_EXTRA_CFLAGS} +endif + obj-$(CONFIG_SQUASHFS) += squashfs.o squashfs-y += inode.o squashfs-y += squashfs2_0.o Index: linux-2.6.24.3/fs/squashfs/inode.c =================================================================== RCS file: /proj/sqlzma/repository/linux-2.6.24.3/fs/squashfs/inode.c,v retrieving revision 1.1 retrieving revision 1.8 diff -u -p -r1.1 -r1.8 --- linux-2.6.24.3/fs/squashfs/inode.c 12 Mar 2008 14:18:02 -0000 1.1 +++ linux-2.6.24.3/fs/squashfs/inode.c 14 Mar 2008 13:53:27 -0000 1.8 @@ -34,8 +34,30 @@ #include <linux/exportfs.h> #include "squashfs.h" +#include "sqlzma.h" +#include "sqmagic.h" -int squashfs_cached_blks; +#undef KeepPreemptive +#if defined(CONFIG_PREEMPT) && !defined(UnsquashNoPreempt) +#define KeepPreemptive +#endif + +struct sqlzma { +#ifdef KeepPreemptive + struct mutex mtx; +#endif + unsigned char read_data[SQUASHFS_FILE_MAX_SIZE]; + struct sqlzma_un un; +}; +static DEFINE_PER_CPU(struct sqlzma *, sqlzma); + +#define dpri(fmt, args...) /* printk("%s:%d: " fmt, __func__, __LINE__, ##args) */ +#define dpri_un(un) dpri("un{%d, {%d %p}, {%d %p}, {%d %p}}\n", \ + (un)->un_lzma, (un)->un_a[0].sz, (un)->un_a[0].buf, \ + (un)->un_a[1].sz, (un)->un_a[1].buf, \ + (un)->un_a[2].sz, (un)->un_a[2].buf) + +static int squashfs_cached_blks; static void vfs_read_inode(struct inode *i); static struct dentry *squashfs_get_parent(struct dentry *child); @@ -243,35 +265,42 @@ SQSH_EXTERN unsigned int squashfs_read_d } if (compressed) { - int zlib_err = 0; + int zlib_err = Z_STREAM_END; + int start; + enum {Src, Dst}; + struct sized_buf sbuf[2]; + struct sqlzma *percpu; + unsigned char *p; /* * uncompress block */ - mutex_lock(&msblk->read_data_mutex); - - msblk->stream.next_out = buffer; - msblk->stream.avail_out = srclength; - - for (bytes = 0; k < b; k++) { - avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + /* mutex_lock(&msblk->read_data_mutex); */ + start = k; + for (; k < b; k++) { wait_on_buffer(bh[k]); if (!buffer_uptodate(bh[k])) goto release_mutex; + } - msblk->stream.next_in = bh[k]->b_data + offset; - msblk->stream.avail_in = avail_bytes; + /* it disables preemption */ + percpu = get_cpu_var(sqlzma); +#ifdef KeepPreemptive + put_cpu_var(sqlzma); + mutex_lock(&percpu->mtx); +#endif + p = percpu->read_data; + k = start; + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); if (k == 0) { - zlib_err = zlib_inflateInit(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflateInit returned unexpected result 0x%x," - " srclength %d\n", zlib_err, srclength); - goto release_mutex; - } - + /* + * keep this block structture to simplify the + * diff. + */ if (avail_bytes == 0) { offset = 0; brelse(bh[k]); @@ -279,30 +308,38 @@ SQSH_EXTERN unsigned int squashfs_read_d } } - zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); - if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { - ERROR("zlib_inflate returned unexpected result 0x%x," - " srclength %d, avail_in %d, avail_out %d\n", zlib_err, - srclength, msblk->stream.avail_in, msblk->stream.avail_out); - goto release_mutex; - } + memcpy(p, bh[k]->b_data + offset, avail_bytes); + p += avail_bytes; +#if 0 + BUG_ON(percpu->read_data + sizeof(percpu->read_data) + < p); +#endif bytes += avail_bytes; offset = 0; brelse(bh[k]); } - if (zlib_err != Z_STREAM_END) - goto release_mutex; - - zlib_err = zlib_inflateEnd(&msblk->stream); - if (zlib_err != Z_OK) { - ERROR("zlib_inflateEnd returned unexpected result 0x%x," - " srclength %d\n", zlib_err, srclength); + sbuf[Src].buf = percpu->read_data; + sbuf[Src].sz = bytes; + sbuf[Dst].buf = buffer; + sbuf[Dst].sz = srclength; + dpri_un(&percpu->un); + dpri("src %d %p, dst %d %p\n", sbuf[Src].sz, sbuf[Src].buf, + sbuf[Dst].sz, sbuf[Dst].buf); + zlib_err = sqlzma_un(&percpu->un, sbuf + Src, sbuf + Dst); + bytes = percpu->un.un_reslen; + +#ifdef KeepPreemptive + mutex_unlock(&percpu->mtx); +#else + put_cpu_var(sqlzma); +#endif + if (unlikely(zlib_err)) { + dpri("zlib_err %d\n", zlib_err); goto release_mutex; } - bytes = msblk->stream.total_out; - mutex_unlock(&msblk->read_data_mutex); + /* mutex_unlock(&msblk->read_data_mutex); */ } else { int i; @@ -330,7 +367,7 @@ SQSH_EXTERN unsigned int squashfs_read_d return bytes; release_mutex: - mutex_unlock(&msblk->read_data_mutex); + /* mutex_unlock(&msblk->read_data_mutex); */ block_release: for (; k < b; k++) @@ -1089,12 +1126,13 @@ static int squashfs_fill_super(struct su { struct squashfs_sb_info *msblk; struct squashfs_super_block *sblk; - int i; + int i, err; char b[BDEVNAME_SIZE]; struct inode *root; TRACE("Entered squashfs_fill_superblock\n"); + err = -ENOMEM; s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); if (s->s_fs_info == NULL) { ERROR("Failed to allocate superblock\n"); @@ -1102,17 +1140,12 @@ static int squashfs_fill_super(struct su } msblk = s->s_fs_info; - msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); - if (msblk->stream.workspace == NULL) { - ERROR("Failed to allocate zlib workspace\n"); - goto failure; - } sblk = &msblk->sblk; msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); msblk->devblksize_log2 = ffz(~msblk->devblksize); - mutex_init(&msblk->read_data_mutex); + /* mutex_init(&msblk->read_data_mutex); */ mutex_init(&msblk->read_page_mutex); mutex_init(&msblk->block_cache_mutex); mutex_init(&msblk->fragment_mutex); @@ -1124,6 +1157,7 @@ static int squashfs_fill_super(struct su /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not * beyond filesystem end. As we're using squashfs_read_data to read sblk here, * first set sblk->bytes_used to a useful value */ + err = -EINVAL; sblk->bytes_used = sizeof(struct squashfs_super_block); if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, sizeof(struct squashfs_super_block) | @@ -1133,21 +1167,36 @@ static int squashfs_fill_super(struct su } /* Check it is a SQUASHFS superblock */ - if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { - if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { - struct squashfs_super_block ssblk; - - WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", - bdevname(s->s_bdev, b)); - - SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); - memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); - msblk->swap = 1; - } else { - SERROR("Can't find a SQUASHFS superblock on %s\n", - bdevname(s->s_bdev, b)); - goto failed_mount; - } + s->s_magic = sblk->s_magic; + msblk->swap = 0; + dpri("magic 0x%x\n", sblk->s_magic); + switch (sblk->s_magic) { + struct squashfs_super_block ssblk; + + case SQUASHFS_MAGIC_SWAP: + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA_SWAP: + WARNING("Mounting a different endian SQUASHFS " + "filesystem on %s\n", bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC: + case SQUASHFS_MAGIC_LZMA: + break; + default: + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + + { + struct sqlzma *p; + dpri("block_size %d, devblksize %d\n", + sblk->block_size, msblk->devblksize); + BUG_ON(sblk->block_size > sizeof(p->read_data)); } /* Check the MAJOR & MINOR versions */ @@ -1191,6 +1240,7 @@ static int squashfs_fill_super(struct su goto failed_mount; /* Allocate read_page block */ + err = -ENOMEM; msblk->read_page = vmalloc(sblk->block_size); if (msblk->read_page == NULL) { ERROR("Failed to allocate read_page block\n"); @@ -1206,19 +1256,30 @@ static int squashfs_fill_super(struct su } msblk->guid = msblk->uid + sblk->no_uids; + dpri("swap %d\n", msblk->swap); + err = -EINVAL; if (msblk->swap) { - unsigned int suid[sblk->no_uids + sblk->no_guids]; + unsigned int *suid; + + err = -ENOMEM; + suid = kmalloc(sizeof(*suid) * (sblk->no_uids + sblk->no_guids), + GFP_KERNEL); + if (unlikely(!suid)) + goto failed_mount; + err = -EINVAL; if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, ((sblk->no_uids + sblk->no_guids) * sizeof(unsigned int)) | SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { ERROR("unable to read uid/gid table\n"); + kfree(suid); goto failed_mount; } SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + sblk->no_guids), (sizeof(unsigned int) * 8)); + kfree(suid); } else if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, ((sblk->no_uids + sblk->no_guids) * @@ -1232,6 +1293,7 @@ static int squashfs_fill_super(struct su if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) goto allocate_root; + err = -ENOMEM; msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); if (msblk->fragment == NULL) { @@ -1261,9 +1323,12 @@ static int squashfs_fill_super(struct su s->s_export_op = &squashfs_export_ops; allocate_root: + dpri("alloate_root\n"); root = new_inode(s); - if ((msblk->read_inode)(root, sblk->root_inode) == 0) + if ((msblk->read_inode)(root, sblk->root_inode) == 0) { + iput(root); goto failed_mount; + } insert_inode_hash(root); s->s_root = d_alloc_root(root); @@ -1284,13 +1349,10 @@ failed_mount: vfree(msblk->read_page); kfree(msblk->block_cache); kfree(msblk->fragment_index_2); - vfree(msblk->stream.workspace); kfree(s->s_fs_info); s->s_fs_info = NULL; - return -EINVAL; - -failure: - return -ENOMEM; + failure: + return err; } @@ -1301,7 +1363,7 @@ static int squashfs_statfs(struct dentry TRACE("Entered squashfs_statfs\n"); - buf->f_type = SQUASHFS_MAGIC; + buf->f_type = sblk->s_magic; buf->f_bsize = sblk->block_size; buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; buf->f_bfree = buf->f_bavail = 0; @@ -1463,15 +1525,21 @@ static int read_block_index(struct super int block = 0; if (msblk->swap) { - char sblock_list[blocks << 2]; + char *sblock_list; + + sblock_list = kmalloc(blocks << 2, GFP_KERNEL); + if (unlikely(!sblock_list)) + goto failure; if (!squashfs_get_cached_block(s, sblock_list, *start_block, *offset, blocks << 2, start_block, offset)) { ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + kfree(sblock_list); goto failure; } SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ((unsigned int *)sblock_list), blocks); + kfree(sblock_list); } else { if (!squashfs_get_cached_block(s, block_list, *start_block, *offset, blocks << 2, start_block, offset)) { @@ -2103,7 +2171,6 @@ static void squashfs_put_super(struct su kfree(sbi->fragment_index); kfree(sbi->fragment_index_2); kfree(sbi->meta_index); - vfree(sbi->stream.workspace); kfree(s->s_fs_info); s->s_fs_info = NULL; } @@ -2117,19 +2184,63 @@ static int squashfs_get_sb(struct file_s mnt); } +static void free_sqlzma(void) +{ + int cpu; + struct sqlzma *p; + + for_each_online_cpu(cpu) { + p = per_cpu(sqlzma, cpu); + if (p) { +#ifdef KeepPreemptive + mutex_destroy(&p->mtx); +#endif + sqlzma_fin(&p->un); + kfree(p); + } + } +} static int __init init_squashfs_fs(void) { + struct sqlzma *p; + int cpu; int err = init_inodecache(); if (err) goto out; + for_each_online_cpu(cpu) { + dpri("%d: %p\n", cpu, per_cpu(sqlzma, cpu)); + err = -ENOMEM; + p = kmalloc(sizeof(struct sqlzma), GFP_KERNEL); + if (p) { +#ifdef KeepPreemptive + mutex_init(&p->mtx); +#endif + err = sqlzma_init(&p->un, 1, 0); + if (unlikely(err)) { + ERROR("Failed to intialize uncompress workspace\n"); + break; + } + per_cpu(sqlzma, cpu) = p; + err = 0; + } else + break; + } + if (unlikely(err)) { + free_sqlzma(); + goto out; + } + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " - "Phillip Lougher\n"); + "Phillip Lougher\n" + "squashfs: LZMA suppport for slax.org by jro\n"); err = register_filesystem(&squashfs_fs_type); - if (err) + if (err) { + free_sqlzma(); destroy_inodecache(); + } out: return err; @@ -2139,6 +2250,7 @@ out: static void __exit exit_squashfs_fs(void) { unregister_filesystem(&squashfs_fs_type); + free_sqlzma(); destroy_inodecache(); } @@ -2187,6 +2299,6 @@ static void destroy_inodecache(void) module_init(init_squashfs_fs); module_exit(exit_squashfs_fs); -MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); -MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem, and LZMA suppport for slax.org"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>, and LZMA suppport for slax.org by jro"); MODULE_LICENSE("GPL"); Index: linux-2.6.24.3/include/linux/squashfs_fs.h =================================================================== RCS file: /proj/sqlzma/repository/linux-2.6.24.3/include/linux/squashfs_fs.h,v retrieving revision 1.1 retrieving revision 1.3 diff -u -p -r1.1 -r1.3 --- linux-2.6.24.3/include/linux/squashfs_fs.h 12 Mar 2008 14:18:13 -0000 1.1 +++ linux-2.6.24.3/include/linux/squashfs_fs.h 14 Mar 2008 04:53:33 -0000 1.3 @@ -341,7 +341,7 @@ struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; - int inode_number:16; + signed int inode_number:16; /* very important signedness */ char name[0]; } __attribute__ ((packed)); Index: linux-2.6.24.3/include/linux/squashfs_fs_sb.h =================================================================== RCS file: /proj/sqlzma/repository/linux-2.6.24.3/include/linux/squashfs_fs_sb.h,v retrieving revision 1.1 retrieving revision 1.5 diff -u -p -r1.1 -r1.5 --- linux-2.6.24.3/include/linux/squashfs_fs_sb.h 12 Mar 2008 14:18:13 -0000 1.1 +++ linux-2.6.24.3/include/linux/squashfs_fs_sb.h 14 Mar 2008 13:53:27 -0000 1.5 @@ -54,7 +54,7 @@ struct squashfs_sb_info { long long *fragment_index; unsigned int *fragment_index_2; char *read_page; - struct mutex read_data_mutex; + /* struct mutex read_data_mutex; */ struct mutex read_page_mutex; struct mutex block_cache_mutex; struct mutex fragment_mutex; @@ -62,7 +62,7 @@ struct squashfs_sb_info { wait_queue_head_t waitq; wait_queue_head_t fragment_wait_queue; struct meta_index *meta_index; - z_stream stream; + /* z_stream stream; */ long long *inode_lookup_table; int unused_cache_blks; int unused_frag_blks; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqlzma2u-3.3.patch ================================================ Index: squashfs3.3/squashfs-tools/Makefile =================================================================== RCS file: /proj/sqlzma/repository/squashfs3.3/squashfs-tools/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.3/squashfs-tools/Makefile 4 Nov 2007 13:19:11 -0000 1.1 +++ squashfs3.3/squashfs-tools/Makefile 5 Nov 2007 05:43:36 -0000 1.2 @@ -1,19 +1,42 @@ -INCLUDEDIR = . -CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 +ifndef Sqlzma +$(error Sqlzma is not defined) +endif -all: mksquashfs unsquashfs +INCLUDEDIR = . -mksquashfs: mksquashfs.o read_fs.o sort.o - $(CC) mksquashfs.o read_fs.o sort.o -lz -lpthread -lm -o $@ +CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 +ifdef UseDebugFlags +DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG +endif +CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} +LDLIBS += -lz -L${LzmaAlone} -L${LzmaC} +Tgt = mksquashfs unsquashfs -mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h +all: ${Tgt} -read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h +read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h +mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ + ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a +mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ +mksquashfs: mksquashfs.o read_fs.o sort.o + +unsquashfs.o: CFLAGS += -U_REENTRANT +unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ + ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a +unsquashfs: LDLIBS += -lunlzma unsquashfs: unsquashfs.o - $(CC) unsquashfs.o -lz -o $@ -unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h +clean: + ${RM} *~ *.o ${Tgt} + +-include test.mk + +# Local variables: ; +# compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); +# End: ; Index: squashfs3.3/squashfs-tools/mksquashfs.c =================================================================== RCS file: /proj/sqlzma/repository/squashfs3.3/squashfs-tools/mksquashfs.c,v retrieving revision 1.1 retrieving revision 1.8 diff -u -p -r1.1 -r1.8 --- squashfs3.3/squashfs-tools/mksquashfs.c 4 Nov 2007 13:19:11 -0000 1.1 +++ squashfs3.3/squashfs-tools/mksquashfs.c 14 Mar 2008 13:53:27 -0000 1.8 @@ -61,6 +61,8 @@ #include "mksquashfs.h" #include "global.h" #include "sort.h" +#include "sqlzma.h" +#include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ @@ -112,6 +114,11 @@ unsigned short uid_count = 0, guid_count squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; +struct sqlzma_un un; +struct sqlzma_opts sqlzma_opts = { + .try_lzma = 1, + .dicsize = SQUASHFS_FILE_SIZE +}; /* write position within data section */ long long bytes = 0, total_bytes = 0; @@ -626,21 +633,8 @@ unsigned int mangle2(z_stream **strm, ch BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } - stream->next_in = (unsigned char *) s; - stream->avail_in = size; - stream->next_out = (unsigned char *) d; - stream->avail_out = block_size; - - res = deflate(stream, Z_FINISH); - if(res != Z_STREAM_END && res != Z_OK) { - if(res == Z_STREAM_ERROR) - BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::compress failed, no progress possible\n"); - else - BAD_ERROR("zlib::compress failed, unknown error %d\n", res); - } - + res = sqlzma_cm(&sqlzma_opts, stream, (void *)s, size, (void *)d, + block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { @@ -991,12 +985,12 @@ int create_inode(squashfs_inode *i_no, s char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { - ERROR("Failed to read symlink %d, creating empty symlink\n", filename); + ERROR("Failed to read symlink %s, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { - ERROR("Symlink %d is greater than 65536 bytes! Creating empty symlink\n", filename); + ERROR("Symlink %s is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } @@ -1022,7 +1016,7 @@ int create_inode(squashfs_inode *i_no, s SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else - BAD_ERROR("Unrecognised inode %d in create_inode\n"); + BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; @@ -1250,17 +1244,17 @@ char *get_fragment(char *buffer, struct int res; unsigned long bytes = block_size; char cbuffer[block_size]; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = (void *)cbuffer, .sz = size}, + {.buf = (void *)buffer, .sz = bytes} + }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); - if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { - if(res == Z_MEM_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); - } + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); } else read_bytes(fd, disk_fragment->start_block, size, buffer); @@ -1755,6 +1749,7 @@ void *reader(void *arg) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } + return NULL; } @@ -1926,7 +1921,7 @@ int progress_bar(long long current, long int spaces = columns - used - hashes; if(!progress || columns - used < 0) - return; + return 0; printf("\r["); @@ -1939,6 +1934,7 @@ int progress_bar(long long current, long printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); + return 0; } @@ -2635,7 +2631,7 @@ error: void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { - int squashfs_type; + int squashfs_type = -1; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; @@ -3242,7 +3238,8 @@ void read_recovery_data(char *recovery_f printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n");\ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; @@ -3261,6 +3258,7 @@ int main(int argc, char *argv[]) be = FALSE; #endif + un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); @@ -3319,24 +3317,33 @@ int main(int argc, char *argv[]) ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } - } else if(strcmp(argv[i], "-b") == 0) { + } else if(strcmp(argv[i], "-b") == 0 + || strcmp(argv[i], "-lzmadic") == 0) { + long bs; + unsigned int bl; if(++i == argc) { - ERROR("%s: -b missing block size\n", argv[0]); + ERROR("%s: -b|-lzmadic missing block size\n", argv[0]); exit(1); } - block_size = strtol(argv[i], &b, 10); + bs = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') - block_size *= 1048576; + bs *= 1048576; else if(*b == 'k' || *b == 'K') - block_size *= 1024; + bs *= 1024; else if(*b != '\0') { - ERROR("%s: -b invalid block size\n", argv[0]); + ERROR("%s: -b|-lzmadic invalid size\n", argv[0]); exit(1); } - if((block_log = slog(block_size)) == 0) { - ERROR("%s: -b block size not power of two or not between 4096 and 1Mbyte\n", argv[0]); + bl = slog(bs); + if(bl == 0) { + ERROR("%s: -b|-lzmadic size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } + if (!strcmp(argv[i - 1], "-b")) { + block_size = bs; + block_log = bl; + } + sqlzma_opts.dicsize = bs; } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); @@ -3440,6 +3447,9 @@ int main(int argc, char *argv[]) exit(1); } root_name = argv[i]; + } else if(strcmp(argv[i], "-nolzma") == 0) { + un.un_lzma = 0; + sqlzma_opts.try_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { @@ -3489,6 +3499,12 @@ printOptions: ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); + ERROR("-lzmadic <dic_size>\tset the LZMA dictionary" + " size to <dic_size>\n" + "\t\t\tDefault value always follow the block" + " size\n" + "\t\t\tUse this alone or AFTER -b option\n"); + ERROR("-nolzma\t\t\tnever try LZMA compression\n"); exit(1); } } @@ -3595,6 +3611,7 @@ printOptions: be = orig_be; block_log = slog(block_size = sBlk.block_size); + //sqlzma_opts.dicsize = block_size; s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); @@ -3608,10 +3625,18 @@ printOptions: initialise_threads(); + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + ERROR("%s:%d: %d\n", __func__, __LINE__, i); + EXIT_MKSQUASHFS(); + } + if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); + if (sqlzma_opts.try_lzma) + printf("lzmadic %u\n", sqlzma_opts.dicsize); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, @@ -3635,6 +3660,8 @@ printOptions: printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); + if (sqlzma_opts.try_lzma) + printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); @@ -3733,7 +3760,9 @@ printOptions: dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; - sBlk.s_magic = SQUASHFS_MAGIC; + sBlk.s_magic = SQUASHFS_MAGIC_LZMA; + if (!un.un_lzma) + sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; @@ -3819,6 +3848,8 @@ restore_filesystem: exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); + if (sqlzma_opts.try_lzma) + printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); Index: squashfs3.3/squashfs-tools/read_fs.c =================================================================== RCS file: /proj/sqlzma/repository/squashfs3.3/squashfs-tools/read_fs.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.3/squashfs-tools/read_fs.c 4 Nov 2007 13:19:11 -0000 1.1 +++ squashfs3.3/squashfs-tools/read_fs.c 5 Nov 2007 05:43:36 -0000 1.2 @@ -46,6 +46,8 @@ extern int add_file(long long, long long #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include <stdlib.h> @@ -62,6 +64,7 @@ extern int add_file(long long, long long } while(0) int swap; +extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { @@ -81,19 +84,20 @@ int read_block(int fd, long long start, char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = (void *)buffer}, + {.buf = (void *)block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); - if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -351,18 +355,30 @@ int read_super(int fd, squashfs_super_bl /* Check it is a SQUASHFS superblock */ swap = 0; - if(sBlk->s_magic != SQUASHFS_MAGIC) { - if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); - memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } - } + switch (sBlk->s_magic) { + squashfs_super_block sblk; + + case SQUASHFS_MAGIC_LZMA: + if (!un.un_lzma) + goto bad; + break; + case SQUASHFS_MAGIC: + break; + case SQUASHFS_MAGIC_LZMA_SWAP: + if (!un.un_lzma) + goto bad; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); + memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + break; + bad: + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; + } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { @@ -416,7 +432,7 @@ unsigned char *squashfs_readdir(int fd, squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; - long long start = sBlk->directory_table_start + directory_start_block, last_start_block; + long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) Index: squashfs3.3/squashfs-tools/sort.c =================================================================== RCS file: /proj/sqlzma/repository/squashfs3.3/squashfs-tools/sort.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- squashfs3.3/squashfs-tools/sort.c 4 Nov 2007 13:19:11 -0000 1.1 +++ squashfs3.3/squashfs-tools/sort.c 5 Nov 2007 05:43:36 -0000 1.2 @@ -74,7 +74,7 @@ struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; -extern write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); +extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) Index: squashfs3.3/squashfs-tools/unsquashfs.c =================================================================== RCS file: /proj/sqlzma/repository/squashfs3.3/squashfs-tools/unsquashfs.c,v retrieving revision 1.1 retrieving revision 1.6 diff -u -p -r1.1 -r1.6 --- squashfs3.3/squashfs-tools/unsquashfs.c 4 Nov 2007 13:19:11 -0000 1.1 +++ squashfs3.3/squashfs-tools/unsquashfs.c 14 Mar 2008 13:53:27 -0000 1.6 @@ -52,6 +52,8 @@ #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" +#include "sqlzma.h" +#include "sqmagic.h" #include <stdlib.h> #include <time.h> @@ -131,6 +133,7 @@ unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; +struct sqlzma_un un; int lookup_type[] = { 0, @@ -199,6 +202,8 @@ int print_filename(char *pathname, struc return 1; } + /* printf("i%d ", inode->inode_number); */ + if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; @@ -318,21 +323,21 @@ int read_block(long long start, long lon char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = (void *)buffer}, + {.buf = (void *)block, .sz = bytes} + }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) buffer, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - goto failed; - } + sbuf[Src].sz = c_byte; + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; @@ -359,20 +364,19 @@ int read_data_block(long long start, uns TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { + enum {Src, Dst}; + struct sized_buf sbuf[] = { + {.buf = (void *)data, .sz = c_byte}, + {.buf = (void *)block, .sz = bytes} + }; + if(read_bytes(start, c_byte, data) == FALSE) return 0; - if((res = uncompress((unsigned char *) block, &bytes, - (const unsigned char *) data, c_byte)) != Z_OK) { - if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough memory\n"); - else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough room in output buffer\n"); - else - ERROR("zlib::uncompress failed, unknown error %d\n", res); - return 0; - } - + res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); + if (res) + abort(); + bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) @@ -921,7 +925,7 @@ int create_inode(char *pathname, struct set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else - ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", + ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } @@ -1775,19 +1779,27 @@ int read_super(char *source) read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ + un.un_lzma = 1; swap = 0; - if(sBlk.s_magic != SQUASHFS_MAGIC) { - if(sBlk.s_magic == SQUASHFS_MAGIC_SWAP) { - squashfs_super_block sblk; - ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); - SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); - memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); - swap = 1; - } else { - ERROR("Can't find a SQUASHFS superblock on %s\n", source); - goto failed_mount; - } - } + switch (sBlk.s_magic) { + squashfs_super_block sblk; + case SQUASHFS_MAGIC: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA: + break; + case SQUASHFS_MAGIC_SWAP: + un.un_lzma = 0; + /*FALLTHROUGH*/ + case SQUASHFS_MAGIC_LZMA_SWAP: + ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); + SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); + memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); + swap = 1; + default: + ERROR("Can't find a SQUASHFS superblock on %s\n", source); + goto failed_mount; + } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { @@ -1857,7 +1869,8 @@ struct pathname *process_extract_files(s printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ - printf("GNU General Public License for more details.\n"); + printf("GNU General Public License for more details.\n");\ + printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; @@ -1957,6 +1970,11 @@ options: EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); + i = sqlzma_init(&un, un.un_lzma, 0); + if (i != Z_OK) { + fputs("sqlzma_init failed", stderr); + abort(); + } read_uids_guids(); ================================================ FILE: src/others/squashfs-3.3-grml-lzma/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.2 2006-11-27 03:54:58 jro Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/ACKNOWLEDGEMENTS ================================================ ACKNOWLEDGEMENTS Thanks to everyone who have download squashfs. I appreciate people using it, and any feedback you have. The following have provided useful feedback, which has guided some of the extra features in squashfs. This is a randomly ordered (roughly in chronological order) list, which is updated when I remember... Acknowledgements for Squashfs-3.3 ------------------------------------ Peter Korsgaard and others sent patches updating Squashfs to changes in the VFS interface for 2.6.22/2.6.23/2.6.24-rc1. Peter also sent some small patches for the Squashfs kernel code. Vito Di Leo sent a patch extending Mksquashfs to support regex filters. While his patched worked, it unfortunately made it easy to make Mksquashfs perform unpredictably with poorly choosen regex expressions. It, however, encouraged myself to add support for wildcard pattern matching and regex filters in a different way. Acknowledgements for Squashfs-3.2-r2 ------------------------------------ Junjiro Okajima discovered a couple of SMP issues, thanks. Junjiro Okajima and Tomas Matejicek have produced some good LZMA patches for Squashfs. Acknowledgements for Squashfs-3.2 --------------------------------- Peter Korsgaard sent a patch updating Squashfs to changes in the VFS interface in Linux 2.6.20. Acknowledgements for Squashfs-3.1 --------------------------------- Kenneth Duda and Ed Swierk of Arastra Inc. identified numerous bugs with Squashfs, and provided patches which were the basis for some of the fixes. In particular they identified the fragment rounding bug, the NFS bug, the initrd bug, and helped identify the 4K stack overflow bug. Scott James Remnant (Ubuntu) also identified the fragment rounding bug, and he also provided a patch. Ming Zhang identified the Lseek bug in Mksquashfs. His tests on the performance of Mksquashfs on SMP systems encouraged the rewrite of Mksquashfs. Peter Korsgaard, Daniel Olivera and Zilvinas Valinskas noticed Squashfs 3.0 didn't compile on Linux-2.6.18-rc[1-4] due to changes in the Linux VFS interfaces, and provided patches. Tomas Matejicek (SLAX) suggested the -force option on Unsquashfs, and noticed Unsquashfs didn't return the correct exit status. Yann Le Doare reported a kernel oops and provided a Qemu image that led to the identification of the simultaneously accessing multiply mounted Squashfs filesystems bug. Older acknowledgements ---------------------- Mark Robson - pointed out early on that initrds didn't work Adam Warner - pointed out that greater than 2GB filesystems didn't work. John Sutton - raised the problem when archiving the entire filesystem (/) there was no way to prevent /proc being archived. This prompted exclude files. Martin Mueller (LinuxTV) - noticed that the filesystem length in the superblock doesn't match the output filesystem length. This is due to padding to a 4K boundary. This prompted the addition of the -nopad option. He also reported a problem where 32K block filesystems hung when used as initrds. Arkadiusz Patyk (Polish Linux Distribution - PLD) reported a problem where 32K block filesystems hung when used as a root filesystem mounted as a loopback device. Joe Blow emailed me that I'd forgotten to put anything in the README about mounting the squashfs filesystem. David Fox (Lindows) noticed that the exit codes returned by Mksquashfs were wrong. He also noticed that a lot of time was spent in the duplicate scan routine. Cameron Rich complained that Squashfs did not support FIFOs or sockets. Steve Chadsey and Thomas Weissmuller noticed that files larger than the available memory could not be compressed by Mksquashfs. "Ptwahyu" and "Hoan" (I have no full names and I don't like giving people's email addresses), noticed that Mksquashfs 1.3 SEGV'd occasionally. Even though I had already noticed this bug, it is useful to be informed by other people. Don Elwell, Murray Jensen and Cameron Rich, have all sent in patches. Thanks, I have not had time to do anything about them yet... Drew Scott Daniels has been a good advocate for Squashfs. Erik Andersen has made some nice suggestions, unfortunately, I have not had time to implement anything. Artemiy I. Pavlov has written a useful LDP mini-howto for Squashfs (http://linuxdoc.artemio.net/squashfs). Yves Combe reported the Apple G5 bug, when using Squashfs for his PPC Knoppix-mib livecd project. Jaco Greeff (mklivecd project, and maintainer of the Mandrake squashfs-tools package) suggested the new mksquashfs -ef option, and the standalone build for mksquashfs. Mike Schaudies made a donation. Arkadiusz Patyk from the Polish Linux Distribution reported that Squashfs didn't work on amd64 machines. He gave me an account on a PLD amd64 machine which allowed myself to track down these bugs. Miles Roper, Peter Kjellerstedt and Willy Tarreau reported that release 2.1 did not compile with gcc < 3.x. Marcel J.E. Mol reported lack of kernel memory issues when using Squashfs on small memory embedded systems. This prompted the addition of the embedded system kernel configuration options. Era Scarecrow noticed that Mksquashfs had not been updated to reflect that smaller than 4K blocks are no longer supported. Kenichi Shima reported the Kconfig file had not been updated to 2.2. Aaron Ten Clay made a donation! Tomas Matejicek (SLAX) made a donation! ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/CHANGES ================================================ SQUASHFS CHANGE LOG 3.3 1 NOV 2007 Increase in block size, sparse file support, Mksquashfs and Unsquashfs extended to use pattern matching in exclude/extract files, plus many more improvements and bug fixes. 1. Filesystem improvements: 1.1. Maximum block size has been increased to 1Mbyte, and the default block size has been increased to 128 Kbytes. This improves compression. 1.2. Sparse files are now supported. Sparse files are files which have large areas of unallocated data commonly called holes. These files are now detected by Squashfs and stored more efficiently. This improves compression and read performance for sparse files. 2. Mksquashfs improvements: 2.1. Exclude files have been extended to use wildcard pattern matching and regular expressions. Support has also been added for non-anchored excludes, which means it is now possible to specify excludes which match anywhere in the filesystem (i.e. leaf files), rather than always having to specify exclude files starting from the root directory (anchored excludes). 2.2. Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). 3. Unsquashfs improvements: 3.1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. 3.2. Extract files have been extended to use wildcard pattern matching and regular expressions. 3.3. Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). 3.4. A -stat option has been added which displays the filesystem superblock information. 3.5. Unsquashfs now supports 1.x filesystems. 4. Miscellaneous improvements/bug fixes: 4.1. Squashfs kernel code improved to use SetPageError in squashfs_readpage() if I/O error occurs. 4.2. Fixed Squashfs kernel code bug preventing file seeking beyond 2GB. 4.3. Mksquashfs now detects file size changes between first phase directory scan and second phase filesystem create. It also deals better with file I/O errors. 3.2-r2 15 JAN 2007 Kernel patch update and progress bar bug fix 1. Kernel patches 2.6.19/2.6.20 have been updated to use const structures and mutexes rather than older semaphores. 2. Minor SMP bug fixes. 3. Progress bar broken on x86-64. Fixed. 3.2 2 JAN 2007 NFS support, improvements to the Squashfs-tools, major bug fixes, lots of small improvements/bug fixes, and new kernel patches. Improvements: 1. Squashfs filesystems can now be exported via NFS. 2. Unsquashfs now supports 2.x filesystems. 3. Mksquashfs now displays a progress bar. 4. Squashfs kernel code has been hardened against accidently or maliciously corrupted Squashfs filesystems. Bug fixes: 5. Race condition occurring on S390 in readpage() fixed. 6. Odd behaviour of MIPS memcpy in read_data() routine worked-around. 7. Missing cache_flush in Squashfs symlink_readpage() added. 3.1-r2 30 AUG 2006 Mksquashfs -sort bug fix A code optimisation after testing unfortunately broke sorting in Mksquashfs. This has been fixed. 3.1 19 AUG 2006 This release has some major improvements to the squashfs-tools, a couple of major bug fixes, lots of small improvements/bug fixes, and new kernel patches. 1. Mksquashfs has been rewritten to be multi-threaded. It has the following improvements 1.1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 1.2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 1.3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 1.4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 1.5 The use of swap memory was found to significantly impact performance. The amount of memory used to cache files is now a command line option, by default this is 512 Mbytes. 2. Unsquashfs has the following improvements 2.1 Unsquashfs now allows you to specify the filename or the directory within the Squashfs filesystem that is to be extracted, rather than always extracting the entire filesystem. 2.2 A new -force option has been added which forces Unsquashfs to output to the destination directory even if files and directories already exist in the destination directory. This allows you to update an already existing directory tree, or to Unsquashfs to a partially filled directory tree. Without the -force option Unsquashfs will refuse to output. 3. The following major bug fixes have been made 3.1 A fragment table rounding bug has been fixed in Mksquashfs. Previously if the number of fragments in the filesystem were a multiple of 512, Mksquashfs would generate an incorrect filesystem. 3.2 A rare SMP bug which occurred when simultaneously acccessing multiply mounted Squashfs filesystems has been fixed. 4. Miscellaneous improvements/bug fixes 4.1 Kernel code stack usage has been reduced. This is to ensure Squashfs works with 4K stacks. 4.2 Readdir (Squashfs kernel code) has been fixed to always return 0, rather than the number of directories read. Squashfs should now interact better with NFS. 4.3 Lseek bug in Mksquashfs when appending to larger than 4GB filesystems fixed. 4.4 Squashfs 2.x initrds can now been mounted. 4.5 Unsquashfs exit status fixed. 4.6 New patches for linux-2.6.18 and linux-2.4.33. 3.0 15 MAR 2006 Major filesystem improvements 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). 2.2-r2 8 SEPT 2005 Second release of 2.2, this release fixes a couple of small bugs, a couple of small documentation mistakes, and adds a patch for kernel 2.6.13. 1. Mksquashfs now deletes the output filesystem image file if an error occurs whilst generating the filesystem. Previously on error the image file was left empty or partially written. 2. Updated mksquashfs so that it doesn't allow you to generate filesystems with block sizes smaller than 4K. Squashfs hasn't supported block sizes less than 4K since 2.0-alpha. 3. Mksquashfs now ignores missing files/directories in sort files. This was the original behaviour before 2.2. 4. Fixed small mistake in fs/Kconfig where the version was still listed as 2.0. 5. Updated ACKNOWLEDGEMENTS file. 2.2 3 JUL 2005 This release has some small improvements, bug fixes and patches for new kernels. 1. Sort routine re-worked and debugged from release 2.1. It now allows you to give Mkisofs style sort files and checks for filenames that don't match anything. Sort priority has also been changed to conform to Mkisofs usage, highest priority files are now placed at the start of the filesystem (this means they will be on the inside of a CD or DVD). 2. New Configure options for embedded systems (memory constrained systems). See INSTALL file for further details. 3. Directory index bug fixed where chars were treated as signed on some architectures. A file would not be found in the rare case that the filename started with a chracter greater than 127. 4. Bug introduced into the read_data() routine when sped up to use data block queueing fixed. If the second or later block resulted in an I/O error this was not checked. 5. Append bug introduced in 2.1 fixed. The code to compute the new compressed and uncompressed directory parts after appending was wrong. 6. Metadata block length read routine altered to not perform a misaligned short read. This was to fix reading on an ARM7 running uCLinux without a misaligned read interrupt handler. 7. Checkdata bug introduced in 2.1 fixed. 2.1-r2 15 DEC 2004 Code changed so it can be compiled with gcc 2.x 1. In some of the code added for release 2.1 I unknowingly used some gcc extensions only supported by 3.x compilers. I have received a couple of reports that the 2.1 release doesn't build on 2.x and so people are clearly still using gcc 2.x. The code has been rewritten to remove these extensions. 2.1 10 DEC 2004 Significantly improved directory handling plus numerous other smaller improvements 1. Fast indexed directories implemented. These speed up directory operations (ls, file lookup etc.) significantly for directories larger than 8 KB. 2. All directories are now sorted in alphabetical order. This again speeds up directory operations, and in some cases it also results in a small compression improvement (greater data similarity between files with alphabetically similar names). 3. Maximum directory size increased from 512 KB to 128 MB. 4. Duplicate fragment checking and appending optimised in mksquashfs, depending on filesystem, this is now up to 25% faster. 5. Mksquashfs help information reformatted and reorganised. 6. The Squashfs version and release date is now printed at kernel boot-time or module insertion. This addition will hopefully help to reduce the growing problem where the Squashfs version supported by a kernel is unknown and the kernel source is unavailable. 7. New PERFORMANCE.README file. 8. New -2.0 mksquashfs option. 9. CHANGES file reorganised. 10. README file reorganised, clarified and updated to include the 2.0 mksquashfs options. 11. New patch for Linux 2.6.9. 12. New patch for Linux 2.4.28. 2.0r2 29 AUG 2004 Workaround for kernel bug in kernels 2.6.8 and newer added 1. New patch for kernel 2.6.8.1. This includes a workaround for a kernel bug introduced in 2.6.7bk14, which is present in all later versions of the kernel. If you're using a 2.6.8 kernel or later then you must use this 2.6.8.1 patch. If you've experienced hangs or oopses using Squashfs with a 2.6.8 or later kernel then you've hit this bug, and this patch will fix it. It is worth mentioning that this kernel bug potentially affects other filesystems. If you receive odd results with other filesystems you may be experiencing this bug with that filesystem. I submitted a patch but this has not yet gone into the kernel, hopefully the bug will be fixed in later kernels. 2.0 13 JULY 2004 A couple of new options, and some bug fixes 1. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 2. Initrds are now supported for kernels 2.6.x. 3. amd64 bug fixes. If you use an amd64, please read the README-AMD64 file. 4. Check-data and gid bug fixes. With 2.0-alpha when mounting 1.x filesystems in certain cases file gids were corrupted. 5. New patch for Linux 2.6.7. 2.0-ALPHA 21 MAY 2004 Filesystem changes and compression improvements 1. Squashfs 2.0 has added the concept of fragment blocks. Files smaller than the file block size and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K (in the ALPHA version of Squashfs 2.0). 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 6. Numerous small bug fixes have been made. 1.3r3 18 JAN 2004 Third release of 1.3, this adds a new mksquashfs option, some bug fixes, and extra patches for new kernels 1. New mksquashfs -ef exclude option. This option reads the exclude dirs/files from an exclude file, one exclude dir/file per line. This avoids the command line size limit when using the -e exclude option, 2. When appending to existing filesystems, if mksquashfs experiences a fatal error (e.g. out of space when adding to the destination), the original filesystem is restored, 3. Mksquashfs now builds standalone, without the kernel needing to be patched. 4. Bug fix in the kernel squashfs filesystem, where the pages being filled were not kmapped. This seems to only have caused problems on an Apple G5, 5. New patch for Linux 2.4.24, 6. New patch for Linux 2.6.1, this replaces the patch for 2.6.0-test7. 1.3r2 14 OCT 2003 Second release of 1.3, bug fixes and extra patches for new kernels 1. Bug fix in routine that adds files to the filesystem being generated in mksquashfs. This bug was introduced in 1.3 (not enough testing...) when I rewrote it to handle files larger than available memory. This bug caused a SEGV, so if you've ever got that, it is now fixed, 2. Long running bug where ls -s and du reported wrong block size fixed. I'm pretty sure this used to work many kernel versions ago (2.4.7) but it broke somewhere along the line since then, 3. New patch for Linux 2.4.22, 4. New patch for 2.6.0-test7, this replaces the patch for 2.6.0-test1. 1.3 29 JUL 2003 FIFO/Socket support added plus optimisations and improvements 1. FIFOs and Socket inodes are now supported, 2. Mksquashfs can now compress files larger than available memory, 3. File duplicate check routine optimised, 4. Exit codes fixed in Mksquashfs, 5. Patch for Linux 2.4.21, 6. Patch for Linux 2.6.0-test1. Hopefully, this will work for the next few releases of 2.6.0-testx, otherwise, I'll be releasing a lot of updates to the 2.6.0 patch... 1.2 13 MAR 2003 Append feature and new mksquashfs options added Mksquashfs can now add to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. See the README file for usage changes. 1.1b 16 JAN 2003 Bug fix release Fixed readpage deadlock bug. This was a rare deadlock bug that happened when pushing pages into the page cache when using greater than 4K blocks. I never got this bug when I tested the filesystem, but two people emailed me on the same day about the problem! I fixed it by using a page cache function that wasn't there when I originally did the work, which was nice :-) 1.1 8 JAN 2003 Added features 1. Kernel squashfs can now mount different byte order filesystems. 2. Additional features added to mksquashfs. Mksquashfs now supports exclude files and multiple source files/directories can be specified. A nopad option has also been added, which informs mksquashfs not to pad filesystems to a multiple of 4K. See README for mksquashfs usage changes. 3. Greater than 2GB filesystems bug fix. Filesystems greater than 2GB can now be created. 1.0c 14 NOV 2002 Bug fix release Fixed bugs with initrds and device nodes 1.0 23 OCT 2002 Initial release ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) 19yy <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/INSTALL ================================================ INSTALLING SQUASHFS The squashfs3.3.tar.gz file contains this file, a README-3.3 file, another README file, an ACKNOWLEDGEMENTS file, a CHANGES file, the kernel-patches directory containing the squashfs patches, and the squashfs-tools directory (mksquashfs and unsquashfs). 1. Patching the kernel ---------------------- There are eleven kernel patch directories depending on your linux kernel version. If your kernel version isn't listed then try the patch for the nearest kernel listed. To patch your kernel, cd into the top level directory, and run the "patch" command, e.g. assuming linux-2.6.22 %cd /usr/src/linux-2.6.22 %patch -p1 < location-of-squashfs/kernel-patches/linux-2.6.22/squashfs3.3-patch Where "location-of-squashfs" is the path to the squashfs3.3 source directory. The squashfs patches patch the relevant kernel files to add configure support, initrd support, include files, and the squashfs directory under linux/fs/. Once patched, the kernel must be reconfigured, with squashfs support turned on (either Y/M) to ensure that inflate support is built into the kernel. The squashfs kernel option can be found in the miscellaneous filesystems submenu near the bottom of the filesystems submenu. There are a set of options which are intended for use by embedded systems with low memory. At the "Additional option for memory-constrained systems" prompt, please say NO unless you're using an embedded system! Saying Y here allows you to specify cache sizes. The "Number of fragments cached" prompt allows the number of fragments cached to be controlled. By default SquashFS caches the last 3 fragments read from the filesystem. Increasing this amount may mean SquashFS has to re-read fragments less often from disk, at the expense of extra system memory. Decreasing this amount will mean SquashFS uses less memory at the expense of extra reads from disk. Note there must be at least one cached fragment. Anything much more than three will probably not make much difference. 2. Building squashfs tools -------------------------- The squashfs-tools directory contains the mksquashfs and unsquashfs programs. These can be made by typing make. The source files use a local copy of squashfs_fs.h (included in the kernel patches) allowing the tools to be made without needing to patch the kernel. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-2.0 ================================================ NOTE: This the original README for version 2.0. It is retained as it contains information about the fragment design. A description of the new 2.0 mksquashfs options has been added to the main README file, and that file should now be consulted for these. SQUASHFS 2.0 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to the final release of Squashfs version 2.0! A lot of changes to the filesystem have been made under the bonnet (hood). Squashfs 2.0 uses fragment blocks and larger blocks (64K) to improve compression ratio by about 5 - 20% over Squashfs 1.0 depending on the files being compressed. Using fragment blocks allows Squashfs 2.0 to achieve better compression than cloop and similar compression to tgz files while retaining the I/O efficiency of a compressed filesystem. Detailed changes: 1. Squashfs 2.0 has added the concept of fragment blocks (see later discussion). Files smaller than the file block size (64K in Squashfs 2.0) and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K. 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 6. Initrds are now supported for kernels 2.6.x. 7. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 8. AMD64, check-data and gid bug fixes. 9. Numerous small bug fixes have been made. 10. New patch for Linux 2.6.7. New Squashfs 2.0 options ------------------------ -noF or -noFragmentCompression Do not compress the fragments. Added for compatibility with noI and noD, probably not that useful. -no-fragments Do not use fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. -always-use-fragments By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. -no-duplicates Do not detect duplicate files. -all-root -root-owned These options (both do exactly the same thing), force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. -force-uid uid This option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. -force-gid gid This option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. Compression improvements example -------------------------------- The following is the compression results obtained compressing the 2.6.6 linux kernel source using CRAMFS, Cloop (with iso filesystem), Squashfs 1.3 and Squashfs 2.0 (results generated using big-endian filesystems). In decreasing order of size: CRAMFS 62791680 bytes (59.9M) Squashfs 1.x 51351552 bytes (48.9M) Cloop 46118681 bytes (44.0M) Squashfs 2.0 45604854 bytes (43.5M) The Squashfs 1.x filesystem is 12.6% larger than the new 2.0 filesystem. The cloop filesystem is 1.1% larger than the Squashfs 2.0 filesystem. Fragment blocks in Squashfs 2.0 ------------------------------- Squashfs like all other compressed filesystems compresses files individually on a block by block basis. This is performed to allow mounting and de-compression of files on a block by block basis without requiring the entire filesystem to be decompressed. This is in contrast to data-based compression schemes which compress without understanding the underlying filesystem (i.e. cloop and tgz files) and which, therefore, do not compress files individually. Each approach has advantages and disadvantages, data-based systems have better compression because compression is always performed at the maximum block size (64K in cloop) irrespective of the size of each file (which could be less than the block size). Compressed filesystems tend to be faster at I/O because they understand the filesystem and therefore employ better caching stategies and read less un-needed data from the filesystem. Fragment blocks in Squashfs 2.0 solves this problem by packing files (and optionally the ends of files) which are smaller than the block size into shared blocks, which are compressed together. For example five files each of 10K will be packed into one shared fragment of 50K and compressed together, rather than being compressed in five 10K blocks. This scheme produces a hybrid filesystem, retaining the I/O efficiency of a compressed filesystem, while obtaining the compression efficiency of data-based schemes by compressing small files together. Squashfs 1.x and Squashfs 2.0 compatibility ------------------------------------------- Appending to Squashfs 1.x filesystems is not supported. If you wish to append to 1.x filesystems, then either use the original mksquashfs, or convert them to Squashfs 2.0 by mounting the filesystem and running the 2.0 mksquashfs on the mounted filesystem. Mounting Squashfs 1.x filesystems IS supported by the 2.0 kernel patch. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-2.1 ================================================ SQUASHFS 2.1 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to Squashfs version 2.1-r2. Squashfs 2.1 introduces indexed directories which considerably speed up directory lookup (ls, find etc.) for directories which are greater than 8K in size. All directories are now also sorted alphabetically which further speeds up directory lookup. Many smaller improvements have also been made to this release, please see the CHANGES file entry for detailed changes. 1. DIRECTORY SPEED IMPROVEMENT EXAMPLES --------------------------------------- To give an indication of the directory speed improvements a number of test results are shown here. There is in addition a new PERFORMANCE.README file which gives details of I/O and lookup performance for Squashfs 2.1 against the Zisofs, Cloop and CRAMFS filesystems. example 1: Filesystems generated from a single directory of 72,784 files (2.6 MB directory size). Each file is 10 bytes in size (the test is directory lookup and so the file size isn't an issue). The ext3 uncompressed directory size is 288 MB (presumably because of one file per block). Zisofs compressed size 153.50 MB Cloop (isofs) compressed size 1.74 MB Squashfs2.1 compressed size 612 KB (0.60 MB) Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 35 minutes 7.895 seconds (User 7.868 secs, Sys 34 mins 5.621 secs) Cloop 35 minutes 12.765 seconds (User 7.771 secs, Sys 34 mins 3.869 secs) Squashfs2.1 19 seconds (User 5.119 secs, Sys 14.547 secs) example 2: Filesystems were generated from the Ubuntu Warty livecd (original uncompressed size on ext3 is 1.4 GB). Zisofs compressed size 589.81 MB Cloop (isofs) compressed size 471.19 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 49.875 seconds (User time 2.589 secs, Sys 11.194 secs) Cloop 20.797 seconds (User time 2.706 secs, Sys 13.496 secs) Squashfs2.0 16.556 seconds (User time 2.424 secs, Sys 10.371 secs) Squashfs2.1 10.143 seconds (User time 2.475 secs, Sys 4.440 secs) NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 2. NEW MKSQUASHFS OPTIONS ------------------------- There is only one extra option "-2.0". This tells mksquashfs to generate a filesystem which is mountable with Squashfs version 2.0. 3. APPENDING AND MOUNTING SQUASHFS 2.0 FILESYSTEMS -------------------------------------------------- Mounting 2.0 filesystems is supported by Squashfs 2.1. In addition mksquashfs v2.1 can append to 2.0 filesystems, although the generated filesystem will still be a 2.0 filesystem. 4. DONATIONS ------------ If you find Squashfs useful then please consider making a donation, particularly if you use Squashfs in a commercial product. Please consider giving something back especially if you're making money from it. Off the Squashfs subject somewhat I'm currently looking for another job doing Linux kernel or filesystems work. If you know of any such work that can be performed from the UK then please get in touch. Thanks. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-3.0 ================================================ SQUASHFS 3.0 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to the first release of Squashfs version 3.0. Squashfs 3.0 has the the following improvements to 2.x. 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). There is a new Unsquashfs utility (in squashfs-tools) than can be used to decompress a filesystem without mounting it. Squashfs 3.0 supports 2.x filesystems. Support for 1.x filesystems will be added in the future. 1. UNSQUASHFS ------------- Unsquashfs has the following options: SYNTAX: unsquashfs [-ls | -dest] filesystem -version print version, licence and copyright information -info print files as they are unsquashed -ls list filesystem only -dest <pathname> unsquash to <pathname>, default "squashfs-root" The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. Unsquashfs can decompress 3.0 filesystems. Support for 2.x and 1.x filesystems will be added in the future. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-3.1 ================================================ SQUASHFS 3.1 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.1-r2. Squashfs 3.1 has major improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- Mksquashfs has been rewritten and it is now multi-threaded. It offers the following improvements: 1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 5. The use of swap memory was found to significantly impact performance. The amount of memory used to cache the file is now a command line option, by default this is 512 Mbytes. 1.1 NEW COMMAND LINE OPTIONS ---------------------------- The new Mksquashfs program has a couple of extra command line options which can be used to control the new features: -processors <processors> This specifies the number of processors used by Mksquashfs. By default this is the number of available processors. -read_queue <size in Mbytes> This specifies the size of the file input queue used by the reader thread. This defaults to 64 Mbytes. -write_queue <size in Mbytes> This specifies the size of the filesystem output queue used by the writer thread. It also specifies the maximum cache used in file duplicate detection (the output queue is shared between these tasks). This defaults to 512 Mbytes. 1.2 PERFORMANCE RESULTS ----------------------- The following results give an indication of the speed improvements. Two example filesystems were tested, a liveCD filesystem (about 1.8 Gbytes uncompressed), and my home directory consisting largely of text files (about 1.3 Gbytes uncompressed). Tests were run on a single core and a dual core system. Dual Core (AMDx2 3800+) system: Source directories on ext3. LiveCD, old mksquashfs: real 11m48.401s user 9m27.056s sys 0m15.281s LiveCD, new par_mksquashfs: real 4m8.736s user 7m11.771s sys 0m27.749s "Home", old mksquashfs: real 4m34.360s user 3m54.007s sys 0m32.155s "Home", new par_mksquashfs: real 1m27.381s user 2m7.304s sys 0m17.234s Single Core PowerBook (PowerPC G4 1.5 GHz Ubuntu Linux) Source directories on ext3. LiveCD, old mksquashs: real 11m38.472s user 9m6.137s sys 0m23.799s LiveCD, par_mksquashfs: real 10m5.572s user 8m59.921s sys 0m16.145s "Home", old mksquashfs: real 3m42.298s user 2m49.478s sys 0m13.675s "Home", new par_mksquashfs: real 3m9.178s user 2m50.699s sys 0m9.069s I'll be interested in any performance results obtained, especially from SMP machines larger than my dual-core AMD box, as this will give an indication of the scalability of the code. Obviously, I'm also interested in any problems, deadlocks, low performance etc. 2. UNSQUASHFS ------------- Unsquashfs now allows you to specify the filename or directory that is to be extracted from the Squashfs filesystem, rather than always extracting the entire filesystem. It also has a new "-force" option, and all options can be specified in a short form (-i rather than -info). The Unsquashfs usage info is now: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The new "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-3.2 ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Squashfs 3.2 has support for NFS exporting, some improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- New command line options: -no-exports Squashfs now supports NFS exports. By default the additional information necessary is added to the filesystem by Mksquashfs. If you do not wish this extra information, then this option can be specified. This will save a couple of bytes per file, and the filesystem will be identical to Squashfs 3.1. -no-progress Mksquashfs by default now displays a progress bar. This option disables it. 2. UNSQUASHFS ------------- Unsquashfs now supports Squashfs 2.x filesystems. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/OLD-READMEs/README-AMD64 ================================================ Information for amd64 users --------------------------- All releases of Squashfs prior to 2.0 generate incorrect filesystems on amd64 machines. Filesystems created on amd64 machines work correctly on amd64 machines, but cannot be mounted on non-amd64 machines. Likewise, filesystems created on non-amd64 machines cannot be mounted on amd64 machines. This bug is caused by the different size of the "time_t" definition used in SquashFS filesystem structures. This bug is fixed in releases 2.0 and newer. However, all amd64 filesystems generated by previous releases will not be mountable on amd64 machines with newer releases. If you have amd64 filesystems generated with mksquashfs version 2.0-alpha or older, it is important that you recreate the filesystem. This can be performed by mounting the filesystem using a kernel with the original patch (i.e. a 2.0-alpha or older patch) and running the NEW (i.e. this release) mksquashfs tool to create a new SquashFS filesystem. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/PERFORMANCE.README ================================================ GENERAL INFORMATION ON PERFORMANCE TESTS ---------------------------------------- The following performance tests were based on two file sets: the liveCD filesystem from the Ubuntu liveCD (Warty release), and the liveCD filesystem from the Damn Small Linux liveCD (release 0.8.4). The Ubuntu liveCD filesystem was used to test filesystem performance from CDROM and hard disk for Zisofs, Cloop, Squashfs 2.0 and Squashfs2.1. CRAMFS filesystem performance could not be tested for this filesystem bacause it exceeds the maximum supported size of CRAMFS. To test CRAMFS performance against Squashfs, the liveCD filesystem from Damn Small Linux was used. NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 1. Ubuntu liveCD performance tests ext3 uncompressed size 1.4 GB Zisofs compressed size 589.81 MB Cloop compressed size 471.89 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB 1.1 Performance tests from CDROM 1.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM Zisofs 49.88 seconds (User 2.60 secs, Sys 11.19 secs) Cloop 20.80 seconds (User 2.71 secs, Sys 13.50 secs) Squashfs2.0 16.56 seconds (User 2.42 secs, Sys 10.37 secs) Squashfs2.1 10.14 seconds (User 2.48 secs, Sys 4.44 secs) 1.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM Zisofs 27 minutes 28.54 seconds (User 3.00 secs, Sys 1 min 4.80 secs) Cloop 5 minutes 55.72 seconds (User 2.90 secs, Sys 3 min 37.90 secs) Squashfs2.0 5 minutes 20.87 seconds (User 2.33 secs, Sys 56.98 secs) Squashfs2.1 5 minutes 15.46 seconds (user 2.28 secs, Sys 51.12 secs) 1.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM Zisofs 101 minutes 29.65 seconds (User 5.33 secs, Sys 1 min 17.20 secs) Cloop 35 minutes 27.51 seconds (user 5.93 secs, Sys 4 mins 30.23 secs) Squashfs2.0 21 minutes 53.05 seconds (user 5.71 secs, Sys 2 mins 36.59 secs) Squashfs2.1 21 minutes 46.99 seconds (User 5.80 secs, Sys 2 mins 31.88 secs) 1.2 Performance tests from Hard disk 1.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 17.29 seconds (User 2.62 secs, Sys 11.08 secs) Cloop 16.46 seconds (User 2.63 secs, Sys 13.41 secs) Squashfs2.0 13.75 seconds (User 2.44 secs, Sys 11.00 secs) Squashfs2.1 6.94 seconds (User 2.44 secs, Sys 4.48 secs) 1.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 1 minute 21.47 seconds (User 2.73 secs, Sys 54.44 secs) Cloop 1 minute 34.06 seconds (user 2.85 secs, Sys 1 min 12.13 secs) Squashfs2.0 1 minute 21.22 seconds (User 2.42 secs, Sys 56.21 secs) Squashfs2.1 1 minute 15.46 seconds (User 2.36 secs, Sys 49.78 secs) 1.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk Zisofs 11 minutes 13.64 seconds (User 5.08 secs, Sys 52.62 secs) Cloop 5 minutes 37.93 seconds (user 6 secs, Sys 2 mins 22.38 secs) Squashfs2.0 5 minutes 7.11 seconds (user 5.63 secs, Sys 2 mins 35.23 secs) Squashfs2.1 5 minutes 1.87 seconds (User 5.71 secs, Sys 2 mins 29.98 secs) 2. Damn Small Linux liveCD performance tests ext3 uncompressed size 126 MB CRAMFS compressed size 52.19 MB Squashfs2.0 compressed size 46.52 MB Squashfs2.1 compressed size 46.52 MB 2.1 Performance tests from CDROM 2.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 10.85 seconds (User 0.39 secs, Sys 0.98 secs) Squashfs2.0 2.97 seconds (User 0.36 secs, Sys 2.15 secs) Squashfs2.1 2.43 seconds (User 0.40 secs, Sys 1.42 secs) 2.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 55.38 seconds (User 0.34 secs, Sys 6.98 secs) Squashfs2.0 35.99 seconds (User 0.30 secs, Sys 6.35 secs) Squashfs2.1 33.83 seconds (User 0.26 secs, Sys 5.56 secs) 2.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM CRAMFS 3 minutes 1.68 seconds (User 0.54 secs, Sys 9.51 secs) Squashfs2.0 1 minute 39.45 seconds (User 0.57 secs, Sys 13.14 secs) Squashfs2.1 1 minute 38.41 seconds (User 0.58 secs, Sys 13.08 secs) 2.2 Performance tests from Hard disk 2.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 1.77 seconds (User 0.53 secs, Sys 1.21 secs) Squashfs2.0 2.67 seconds (User 0.41 secs, Sys 2.25 secs) Squashfs2.1 1.87 seconds (User 0.41 secs, Sys 1.46 secs) 2.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 6.80 seconds (User 0.36 secs, Sys 6.02 secs) Squashfs2.0 7.23 seconds (User 0.29 secs, Sys 6.62 secs) Squashfs2.1 6.53 seconds (User 0.31 secs, Sys 5.82 secs) 2.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk CRAMFS 28.55 seconds (User 0.49 secs, Sys 6.49 secs) Squashfs2.0 25.44 seconds (User 0.58 secs, Sys 13.17 secs) Squashfs2.1 24.72 seconds (User 0.56 secs, Sys 13.15 secs) ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/README ================================================ SQUASHFS 3.3 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.3. Please read the README-3.3 and CHANGES files for details of changes. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 1Mbytes (default block size 128K). Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. 1. SQUASHFS OVERVIEW -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. In theory files up to 2^64 bytes are supported. In theory filesystems can be up to 2^64 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 1Mbyte (the default size is 128K). Using 128K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 7. Both big and little endian architectures are supported. Squashfs can mount filesystems created on different byte order machines. 2. USING SQUASHFS ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 3. MKSQUASHFS ------------- 3.1 Mksquashfs options and overview. ------------------------------------ As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. SYNTAX:mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Options are -version print version, licence and copyright message -recover <name> recover filesystem data using recovery file <name> -no-recovery don't generate a recovery file -info print files written to filesystem -no-exports don't make the filesystem exportable via NFS -no-progress don't display the progress bar -no-sparse don't detect sparse files -b <block_size> set data block to <block_size>. Default 131072 bytes -processors <number> Use <number> processors. By default will use number of processors available -read-queue <size> Set input queue to <size> Mbytes. Default 64 Mbytes -write-queue <size> Set output queue to <size> Mbytes. Default 512 Mbytes -noI do not compress inode table -noD do not compress data blocks -noF do not compress fragment blocks -no-fragments do not use fragments -always-use-fragments use fragment blocks for files larger than block size -no-duplicates do not perform duplicate checking -noappend do not append to existing filesystem -keep-as-directory if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory -root-becomes <name> when appending source files/directories, make the original root become a subdirectory in the new root called <name>, rather than adding the new source items to the original root -all-root make all files owned by root -force-uid uid set all file uids to uid -force-gid gid set all file gids to gid -le create a little endian filesystem -be create a big endian filesystem -nopad do not pad filesystem to a multiple of 4K -check_data add checkdata for greater filesystem checks -root-owned alternative name for -all-root -noInodeCompression alternative name for -noI -noDataCompression alternative name for -noD -noFragmentCompression alternative name for -noF -sort <sort_file> sort files according to priorities in <sort_file>. One file or dir with priority per line. Priority -32768 to 32767, default priority 0 -ef <exclude_file> list of exclude dirs/files. One per line -wildcards Allow extended shell wildcards (globbing) to be used in exclude dirs/files -regex Allow POSIX regular expressions to be used in exclude dirs/files Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. 3.2 Changing compression defaults used in mksquashfs ---------------------------------------------------- There are a large number of options that can be used to control the compression in mksquashfs. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances! The -noI, -noD and -noF options (also -noInodeCompression, -noDataCompression and -noFragmentCompression) can be used to force mksquashfs to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. The -no-fragments tells mksquashfs to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 3.1 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. The -always-use-fragments option tells mksquashfs to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. The -no-duplicates option tells mksquashfs to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. The -b option allows the block size to be selected, both "K" and "M" postfixes are supported, this can be either 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K or 1M bytes. 3.3 Specifying the UIDs/GIDs used in the filesystem --------------------------------------------------- By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, mksquashfs provides a number of options which can be used to override the ownership. The options -all-root and -root-owned (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The "-force-uid uid" option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. The "-force-gid gid" option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. 3.4 Excluding files from the filesystem --------------------------------------- For new wildcard exclude file handling please refer to the README-3.3 file. The older exclude functionality described here is used if the -wildcard or -regex options are not specified. The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. 3.5 Appending to squashfs filesystems ------------------------------------- Running squashfs with the destination directory containing an existing filesystem will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3.6 Miscellaneous options ------------------------- The -info option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The -le and -be options can be used to force mksquashfs to generate a little endian or big endian filesystem. Normally mksquashfs will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 4. UNSQUASHFS ------------- Unsquashfs allows you to decompress and extract a Squashfs filesystem without mounting it. It can extract the entire filesystem, or a specific file or directory. The Unsquashfs usage info is: SYNTAX: unsquashfs [options] filesystem [directories or files to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -li[nfo] print files as they are unsquashed with file attributes (like ls -l output) -l[s] list filesystem, but don't unsquash -ll[s] list filesystem with file attributes (like ls -l output), but don't unsquash -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -f[orce] if file already exists then overwrite -s[tat] display filesystem superblock information -e[f] <extract file> list of directories or files to extract. One per line -r[egex] treat extract names as POSIX regular expressions rather than use the default shell wildcard expansion (globbing) To extract a subset of the filesystem, the filenames or directory trees that are to be extracted can now be specified on the command line. The files/directories should be specified using the full path to the files/directories as they appear within the Squashfs filesystem. The files/directories will also be extracted to those positions within the specified destination directory. Please refer to the README-3.3 file for a description of the new wildcard pattern matching functionality for extract files. The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. The "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. Unsquashfs can decompress all Squashfs filesystem versions, 1.x, 2.x and 3.x filesystems. 5. FILESYSTEM LAYOUT -------------------- Brief filesystem design notes follow for the original 1.x filesystem layout. A description of the 2.x and 3.x filesystem layouts will be written sometime! A squashfs filesystem consists of five parts, packed together on a byte alignment: --------------- | superblock | |---------------| | data | | blocks | |---------------| | inodes | |---------------| | directories | |---------------| | uid/gid | | lookup table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory and uid/gid lookup tables are written. 5.1 Metadata ------------ Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. An inode is identified by a two field tuple <start address of compressed block : offset into de-compressed block>. Inode contents vary depending on the file type. The base inode consists of: base inode: Inode type Mode uid index gid index The inode type is 4 bits in size, and the mode is 12 bits. The uid and gid indexes are 4 bits in length. Ordinarily, this will allow 16 unique indexes into the uid table. To minimise overhead, the uid index is used in conjunction with the spare bit in the file type to form a 48 entry index as follows: inode type 1 - 5: uid index = uid inode type 5 -10: uid index = 16 + uid inode type 11 - 15: uid index = 32 + uid In this way 48 unique uids are supported using 4 bits, minimising data inode overhead. The 4 bit gid index is used to index into a 15 entry gid table. Gid index 15 is used to indicate that the gid is the same as the uid. This prevents the 15 entry gid table filling up with the common case where the uid/gid is the same. The data contents of symbolic links are stored immediately after the symbolic link inode, inside the inode table. This allows the normally small symbolic link to be compressed as part of the inode table, achieving much greater compression than if the symbolic link was compressed individually. Similarly, the block index for regular files is stored immediately after the regular file inode. The block index is a list of block lengths (two bytes each), rather than block addresses, saving two bytes per block. The block address for a given block is computed by the summation of the previous block lengths. This takes advantage of the fact that the blocks making up a file are stored contiguously in the filesystem. The top bit of each block length is set if the block is uncompressed, either because the -noD option is set, or if the compressed block was larger than the uncompressed block. 5.2 Directories --------------- Like inodes, directories are packed into the metadata blocks, and are not aligned on block boundaries, therefore directories can overlap compressed blocks. A directory is, again, identified by a two field tuple <start address of compressed block containing directory start : offset into de-compressed block>. Directories are organised in a slightly complex way, and are not simply a list of file names and inode tuples. The organisation takes advantage of the observation that in most cases, the inodes of the files in the directory will be in the same compressed metadata block, and therefore, the inode tuples will have the same start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. The organisation is as follows: directory_header: count (8 bits) inode start block (24 bits) directory entry: * count inode offset (13 bits) inode type (3 bits) filename size (8 bits) filename This organisation saves on average 3 bytes per filename. 5.3 File data ------------- File data is compressed on a block by block basis and written to the filesystem. The filesystem supports up to 32K blocks, which achieves greater compression ratios than the Linux 4K page size. The disadvantage with using greater than 4K blocks (and the reason why most filesystems do not), is that the VFS reads data in 4K pages. The filesystem reads and decompresses a larger block containing that page (e.g. 32K). However, only 4K can be returned to the VFS, resulting in a very inefficient filesystem, as 28K must be thrown away. Squashfs, solves this problem by explicitly pushing the extra pages into the page cache. 6. AUTHOR INFO -------------- Squashfs was written by Phillip Lougher, email phillip@lougher.org.uk, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback! ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/README-3.3 ================================================ SQUASHFS 3.3 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to another release of Squashfs. This is the 22nd release in just over five years of work. Squashfs 3.3 has lots of nice improvements, both to the filesystem itself (bigger blocks, and sparse files), but also to the Squashfs-tools Mksquashfs and Unsquashfs. As usual the CHANGES file has a detailed list of all the improvements. Following is a description of the changes to the Squashfs tools, usage guides to the new options, and a summary of the new options. 1. MKSQUASHFS - EXTENDED EXCLUDE FILE HANDLING ---------------------------------------------- 1. Extended wildcard pattern matching now supported in exclude files Enabled by specifying -wildcard option Supports both anchored and non-anchored exclude files. 1.1 Anchored excludes Similar to existing exclude files except with wildcards. Exclude file matches from root of source directories. Examples: 1. mksquashfs example image.sqsh -e 'test/*.gz' Exclude all files matching "*.gz" in the top level directory "test". 2. mksquashfs example image.sqsh -e '*/[Tt]est/example*' Exclude all files beginning with "example" inside directories called "Test" or "test", that occur inside any top level directory. Using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -e 'test/!(*data*).gz' Exclude all files matching "*.gz" in top level directory "test", except those with "data" in the name. 1.2 Non-anchored excludes By default excludes match from the top level directory, but it is often useful to exclude a file matching anywhere in the source directories. For this non-anchored excludes can be used, specified by pre-fixing the exclude with "...". Examples: 1. mksquashfs example image.sqsh -e '... *.gz' Exclude files matching "*.gz" anywhere in the source directories. For example this will match "example.gz", "test/example.gz", and "test/test/example.gz". 2. mksquashfs example image.sqsh -e '... [Tt]est/*.gz' Exclude files matching "*.gz" inside directories called "Test" or "test" that occur anywhere in the source directories. Again, using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -e '... !(*data*).gz' Exclude all files matching "*.gz" anywhere in the source directories, except those with "data" in the name. 2. Regular expression pattern matching now supported in exclude files Enabled by specifying -regex option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. Supports both anchored and non-anchored exclude files. 2. MKSQUASHFS - NEW RECOVERY FILE FEATURE ----------------------------------------- Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). The recovery files are called squashfs_recovery_xxx_yyy, where "xxx" is the name of the filesystem being appended to, and "yyy" is a number to guarantee filename uniqueness (the PID of the parent Mksquashfs process). Normally if Mksquashfs exits correctly the recovery file is deleted to avoid cluttering the filesystem. If Mksquashfs aborts, the "-recover" option can be used to recover the filesystem, giving the previously created recovery file as a parameter, i.e. mksquashfs dummy image.sqsh -recover squashfs_recovery_image.sqsh_1234 The writing of the recovery file can be disabled by specifying the "-no-recovery" option. 3. UNSQUASHFS - EXTENDED EXTRACT FILE HANDLING ---------------------------------------------- 1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. To specify a file containing the extract files use the "-e[f]" option. 2. Extended wildcard pattern matching now supported in extract files Enabled by default. Similar to existing extract files except with wildcards. Examples: 1. unsquashfs image.sqsh 'test/*.gz' Extract all files matching "*.gz" in the top level directory "test". 2. unsquashfs image.sqsh '[Tt]est/example*' Extract all files beginning with "example" inside top level directories called "Test" or "test". Using extended wildcards, negative matching is also possible. 3. unsquashfs image.sqsh 'test/!(*data*).gz' Extract all files matching "*.gz" in top level directory "test", except those with "data" in the name. 3. Regular expression pattern matching now supported in extract files Enabled by specifying -r[egex] option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. 4. UNSQUASHFS - EXTENDED FILENAME PRINTING ------------------------------------------ Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). New options: -ll[s] list filesystem with file attributes, but don't unsquash -li[nfo] print files as they are unsquashed with file attributes 5. UNSQUASHFS - MISCELLANEOUS OPTIONS ------------------------------------- -s[tat] Display the filesystem superblock information. This is useful to discover the filesystem version, byte ordering, whether it has an NFS export table, and what options were used to compress the filesystem. ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.10/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.10/fs/Kconfig linux-2.6.10-squashfs3.3/fs/Kconfig --- linux-2.6.10/fs/Kconfig 2004-12-24 21:34:58.000000000 +0000 +++ linux-2.6.10-squashfs3.3/fs/Kconfig 2007-11-01 05:06:24.000000000 +0000 @@ -1266,6 +1266,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.10/fs/Makefile linux-2.6.10-squashfs3.3/fs/Makefile --- linux-2.6.10/fs/Makefile 2004-12-24 21:34:58.000000000 +0000 +++ linux-2.6.10-squashfs3.3/fs/Makefile 2007-11-01 05:06:24.000000000 +0000 @@ -51,6 +51,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.10/fs/squashfs/inode.c linux-2.6.10-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.10/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:11:22.000000000 +0000 @@ -0,0 +1,2215 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static void *kzalloc(int size, int flags) +{ + void *buff = kmalloc(size, flags); + + if(buff != NULL) + memset(buff, 0, size); + + return buff; +} + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + down(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + up(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + up(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + up(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + up(&msblk->block_cache_mutex); + goto out; + } + + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + up(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + up(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + up(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + up(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + down(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + up(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + down(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + up(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + up(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + down(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + up(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + up(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->block_cache_mutex); + init_MUTEX(&msblk->fragment_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.10/fs/squashfs/Makefile linux-2.6.10-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.10/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.10/fs/squashfs/squashfs2_0.c linux-2.6.10-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.10/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:57:55.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.10/fs/squashfs/squashfs.h linux-2.6.10-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.10/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:13:29.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.10/include/linux/squashfs_fs.h linux-2.6.10-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.10/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.10/include/linux/squashfs_fs_i.h linux-2.6.10-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.10/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.10/include/linux/squashfs_fs_sb.h linux-2.6.10-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.10/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.10-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-10-31 14:28:58.000000000 +0000 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + struct semaphore meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.10/init/do_mounts_rd.c linux-2.6.10-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.10/init/do_mounts_rd.c 2004-12-24 21:35:23.000000000 +0000 +++ linux-2.6.10-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:24.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.12/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.12/fs/Kconfig linux-2.6.12-squashfs3.3/fs/Kconfig --- linux-2.6.12/fs/Kconfig 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/Kconfig 2007-11-01 05:06:24.000000000 +0000 @@ -1171,6 +1171,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.12/fs/Makefile linux-2.6.12-squashfs3.3/fs/Makefile --- linux-2.6.12/fs/Makefile 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/Makefile 2007-11-01 05:06:24.000000000 +0000 @@ -52,6 +52,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/inode.c linux-2.6.12-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.12/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:11:08.000000000 +0000 @@ -0,0 +1,2215 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static void *kzalloc(int size, int flags) +{ + void *buff = kmalloc(size, flags); + + if(buff != NULL) + memset(buff, 0, size); + + return buff; +} + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + down(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + up(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + up(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + up(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + up(&msblk->block_cache_mutex); + goto out; + } + + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + up(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + up(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + up(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + up(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + down(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + up(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + down(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + up(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + up(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + down(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + up(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + up(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->block_cache_mutex); + init_MUTEX(&msblk->fragment_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/Makefile linux-2.6.12-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.12/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/squashfs2_0.c linux-2.6.12-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.12/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:57:55.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/squashfs.h linux-2.6.12-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.12/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:13:23.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs.h linux-2.6.12-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.12/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs_i.h linux-2.6.12-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.12/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs_sb.h linux-2.6.12-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.12/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-10-31 14:28:58.000000000 +0000 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + struct semaphore meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.12/init/do_mounts_rd.c linux-2.6.12-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.12/init/do_mounts_rd.c 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:24.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.14/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.14/fs/Kconfig linux-2.6.14-squashfs3.3/fs/Kconfig --- linux-2.6.14/fs/Kconfig 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/Kconfig 2007-11-01 05:06:24.000000000 +0000 @@ -1137,6 +1137,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.14/fs/Makefile linux-2.6.14-squashfs3.3/fs/Makefile --- linux-2.6.14/fs/Makefile 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/Makefile 2007-11-01 05:06:24.000000000 +0000 @@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/inode.c linux-2.6.14-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.14/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:10:57.000000000 +0000 @@ -0,0 +1,2204 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + down(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + up(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + up(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + up(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + up(&msblk->block_cache_mutex); + goto out; + } + + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + up(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + up(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + up(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + up(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + down(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + up(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + down(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + up(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + up(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + down(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + up(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + up(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->block_cache_mutex); + init_MUTEX(&msblk->fragment_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/Makefile linux-2.6.14-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.14/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/squashfs2_0.c linux-2.6.14-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.14/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:58:14.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/squashfs.h linux-2.6.14-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.14/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:13:16.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs.h linux-2.6.14-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.14/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs_i.h linux-2.6.14-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.14/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs_sb.h linux-2.6.14-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.14/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-10-31 14:28:58.000000000 +0000 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + struct semaphore meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.14/init/do_mounts_rd.c linux-2.6.14-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.14/init/do_mounts_rd.c 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:24.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.16/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.16/fs/Kconfig linux-2.6.16-squashfs3.3/fs/Kconfig --- linux-2.6.16/fs/Kconfig 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1193,6 +1193,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.16/fs/Makefile linux-2.6.16-squashfs3.3/fs/Makefile --- linux-2.6.16/fs/Makefile 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/inode.c linux-2.6.16-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.16/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:10:37.000000000 +0000 @@ -0,0 +1,2204 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.16/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/squashfs2_0.c linux-2.6.16-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.16/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:58:35.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/squashfs.h linux-2.6.16-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.16/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:12:17.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs.h linux-2.6.16-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.16/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs_i.h linux-2.6.16-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.16/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs_sb.h linux-2.6.16-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.16/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.16/init/do_mounts_rd.c linux-2.6.16-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.16/init/do_mounts_rd.c 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.18/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.18/fs/Kconfig linux-2.6.18-squashfs3.3/fs/Kconfig --- linux-2.6.18/fs/Kconfig 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1249,6 +1249,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.18/fs/Makefile linux-2.6.18-squashfs3.3/fs/Makefile --- linux-2.6.18/fs/Makefile 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -57,6 +57,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/inode.c linux-2.6.18-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.18/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:10:25.000000000 +0000 @@ -0,0 +1,2206 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/Makefile linux-2.6.18-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.18/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/squashfs2_0.c linux-2.6.18-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.18/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:58:54.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/squashfs.h linux-2.6.18-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.18/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/fs/squashfs/squashfs.h 2007-08-19 04:23:16.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs.h linux-2.6.18-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.18/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs_i.h linux-2.6.18-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.18/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs_sb.h linux-2.6.18-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.18/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.18/init/do_mounts_rd.c linux-2.6.18-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.18/init/do_mounts_rd.c 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.20/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.20/fs/Kconfig linux-2.6.20-squashfs3.3/fs/Kconfig --- linux-2.6.20/fs/Kconfig 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1404,6 +1404,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.20/fs/Makefile linux-2.6.20-squashfs3.3/fs/Makefile --- linux-2.6.20/fs/Makefile 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -68,6 +68,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/inode.c linux-2.6.20-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.20/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:10:13.000000000 +0000 @@ -0,0 +1,2192 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/smp_lock.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/Makefile linux-2.6.20-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.20/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/squashfs2_0.c linux-2.6.20-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.20/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-25 00:43:59.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/squashfs.h linux-2.6.20-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.20/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/fs/squashfs/squashfs.h 2007-08-19 04:23:16.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs.h linux-2.6.20-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.20/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs_i.h linux-2.6.20-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.20/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs_sb.h linux-2.6.20-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.20/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.20/init/do_mounts_rd.c linux-2.6.20-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.20/init/do_mounts_rd.c 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.22/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.22/fs/Kconfig linux-2.6.22-squashfs3.3/fs/Kconfig --- linux-2.6.22/fs/Kconfig 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1367,6 +1367,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.22/fs/Makefile linux-2.6.22-squashfs3.3/fs/Makefile --- linux-2.6.22/fs/Makefile 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/inode.c linux-2.6.22-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.22/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:09:57.000000000 +0000 @@ -0,0 +1,2191 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/smp_lock.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/Makefile linux-2.6.22-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.22/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/squashfs2_0.c linux-2.6.22-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.22/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-25 00:43:59.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/squashfs.h linux-2.6.22-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.22/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/fs/squashfs/squashfs.h 2007-08-19 04:23:16.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs.h linux-2.6.22-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.22/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs_i.h linux-2.6.22-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.22/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs_sb.h linux-2.6.22-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.22/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.22/init/do_mounts_rd.c linux-2.6.22-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.22/init/do_mounts_rd.c 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.23/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.23/fs/Kconfig linux-2.6.23-squashfs3.3/fs/Kconfig --- linux-2.6.23/fs/Kconfig 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1364,6 +1364,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.23/fs/Makefile linux-2.6.23-squashfs3.3/fs/Makefile --- linux-2.6.23/fs/Makefile 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/inode.c linux-2.6.23-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.23/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:09:05.000000000 +0000 @@ -0,0 +1,2192 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/Makefile linux-2.6.23-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.23/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.23/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-25 00:43:59.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.23/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/fs/squashfs/squashfs.h 2007-08-19 04:23:16.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.23/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.23/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.23/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.23/init/do_mounts_rd.c linux-2.6.23-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.23/init/do_mounts_rd.c 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.24/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.24/fs/Kconfig linux-2.6.24-squashfs3.3/fs/Kconfig --- linux-2.6.24/fs/Kconfig 2007-10-25 17:41:45.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1396,6 +1396,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.24/fs/Makefile linux-2.6.24-squashfs3.3/fs/Makefile --- linux-2.6.24/fs/Makefile 2007-10-25 17:41:45.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/Makefile 2007-11-01 05:08:09.000000000 +0000 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/inode.c linux-2.6.24-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.24/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/squashfs/inode.c 2007-11-01 05:05:00.000000000 +0000 @@ -0,0 +1,2192 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + mutex_lock(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + mutex_unlock(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + mutex_unlock(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } + + mutex_lock(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + mutex_unlock(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + mutex_unlock(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + mutex_unlock(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + mutex_unlock(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + mutex_lock(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + mutex_unlock(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + mutex_lock(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + mutex_unlock(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + mutex_unlock(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + mutex_unlock(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + mutex_lock(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + mutex_unlock(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + mutex_unlock(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->block_cache_mutex); + mutex_init(&msblk->fragment_mutex); + mutex_init(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(struct kmem_cache *cachep, void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/Makefile linux-2.6.24-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.24/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/squashfs2_0.c linux-2.6.24-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.24/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-25 00:43:59.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/squashfs.h linux-2.6.24-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.24/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/fs/squashfs/squashfs.h 2007-08-19 04:23:16.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs.h linux-2.6.24-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.24/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs_i.h linux-2.6.24-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.24/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs_sb.h linux-2.6.24-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.24/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-08-19 04:24:26.000000000 +0100 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex block_cache_mutex; + struct mutex fragment_mutex; + struct mutex meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.24/init/do_mounts_rd.c linux-2.6.24-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.24/init/do_mounts_rd.c 2007-10-25 17:41:49.000000000 +0100 +++ linux-2.6.24-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.6/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.6/fs/Kconfig linux-2.6.6-squashfs3.3/fs/Kconfig --- linux-2.6.6/fs/Kconfig 2004-05-10 03:32:38.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1145,6 +1145,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.6/fs/Makefile linux-2.6.6-squashfs3.3/fs/Makefile --- linux-2.6.6/fs/Makefile 2004-05-10 03:32:38.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -50,6 +50,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.6/fs/squashfs/inode.c linux-2.6.6-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.6/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:11:47.000000000 +0000 @@ -0,0 +1,2215 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static void *kzalloc(int size, int flags) +{ + void *buff = kmalloc(size, flags); + + if(buff != NULL) + memset(buff, 0, size); + + return buff; +} + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + down(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + up(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + up(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + up(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + up(&msblk->block_cache_mutex); + goto out; + } + + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + up(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + up(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + up(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + up(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + down(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + up(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + down(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + up(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + up(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + down(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + up(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + up(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->block_cache_mutex); + init_MUTEX(&msblk->fragment_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.6/fs/squashfs/Makefile linux-2.6.6-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.6/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.6/fs/squashfs/squashfs2_0.c linux-2.6.6-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.6/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:57:55.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.6/fs/squashfs/squashfs.h linux-2.6.6-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.6/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:13:45.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.6/include/linux/squashfs_fs.h linux-2.6.6-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.6/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.6/include/linux/squashfs_fs_i.h linux-2.6.6-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.6/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.6/include/linux/squashfs_fs_sb.h linux-2.6.6-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.6/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.6-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-10-31 14:28:58.000000000 +0000 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + struct semaphore meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.6/init/do_mounts_rd.c linux-2.6.6-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.6/init/do_mounts_rd.c 2004-05-10 03:32:54.000000000 +0100 +++ linux-2.6.6-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/kernel-patches/linux-2.6.8.1/squashfs3.3-patch ================================================ diff -x .gitignore -Nurp linux-2.6.8.1/fs/Kconfig linux-2.6.8.1-squashfs3.3/fs/Kconfig --- linux-2.6.8.1/fs/Kconfig 2004-08-14 11:55:33.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/Kconfig 2007-11-01 05:06:25.000000000 +0000 @@ -1231,6 +1231,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.3 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.3 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.8.1/fs/Makefile linux-2.6.8.1-squashfs3.3/fs/Makefile --- linux-2.6.8.1/fs/Makefile 2004-08-14 11:55:33.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/Makefile 2007-11-01 05:06:25.000000000 +0000 @@ -50,6 +50,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.8.1/fs/squashfs/inode.c linux-2.6.8.1-squashfs3.3/fs/squashfs/inode.c --- linux-2.6.8.1/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/squashfs/inode.c 2007-11-01 03:11:35.000000000 +0000 @@ -0,0 +1,2215 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +int squashfs_cached_blks; + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static void *kzalloc(int size, int flags) +{ + void *buff = kmalloc(size, flags); + + if(buff != NULL) + memset(buff, 0, size); + + return buff; +} + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + bh[0] = sb_getblk(s, cur_index); + if (bh[0] == NULL) + goto block_release; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 1; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int n, i, bytes, return_length = length; + long long next_index; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + for (i = 0; i < squashfs_cached_blks; i++) + if (msblk->block_cache[i].block == block) + break; + + down(&msblk->block_cache_mutex); + + if (i == squashfs_cached_blks) { + /* read inode header block */ + if (msblk->unused_cache_blks == 0) { + up(&msblk->block_cache_mutex); + wait_event(msblk->waitq, msblk->unused_cache_blks); + continue; + } + + i = msblk->next_cache; + for (n = 0; n < squashfs_cached_blks; n++) { + if (msblk->block_cache[i].block != SQUASHFS_USED_BLK) + break; + i = (i + 1) % squashfs_cached_blks; + } + + msblk->next_cache = (i + 1) % squashfs_cached_blks; + + if (msblk->block_cache[i].block == SQUASHFS_INVALID_BLK) { + msblk->block_cache[i].data = vmalloc(SQUASHFS_METADATA_SIZE); + if (msblk->block_cache[i].data == NULL) { + ERROR("Failed to allocate cache block\n"); + up(&msblk->block_cache_mutex); + goto out; + } + } + + msblk->block_cache[i].block = SQUASHFS_USED_BLK; + msblk->unused_cache_blks --; + up(&msblk->block_cache_mutex); + + msblk->block_cache[i].length = squashfs_read_data(s, + msblk->block_cache[i].data, block, 0, &next_index, + SQUASHFS_METADATA_SIZE); + + if (msblk->block_cache[i].length == 0) { + ERROR("Unable to read cache block [%llx:%x]\n", block, offset); + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + msblk->unused_cache_blks ++; + smp_mb(); + vfree(msblk->block_cache[i].data); + wake_up(&msblk->waitq); + up(&msblk->block_cache_mutex); + goto out; + } + + down(&msblk->block_cache_mutex); + msblk->block_cache[i].block = block; + msblk->block_cache[i].next_index = next_index; + msblk->unused_cache_blks ++; + smp_mb(); + wake_up(&msblk->waitq); + TRACE("Read cache block [%llx:%x]\n", block, offset); + } + + if (msblk->block_cache[i].block != block) { + up(&msblk->block_cache_mutex); + continue; + } + + bytes = msblk->block_cache[i].length - offset; + + if (bytes < 1) { + up(&msblk->block_cache_mutex); + goto out; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, msblk->block_cache[i].data + offset, length); + if (msblk->block_cache[i].length - offset == length) { + *next_block = msblk->block_cache[i].next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + up(&msblk->block_cache_mutex); + goto finish; + } else { + if (buffer) { + memcpy(buffer, msblk->block_cache[i].data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = msblk->block_cache[i].next_index; + up(&msblk->block_cache_mutex); + length -= bytes; + offset = 0; + } + } + +finish: + return return_length; +out: + return 0; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_fragment_cache *fragment) +{ + down(&msblk->fragment_mutex); + fragment->locked --; + if (fragment->locked == 0) { + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + } + up(&msblk->fragment_mutex); +} + + +SQSH_EXTERN +struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + int i, n; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + while (1) { + down(&msblk->fragment_mutex); + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && + msblk->fragment[i].block != start_block; i++); + + if (i == SQUASHFS_CACHED_FRAGMENTS) { + if (msblk->unused_frag_blks == 0) { + up(&msblk->fragment_mutex); + wait_event(msblk->fragment_wait_queue, msblk->unused_frag_blks); + continue; + } + + i = msblk->next_fragment; + for (n = 0; n < SQUASHFS_CACHED_FRAGMENTS; n++) { + if (msblk->fragment[i].locked == 0) + break; + i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS; + } + + msblk->next_fragment = (msblk->next_fragment + 1) % + SQUASHFS_CACHED_FRAGMENTS; + + if (msblk->fragment[i].data == NULL) { + msblk->fragment[i].data = vmalloc(sblk->block_size); + if (msblk->fragment[i].data == NULL) { + ERROR("Failed to allocate fragment cache block\n"); + up(&msblk->fragment_mutex); + goto out; + } + } + + msblk->unused_frag_blks --; + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + msblk->fragment[i].locked = 1; + up(&msblk->fragment_mutex); + + msblk->fragment[i].length = squashfs_read_data(s, + msblk->fragment[i].data, start_block, length, NULL, + sblk->block_size); + + if (msblk->fragment[i].length == 0) { + ERROR("Unable to read fragment cache block [%llx]\n", start_block); + msblk->fragment[i].locked = 0; + msblk->unused_frag_blks ++; + smp_mb(); + wake_up(&msblk->fragment_wait_queue); + goto out; + } + + down(&msblk->fragment_mutex); + msblk->fragment[i].block = start_block; + TRACE("New fragment %d, start block %lld, locked %d\n", + i, msblk->fragment[i].block, msblk->fragment[i].locked); + up(&msblk->fragment_mutex); + break; + } + + if (msblk->fragment[i].locked == 0) + msblk->unused_frag_blks --; + msblk->fragment[i].locked++; + up(&msblk->fragment_mutex); + TRACE("Got fragment %d, start block %lld, locked %d\n", i, + msblk->fragment[i].block, msblk->fragment[i].locked); + break; + } + + return &msblk->fragment[i]; + +out: + return NULL; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int readahead_metadata(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int i; + + squashfs_cached_blks = SQUASHFS_CACHED_BLKS; + + /* Init inode_table block pointer array */ + msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * + squashfs_cached_blks, GFP_KERNEL); + if (msblk->block_cache == NULL) { + ERROR("Failed to allocate block cache\n"); + goto failed; + } + + for (i = 0; i < squashfs_cached_blks; i++) + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; + + msblk->next_cache = 0; + msblk->unused_cache_blks = squashfs_cached_blks; + + return 1; + +failed: + return 0; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + int i; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->block_cache_mutex); + init_MUTEX(&msblk->fragment_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + init_waitqueue_head(&msblk->waitq); + init_waitqueue_head(&msblk->fragment_wait_queue); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + if (readahead_metadata(s) == 0) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment = kzalloc(sizeof(struct squashfs_fragment_cache) * + SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL); + if (msblk->fragment == NULL) { + ERROR("Failed to allocate fragment block cache\n"); + goto failed_mount; + } + + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { + msblk->fragment[i].block = SQUASHFS_INVALID_BLK; + } + + msblk->next_fragment = 0; + msblk->unused_frag_blks = SQUASHFS_CACHED_FRAGMENTS; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->fragment); + kfree(msblk->uid); + vfree(msblk->read_page); + kfree(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_fragment_cache *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment == NULL) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos =- 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + int i; + + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + if (sbi->block_cache) + for (i = 0; i < squashfs_cached_blks; i++) + if (sbi->block_cache[i].block != SQUASHFS_INVALID_BLK) + vfree(sbi->block_cache[i].data); + if (sbi->fragment) + for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) + vfree(sbi->fragment[i].data); + kfree(sbi->fragment); + kfree(sbi->block_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.3 (2007/10/31) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.2-r2-CVS, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.8.1/fs/squashfs/Makefile linux-2.6.8.1-squashfs3.3/fs/squashfs/Makefile --- linux-2.6.8.1/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/squashfs/Makefile 2005-11-20 14:31:00.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.8.1/fs/squashfs/squashfs2_0.c linux-2.6.8.1-squashfs3.3/fs/squashfs/squashfs2_0.c --- linux-2.6.8.1/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/squashfs/squashfs2_0.c 2007-10-31 22:57:55.000000000 +0000 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.8.1/fs/squashfs/squashfs.h linux-2.6.8.1-squashfs3.3/fs/squashfs/squashfs.h --- linux-2.6.8.1/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/fs/squashfs/squashfs.h 2007-11-01 02:13:38.000000000 +0000 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.8.1/include/linux/squashfs_fs.h linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs.h --- linux-2.6.8.1/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs.h 2007-11-01 03:50:57.000000000 +0000 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int pending; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.8.1/include/linux/squashfs_fs_i.h linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs_i.h --- linux-2.6.8.1/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs_i.h 2007-08-19 04:24:08.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.8.1/include/linux/squashfs_fs_sb.h linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs_sb.h --- linux-2.6.8.1/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/include/linux/squashfs_fs_sb.h 2007-10-31 14:28:58.000000000 +0000 @@ -0,0 +1,76 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache { + long long block; + int length; + long long next_index; + char *data; +}; + +struct squashfs_fragment_cache { + long long block; + int length; + unsigned int locked; + char *data; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_fragment_cache *fragment; + int next_cache; + int next_fragment; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore block_cache_mutex; + struct semaphore fragment_mutex; + struct semaphore meta_index_mutex; + wait_queue_head_t waitq; + wait_queue_head_t fragment_wait_queue; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int unused_cache_blks; + int unused_frag_blks; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.8.1/init/do_mounts_rd.c linux-2.6.8.1-squashfs3.3/init/do_mounts_rd.c --- linux-2.6.8.1/init/do_mounts_rd.c 2004-08-14 11:55:48.000000000 +0100 +++ linux-2.6.8.1-squashfs3.3/init/do_mounts_rd.c 2007-11-01 05:06:25.000000000 +0000 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/Makefile ================================================ ifndef Sqlzma $(error Sqlzma is not defined) endif INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ifdef UseDebugFlags DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG endif CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} LDLIBS += -lm -L${LzmaAlone} -L${LzmaC} Tgt = mksquashfs unsquashfs all: ${Tgt} read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ -lz mksquashfs: mksquashfs.o read_fs.o sort.o unsquashfs.o: CFLAGS += -U_REENTRANT unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a unsquashfs: LDLIBS += -lunlzma -lz unsquashfs: unsquashfs.o clean: ${RM} *~ *.o ${Tgt} -include test.mk # Local variables: ; # compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include <squashfs_fs.h> #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "sqlzma.h" #include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; struct sqlzma_un un; struct sqlzma_opts sqlzma_opts = { .try_lzma = 1, .dicsize = SQUASHFS_FILE_SIZE }; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { long long file_size; struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } res = sqlzma_cm(&sqlzma_opts, stream, (void *)s, size, (void *)d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL); #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)cbuffer, .sz = size}, {.buf = (void *)buffer, .sz = bytes} }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int avail_bytes, compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else if(b->size != 0) chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; char *datap; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_MAX_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } char buffer2[SQUASHFS_FILE_MAX_SIZE]; struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long dup_start = dupl_ptr->start; char *buffer; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else if(b->size) buffer = read_from_disk(b->start, b->size); else continue; read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int block_order = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = alloc_get(reader_buffer); byte = file_buffer->size = read(file, file_buffer->data, block_size); file_buffer->block_order = block_order ++; file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read(file, &buffer, 1) == 1) goto restat; } if(file_buffer->fragment = file_buffer->block == frag_block) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = alloc_get(reader_buffer); file_buffer->block_order = block_order ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } return NULL; } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); if(sparse_files && all_zero(file_buffer)) write_buffer->c_byte = 0; else write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { int file; struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; int status; *duplicate_file = FALSE; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else alloc_free(read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block, thresh; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct file_data *file_data; struct buffer_list *buffer_list; int status; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; } else { buffer_list[block].read_buffer = NULL; alloc_free(read_buffer); } buffer_list[block].start = read_buffer->block; buffer_list[block].size = read_buffer->size; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); if(status = read_buffer->error) { alloc_free(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); alloc_free(read_buffer); } else if(!no_fragments && (read_size < block_size)) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf.st_size + block_size - 1) >> block_log; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, new, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; #if 0 default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; #endif } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(block_size, reader_buffer_size); writer_buffer = alloc_init(block_size, writer_buffer_size); fragment_buffer = alloc_init(block_size, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB)) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing exclude which subsumes the exclude currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific excludes, delete as they're subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with -wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories in the * filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n"); read_bytes(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) BAD_ERROR("Failed to create recovery file, because %s. Aborting\n", strerror(errno)); if(write(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int readbytes; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n"); if((readbytes = read(recoverfd, metadata, bytes)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(readbytes != bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_bytes(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 3.3 (2007/10/31)\n");\ printf("copyright (C) 2007 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; int s_minor; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-lzmadic") == 0) { long bs; unsigned int bl; if(++i == argc) { ERROR("%s: -b|-lzmadic missing block size\n", argv[0]); exit(1); } bs = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') bs *= 1048576; else if(*b == 'k' || *b == 'K') bs *= 1024; else if(*b != '\0') { ERROR("%s: -b|-lzmadic invalid size\n", argv[0]); exit(1); } bl = slog(bs); if(bl == 0) { ERROR("%s: -b|-lzmadic size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } if (!strcmp(argv[i - 1], "-b")) { block_size = bs; block_log = bl; } sqlzma_opts.dicsize = bs; } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { un.un_lzma = 0; sqlzma_opts.try_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors <number>\tUse <number> processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); ERROR("-lzmadic <dic_size>\tset the LZMA dictionary" " size to <dic_size>\n" "\t\t\tDefault value always follow the block" " size\n" "\t\t\tUse this alone or AFTER -b option\n"); ERROR("-nolzma\t\t\tnever try LZMA compression\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); if(block_size <= 65536 && sparse_files == FALSE) s_minor = 0; else s_minor = SQUASHFS_MINOR; for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } be = orig_be; block_log = slog(block_size = sBlk.block_size); //sqlzma_opts.dicsize = block_size; s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { ERROR("%s:%d: %d\n", __func__, __LINE__, i); EXIT_MKSQUASHFS(); } if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC_LZMA; if (!un.un_lzma) sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { int uid = uids[i]; struct passwd *user = getpwuid(uid); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC_LZMA: if (!un.un_lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_LZMA_SWAP: if (!un.un_lzma) goto bad; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %xllx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.3-grml-lzma/squashfs3.3/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include <stdlib.h> #include <time.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("unsquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ exit(1); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(char *pathname, unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, unsigned char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; struct test { int mask; int value; int position; char mode; }; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; struct sqlzma_un un; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } /* printf("i%d ", inode->inode_number); */ if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)data, .sz = c_byte}, {.buf = (void *)block, .sz = bytes} }; if(read_bytes(start, c_byte, data) == FALSE) return 0; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, unsigned char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, unsigned char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int lseek_broken = FALSE; char *zero_data; long long hole; int write_block(int file_fd, char *buffer, int size) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } hole = 0; } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } int write_file(long long file_size, char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; int file_end = file_size / block_size; TRACE("write_file: regular file, blocks %d\n", blocks); hole = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } s_ops.read_block_list(block_list, block_ptr, blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if(block_list[i] == 0) { /* sparse file */ hole += i == file_end ? file_size & (block_size - 1) : block_size; continue; } if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write_block(file_fd, file_data, bytes) == FALSE) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write_block(file_fd, fragment_data + offset, frag_bytes) == FALSE) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } if(hole) { /* corner case for hole extending to end of file */ hole --; if(write_block(file_fd, "\0", 1) == FALSE) { ERROR("write_file: failed to write sparse data block\n"); goto failure; } } close(file_fd); free(block_list); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i->data, pathname, i->fragment, i->frag_bytes, i->offset, i->blocks, i->start, i->block_ptr, i->mode)) { set_attributes(pathname, i->mode, i->uid, i->gid, i->time, force); file_count ++; } break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %d\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%x\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start), file_fd; char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB)) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { struct dir *dir = s_ops.squashfs_opendir(parent_name, start_block, offset); unsigned int type; char *name, pathname[1024]; struct pathnames *new; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) create_inode(pathname, i); } free_subdir(new); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ un.un_lzma = 1; swap = 0; switch (sBlk.s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } #define VERSION() \ printf("unsquashfs version 1.5 (2007/10/31)\n");\ printf("copyright (C) 2007 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; char **target_name = NULL; int n, targets = 0; struct pathnames *paths = NULL; struct pathname *path = NULL; if(root_process = geteuid() == 0) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { fputs("sqlzma_init failed", stderr); abort(); } read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/7zCrcT8.c ================================================ /* 7zCrcT8.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 #define CRC_NUM_TABLES 8 UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; void MY_FAST_CALL CrcGenerateTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } #if CRC_NUM_TABLES > 1 for (; i < 256 * CRC_NUM_TABLES; i++) { UInt32 r = g_CrcTable[i - 256]; g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); } #endif } UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { return CrcUpdateT8(v, data, size, g_CrcTable); } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Alloc.c ================================================ /* Alloc.c */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return malloc(size); } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Alloc.h ================================================ /* Alloc.h */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include <stddef.h> #include "../../Types.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c */ #include <memory.h> #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/Lzma/LzmaDecode.h" #include "../../Compress/Branch/BranchX86.h" #include "../../Compress/Branch/BranchX86_2.h" #endif #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; CFileSize Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; size_t curSize = (1 << 20); if (curSize > cb->Size) curSize = (size_t)cb->Size; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize); *size = (SizeT)processedSize; if (processedSize > curSize) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR; } #ifdef _LZMA_IN_CB SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuffer; size_t processedSize, curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)(inSize); RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize)); if (processedSize == 0) return SZE_DATA_ERROR; if (processedSize > curSize) return SZE_FAIL; memcpy(outBuffer, inBuffer, processedSize); outBuffer += processedSize; inSize -= processedSize; } return SZ_OK; } #endif #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SZ_RESULT CheckSupportedFolder(const CFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZE_NOTIMPL; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZE_NOTIMPL; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZE_NOTIMPL; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZE_NOTIMPL; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZE_NOTIMPL; return SZ_OK; } return SZE_NOTIMPL; } CFileSize GetSum(const CFileSize *values, UInt32 index) { CFileSize sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; size_t tempSizes[3] = { 0, 0, 0}; size_t tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; CFileSize offset; CFileSize inSize; Byte *outBufCur = outBuffer; size_t outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; CFileSize unpackSize = folder->UnPackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (size_t)unpackSize; if (outSizeCur != unpackSize) return SZE_OUTOFMEMORY; temp = (Byte *)allocMain->Alloc(outSizeCur); if (temp == 0 && outSizeCur != 0) return SZE_OUTOFMEMORY; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) return SZE_OUTOFMEMORY; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (size_t)unpackSize; } else return SZE_NOTIMPL; } offset = GetSum(packSizes, si); inSize = packSizes[si]; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); #endif if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); #else memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize); #endif } else { SZ_RESULT res = SzDecodeLzma(coder, inSize, #ifdef _LZMA_IN_CB inStream, #else inBuffer + (size_t)offset, #endif outBufCur, outSizeCur, allocMain); RINOK(res) } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZE_NOTIMPL; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { CFileSize offset = GetSum(packSizes, 1); CFileSize s3Size = packSizes[1]; SZ_RESULT res; if (ci != 3) return SZE_NOTIMPL; #ifdef _LZMA_IN_CB RINOK(inStream->Seek(inStream, startPos + offset)); tempSizes[2] = (size_t)s3Size; if (tempSizes[2] != s3Size) return SZE_OUTOFMEMORY; tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZE_OUTOFMEMORY; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) #endif res = x86_2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], #ifdef _LZMA_IN_CB tempBuf[2], tempSizes[2], #else inBuffer + (size_t)offset, (size_t)s3Size, #endif outBuffer, outSize); RINOK(res) } else return SZE_NOTIMPL; } return SZ_OK; } SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SZ_RESULT res = SzDecode2(packSizes, folder, #ifdef _LZMA_IN_CB inStream, startPos, #else inBuffer, #endif outBuffer, outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) allocMain->Free(tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, CFileSize startPos, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "../../7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder); size_t unPackSize = (size_t)unPackSizeSpec; CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0); #ifndef _LZMA_IN_CB Byte *inBuffer = 0; size_t processedSize; CFileSize packSizeSpec; size_t packSize; RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec)); packSize = (size_t)packSizeSpec; if (packSize != packSizeSpec) return SZE_OUTOFMEMORY; #endif if (unPackSize != unPackSizeSpec) return SZE_OUTOFMEMORY; *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, startOffset)); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc(packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, packSize, &processedSize); if (res == SZ_OK && processedSize != packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc(unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, startOffset, #else inBuffer, #endif *outBuffer, unPackSize, allocTemp); if (res == SZ_OK) { if (folder->UnPackCRCDefined) { if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC) res = SZE_CRC_ERROR; } } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZE_CRC_ERROR; } } } return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zDecode.h" #include "../../7zCrc.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { CFileSize t = size + db->Database.PackSizes[packStreamIndex + i]; if (t < size) return SZE_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { void *inBufferSpec; size_t processedSize; const Byte *inBuffer; RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize)); inBuffer = (const Byte *)inBufferSpec; if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value, UInt32 *crc) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt64)b << (8 * i)); *crc = CRC_UPDATE_BYTE(*crc, b); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, allocFunc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); MY_ALLOC(UInt32, *digests, numItems, allocFunc); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZE_NOTIMPL; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, allocFunc); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } case k7zIdLastWriteTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp->Alloc)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->IsLastWriteTimeDefined = defined; f->LastWriteTime.Low = f->LastWriteTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->LastWriteTime.Low)); RINOK(SzReadUInt32(sd, &f->LastWriteTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); allocTemp->Free(lwtVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, dataStartPos, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, allocTemp); RINOK(res) if (folder->UnPackCRCDefined) if (CrcCalc(outBuffer->Items, (size_t)unPackSize) != folder->UnPackCRC) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc = 0; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc)); crc = CRC_INIT_VAL; RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc)); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc)); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc)); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CRC_GET_DIGEST(crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { res = SZE_ARCHIVE_ERROR; if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC) { for (;;) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->IsLastWriteTimeDefined = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); typedef struct _CArchiveFileTime { UInt32 Low; UInt32 High; } CArchiveFileTime; typedef struct _CFileItem { CArchiveFileTime LastWriteTime; /* CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; Byte IsLastWriteTimeDefined; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _WIN32 #define USE_WINDOWS_FUNCTIONS #endif #ifdef USE_WINDOWS_FUNCTIONS #include <windows.h> #endif #include "7zIn.h" #include "7zExtract.h" #include "../../7zCrc.h" #ifdef USE_WINDOWS_FUNCTIONS typedef HANDLE MY_FILE_HANDLE; #else typedef FILE *MY_FILE_HANDLE; #endif void ConvertNumberToString(CFileSize value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) void ConvertFileTimeToString(CArchiveFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } #ifdef USE_WINDOWS_FUNCTIONS /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). */ #define kChunkSizeMax (1 << 24) #endif size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res || processedLoc == 0) break; } while (size > 0); return processedSize; } #else return fread(data, 1, size, file); #endif } size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size) { if (size == 0) return 0; #ifdef USE_WINDOWS_FUNCTIONS { size_t processedSize = 0; do { DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size; DWORD processedLoc = 0; BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL); data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; processedSize += processedLoc; if (!res) break; } while (size > 0); return processedSize; } #else return fwrite(data, 1, size, file); #endif } int MyCloseFile(MY_FILE_HANDLE file) { #ifdef USE_WINDOWS_FUNCTIONS return (CloseHandle(file) != FALSE) ? 0 : 1; #else return fclose(file); #endif } typedef struct _CFileInStream { ISzInStream InStream; MY_FILE_HANDLE File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = MyReadFile(s->File, buffer, size); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; #ifdef USE_WINDOWS_FUNCTIONS { LARGE_INTEGER value; value.LowPart = (DWORD)pos; value.HighPart = (LONG)((UInt64)pos >> 32); #ifdef _SZ_FILE_SIZE_32 /* VC 6.0 has bug with >> 32 shifts. */ value.HighPart = 0; #endif value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN); if (value.LowPart == 0xFFFFFFFF) if(GetLastError() != NO_ERROR) return SZE_FAIL; return SZ_OK; } #else int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; #endif } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (archiveStream.File == INVALID_HANDLE_VALUE) #else archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) #endif { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->IsLastWriteTimeDefined) ConvertFileTimeToString(&f->LastWriteTime, t); else strcpy(t, " "); printf("%10s %s %s\n", s, t, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { MY_FILE_HANDLE outputHandle; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = #ifdef USE_WINDOWS_FUNCTIONS CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (outputHandle == INVALID_HANDLE_VALUE) #else fopen(fileName, "wb+"); if (outputHandle == 0) #endif { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (MyCloseFile(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); MyCloseFile(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == (SZ_RESULT)SZE_NOTIMPL) PrintError("decoder doesn't support this archive"); else if (res == (SZ_RESULT)SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else if (res == (SZ_RESULT)SZE_CRC_ERROR) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" /* int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { return (*a1 == *a2) ? 1 : 0; } */ ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Types.h" typedef UInt64 CMethodID; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.c # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchX86_2.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/makefile ================================================ PROG = 7zDec.exe !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4 !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** C_OBJS = \ $O\7zCrc.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ $O\BranchX86.obj \ $O\BranchX86_2.obj \ $(C_OBJS) \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c $(COMPL_O2) $O\BranchX86.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c $(COMPL_O2) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c BranchX86.o: ../../Compress/Branch/BranchX86.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c $(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchARM.c ================================================ /* BranchARM.c */ #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchARM.h ================================================ /* BranchARM.h */ #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "BranchTypes.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchARMThumb.c ================================================ /* BranchARMThumb.c */ #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchARMThumb.h ================================================ /* BranchARMThumb.h */ #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "BranchTypes.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchIA64.c ================================================ /* BranchIA64.c */ #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 /* && (instNorm & 0x3F)== 0 */ ) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchIA64.h ================================================ /* BranchIA64.h */ #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "BranchTypes.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchPPC.c ================================================ /* BranchPPC.c */ #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */ if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 /* || (data[i+3] & 3) == 3 */ ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchPPC.h ================================================ /* BranchPPC.h */ #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "BranchTypes.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchSPARC.c ================================================ /* BranchSPARC.c */ #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchSPARC.h ================================================ /* BranchSPARC.h */ #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "BranchTypes.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchTypes.h ================================================ /* BranchTypes.h */ #ifndef __BRANCHTYPES_H #define __BRANCHTYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want <stddef.h> */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include <stddef.h> typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *prevMaskMix & 0x7; if (endPos < 5) return 0; nowPos += 5; prevPosT = (SizeT)0 - 1; for(;;) { Byte *p = buffer + bufferPos; Byte *limit = buffer + endPos - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - buffer); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (nowPos + (UInt32)bufferPos) + src; else dest = src - (nowPos + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #include "BranchTypes.h" #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchX86_2.c ================================================ // BranchX86_2.c #include "BranchX86_2.h" #include "../../Alloc.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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; }} #define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; } #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 #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 UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits)); // #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits)); int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *Buffer, *BufferLim; UInt32 Range, Code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; RC_INIT(buf3, size3); if (outSize == 0) return BCJ2_RESULT_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IfBit0(prob) { UpdateBit0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UpdateBit1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return BCJ2_RESULT_DATA_ERROR; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return BCJ2_RESULT_DATA_ERROR; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Branch/BranchX86_2.h ================================================ // BranchX86_2.h #ifndef __BRANCHX86_2_H #define __BRANCHX86_2_H #include "BranchTypes.h" #define BCJ2_RESULT_OK 0 #define BCJ2_RESULT_DATA_ERROR 1 /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). */ int x86_2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Huffman/HuffmanEncode.c ================================================ /* Compress/HuffmanEncode.c */ #include "HuffmanEncode.h" #include "../../Sort.h" #define kMaxLen 16 #define NUM_BITS 10 #define MASK ((1 << NUM_BITS) - 1) #define NUM_COUNTERS 64 /* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */ #define HUFFMAN_SPEED_OPT void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen) { UInt32 num = 0; /* if (maxLen > 10) maxLen = 10; */ { UInt32 i; #ifdef HUFFMAN_SPEED_OPT UInt32 counters[NUM_COUNTERS]; for (i = 0; i < NUM_COUNTERS; i++) counters[i] = 0; for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++; } for (i = 1; i < NUM_COUNTERS; i++) { UInt32 temp = counters[i]; counters[i] = num; num += temp; } for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS); } counters[0] = 0; HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]); #else for (i = 0; i < numSymbols; i++) { UInt32 freq = freqs[i]; if (freq == 0) lens[i] = 0; else p[num++] = i | (freq << NUM_BITS); } HeapSort(p, num); #endif } if (num < 2) { int minCode = 0; int maxCode = 1; if (num == 1) { maxCode = p[0] & MASK; if (maxCode == 0) maxCode++; } p[minCode] = 0; p[maxCode] = 1; lens[minCode] = lens[maxCode] = 1; return; } { UInt32 b, e, i; i = b = e = 0; do { UInt32 n, m, freq; n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq = (p[n] & ~MASK); p[n] = (p[n] & MASK) | (e << NUM_BITS); m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++; freq += (p[m] & ~MASK); p[m] = (p[m] & MASK) | (e << NUM_BITS); p[e] = (p[e] & MASK) | freq; e++; } while (num - e > 1); { UInt32 lenCounters[kMaxLen + 1]; for (i = 0; i <= kMaxLen; i++) lenCounters[i] = 0; p[--e] &= MASK; lenCounters[1] = 2; while (e > 0) { UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1; p[e] = (p[e] & MASK) | (len << NUM_BITS); if (len >= maxLen) for (len = maxLen - 1; lenCounters[len] == 0; len--); lenCounters[len]--; lenCounters[len + 1] += 2; } { UInt32 len; i = 0; for (len = maxLen; len != 0; len--) { UInt32 num; for (num = lenCounters[len]; num != 0; num--) lens[p[i++] & MASK] = (Byte)len; } } { UInt32 nextCodes[kMaxLen + 1]; { UInt32 code = 0; UInt32 len; for (len = 1; len <= kMaxLen; len++) nextCodes[len] = code = (code + lenCounters[len - 1]) << 1; } /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */ { UInt32 i; for (i = 0; i < numSymbols; i++) p[i] = nextCodes[lens[i]]++; } } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Huffman/HuffmanEncode.h ================================================ /* Compress/HuffmanEncode.h */ #ifndef __COMPRESS_HUFFMANENCODE_H #define __COMPRESS_HUFFMANENCODE_H #include "../../Types.h" /* Conditions: num <= 1024 = 2 ^ NUM_BITS Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS) maxLen <= 16 = kMaxLen Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) */ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lz/LzHash.h ================================================ /* LzHash.h */ #ifndef __C_LZHASH_H #define __C_LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \ hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lz/MatchFinder.c ================================================ /* MatchFinder.c */ /* Please call InitCrcTable before */ #include <string.h> #include "MatchFinder.h" #include "LzHash.h" #include "../../7zCrc.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); UInt32 numReadBytes; UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, size, &numReadBytes); if (p->result != SZ_OK) return; if (numReadBytes == 0) { p->streamEndWasReached = 1; return; } p->streamPos += numReadBytes; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, p->streamPos - p->pos + p->keepSizeBefore); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } void MatchFinder_Construct(CMatchFinder *p) { p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); } void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for(i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while(++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lz/MatchFinder.h ================================================ /* MatchFinder.h */ #ifndef __MATCHFINDER_H #define __MATCHFINDER_H #include "../../IStream.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; HRes result; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lz/MatchFinderMt.c ================================================ /* MatchFinderMt.c */ #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif #include "../../7zCrc.h" #include "LzHash.h" #include "MatchFinderMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks) { HRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads(name, v) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \ for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask) DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #if _MSC_VER >= 1300 #define NO_INLINE __declspec(noinline) __fastcall #else #ifdef _MSC_VER #define NO_INLINE __fastcall #endif #endif Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while(++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned StdCall BtThreadFunc2(void *p) { #ifdef USE_ALLOCA alloca(0x180); #endif BtThreadFunc((CMatchFinderMt *)p); return 0; } HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return E_INVALIDARG; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZE_OUTOFMEMORY; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZE_OUTOFMEMORY; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lz/MatchFinderMt.h ================================================ /* MatchFinderMt.h */ #ifndef __MATCHFINDERMT_H #define __MATCHFINDERMT_H #include "../../Threads.h" #include "MatchFinder.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaDecode.c ================================================ /* LzmaDecode.c LZMA Decoder (optimized for Speed version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #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; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaDecode.h ================================================ /* LzmaDecode.h LZMA Decoder interface LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 #include "LzmaTypes.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 */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #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 ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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" #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; for (;;) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H #include "LzmaTypes.h" /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/LzmaTypes.h ================================================ /* LzmaTypes.h Types for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.40 (2006-05-01) */ #ifndef __LZMATYPES_H #define __LZMATYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif /* #define _LZMA_NO_SYSTEM_SIZE_T */ /* You can use it, if you don't want <stddef.h> */ #ifndef _7ZIP_SIZET_DEFINED #define _7ZIP_SIZET_DEFINED #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else #include <stddef.h> typedef size_t SizeT; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/kmod/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> #include <pthread.h> #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/vmalloc.h> #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (unlikely(err)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima <sfjro at users dot sf dot net>"); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/kmod.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: kmod.mk,v 1.1 2007-11-05 05:43:35 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif ifndef KDir $(error KDir is not defined) endif #include makefile.gcc Kmod = kmod EXTRA_CFLAGS += -Wall -Werror -I${CURDIR} -I${Sqlzma} # -D_LZMA_PROB32 EXTRA_CFLAGS += $(shell ${CPP} ${CFLAGS} -P testflags.c) all: ${Kmod}/uncomp.c ${MAKE} EXTRA_CFLAGS="${EXTRA_CFLAGS}" M=${CURDIR}/${Kmod} \ -C ${KDir} C=0 V=0 modules ${Kmod}/uncomp.c: uncomp.c ln $< $@ clean: clean_kmod clean_kmod: ${MAKE} -C ${KDir} M=${CURDIR}/${Kmod} V=0 clean ${RM} ${Kmod}/*~ -@test -e ${Kmod}/uncomp.c && \ diff -q ${Kmod}/uncomp.c uncomp.c > /dev/null && \ find ${Kmod}/uncomp.c -links +1 | xargs -r ${RM} # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. KDir=/lib/modules/`uname -r`/build -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif #include makefile.gcc CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 ifdef KDir include kmod.mk endif ifdef UseDebugFlags DebugFlags = -O0 -g -UNDEBUG endif CFLAGS += -DNDEBUG ${DebugFlags} Tgt = libunlzma.a libunlzma_r.a all: ${Tgt} %_r.c: %.c ln $< $@ # -pthread %_r.o: CFLAGS += -D_REENTRANT -include pthread.h uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h libunlzma.a: uncomp.o LzmaDecode.o ${AR} cr $@ $^ libunlzma_r.a: uncomp_r.o LzmaDecode_r.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDecode_r.o LzmaDecode.o *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/testflags.c ================================================ #ifdef _LZMA_PROB32 -D_LZMA_PROB32 #else -U_LZMA_PROB32 #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Compress/Lzma/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> #include <pthread.h> #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/vmalloc.h> #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDecode.h" static int LzmaUncompress(struct sqlzma_un *un) { int err, i, ret; SizeT outSize, inProcessed, outProcessed, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDecoderState state; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE); src += LZMA_PROPERTIES_SIZE; if (unlikely(ret != LZMA_RESULT_OK)) goto out; i = LzmaGetNumProbs(&state.Properties); if (unlikely(i <= 0)) i = 1; i *= sizeof(CProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.Probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ err = LzmaDecode(&state, src, srclen, &inProcessed, dst, outSize, &outProcessed); if (unlikely(err)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima <sfjro at users dot sf dot net>"); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/CpuArch.h ================================================ /* CpuArch.h */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/IStream.h ================================================ /* IStream.h */ #ifndef __C_ISTREAM_H #define __C_ISTREAM_H #include "Types.h" typedef struct _ISeqInStream { HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize); } ISeqInStream; typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Sort.c ================================================ /* Sort.c */ #include "Sort.h" #define HeapSortDown(p, k, size, temp) \ { for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && p[s + 1] > p[s]) s++; \ if (temp >= p[s]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSort(UInt32 *p, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; UInt32 k = i; HeapSortDown(p, k, size, temp) } while(--i != 0); } /* do { UInt32 k = 1; UInt32 temp = p[size]; p[size--] = p[1]; HeapSortDown(p, k, size, temp) } while (size > 1); */ while (size > 3) { UInt32 temp = p[size]; UInt32 k = (p[3] > p[2]) ? 3 : 2; p[size--] = p[1]; p[1] = p[k]; HeapSortDown(p, k, size, temp) } { UInt32 temp = p[size]; p[size] = p[1]; if (size > 2 && p[2] < temp) { p[1] = p[2]; p[2] = temp; } else p[1] = temp; } } /* #define HeapSortRefDown(p, vals, n, size, temp) \ { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \ UInt32 s = (k << 1); \ if (s > size) break; \ if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ if (val >= vals[p[s]]) break; \ p[k] = p[s]; k = s; \ } p[k] = temp; } void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size) { if (size <= 1) return; p--; { UInt32 i = size / 2; do { UInt32 temp = p[i]; HeapSortRefDown(p, vals, i, size, temp); } while(--i != 0); } do { UInt32 temp = p[size]; p[size--] = p[1]; HeapSortRefDown(p, vals, 1, size, temp); } while (size > 1); } */ ================================================ FILE: src/others/squashfs-3.3-lzma/C/Sort.h ================================================ /* Sort.h */ #ifndef __7Z_Sort_H #define __7Z_Sort_H #include "Types.h" void HeapSort(UInt32 *p, UInt32 size); /* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */ #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Threads.c ================================================ /* Threads.c */ #include "Threads.h" #include <process.h> HRes GetError() { DWORD res = GetLastError(); return (res) ? (HRes)(res) : SZE_FAIL; } HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); } HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); } HRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return SZ_OK; } HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return BoolToHRes(thread->handle != 0); } HRes WaitObject(HANDLE h) { return (HRes)WaitForSingleObject(h, INFINITE); } HRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } HRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } HRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return BoolToHRes(p->handle != 0); } HRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); } HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); } HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return BoolToHRes(p->handle != 0); } HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } HRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } HRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; } return SZ_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/C/Threads.h ================================================ /* Threads.h */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include <windows.h> #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE StdCall #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); HRes Thread_Wait(CThread *thread); HRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) HRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); HRes Event_Set(CEvent *event); HRes Event_Reset(CEvent *event); HRes Event_Wait(CEvent *event); HRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); HRes Semaphore_Release1(CSemaphore *p); HRes Semaphore_Wait(CSemaphore *p); HRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; HRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/C/Types.h ================================================ /* 7zTypes.h */ #ifndef __C_TYPES_H #define __C_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED #ifdef _LZMA_UINT32_IS_ULONG typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED #ifdef _LZMA_INT32_IS_ULONG typedef long Int32; #else typedef int Int32; #endif #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED #ifdef _SZ_NO_INT_64 typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 UInt64; #else typedef unsigned long long int UInt64; #endif #endif #endif /* #define _SZ_FILE_SIZE_32 */ /* You can define _SZ_FILE_SIZE_32, if you don't need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_32 typedef UInt32 CFileSize; #else typedef UInt64 CFileSize; #endif #endif #define SZ_RESULT int typedef int HRes; #define RES_OK (0) #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_CRC_ERROR (3) #define SZE_ARCHIVE_ERROR (6) #define SZE_OUTOFMEMORY (0x8007000EL) #define SZE_NOTIMPL (0x80004001L) #define SZE_FAIL (0x80004005L) #define SZE_INVALIDARG (0x80070057L) #ifndef RINOK #define RINOK(x) { HRes __result_ = (x); if(__result_ != 0) return __result_; } #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #define StdCall __stdcall #else #define StdCall #endif #if _MSC_VER >= 1300 #define MY_FAST_CALL __declspec(noinline) __fastcall #elif defined( _MSC_VER) #define MY_FAST_CALL __fastcall #else #define MY_FAST_CALL #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "7zDecode.h" #include "../../IPassword.h" #include "../../Common/LockedStream.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unPackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &properties = coderInfo.Properties; size_t size = properties.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR password; RINOK(getTextPassword->CryptoGetTextPassword(&password)); CByteBuffer buffer; UString unicodePassword(password); const UInt32 sizeInBytes = unicodePassword.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < unicodePassword.Length(); i++) { wchar_t c = unicodePassword[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword( (const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unPackSizesPointers; packSizesPointers.Reserve(numInStreams); unPackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unPackStreamIndex++) unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unPackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Properties.SetCapacity(size); memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnPackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnPackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnPackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnPacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _database.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &database = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &database = _database; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = database.Folders[folderIndex]; UInt64 unPackSize = folderInfo.GetUnPackSize(); importantTotalUnPacked += unPackSize; extractFolderInfoVector.Back().UnPackSize = unPackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = database.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize; // Count partial_folder_size // efi.UnPackSize += unPackSize; // importantTotalUnPacked += unPackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnPacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnPacked = 0; UInt64 totalFolderUnPacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnPacked += totalFolderUnPacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnPacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnPacked = efi.UnPackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; #else const CArchiveDatabaseEx &database = _database; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = database.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&database, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = database.Folders[folderIndex]; totalFolderPacked = _database.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &database.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult( NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fileInfo = _archiveDatabase->Files[index]; UInt64 fileSize = fileInfo.UnPackSize; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fileInfo.IsFileCRCDefined && _checkCrc) digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zProperties.h" #include "../../../Common/IntToString.h" #include "../../../Common/ComTry.h" #include "../../../Windows/Defs.h" #include "../Common/ItemNameUtils.h" #ifdef _7Z_VOL #include "../Common/MultiStream.h" #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = #ifdef _7Z_VOL _refs.Size(); #else *numItems = _database.Files.Size(); #endif return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _database.Folders.Size(); i++) { const CFolder &f = _database.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _database.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop) { if (timeDefined) prop = unixTime; } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; #ifndef _SFX static inline UInt32 GetUInt32FromMemLE(const Byte *p) { return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); } #endif bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ #ifdef _7Z_VOL const CRef &ref = _refs[index]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &_database = volume.Database; UInt32 index2 = ref.ItemIndex; const CFileItem &item = _database.Files[index2]; #else const CFileItem &item = _database.Files[index]; UInt32 index2 = index; #endif switch(propID) { case kpidPath: { if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; } case kpidIsFolder: prop = item.IsDirectory; break; case kpidSize: { prop = item.UnPackSize; // prop = ref2.UnPackSize; break; } case kpidPosition: { /* if (ref2.Refs.Size() > 1) prop = ref2.StartPos; else */ if (item.IsStartPosDefined) prop = item.StartPos; break; } case kpidPackedSize: { // prop = ref2.PackSize; { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _database.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidLastAccessTime: MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop); break; case kpidCreationTime: MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop); break; case kpidLastWriteTime: MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop); break; case kpidAttributes: if (item.AreAttributesDefined) prop = item.Attributes; break; case kpidCRC: if (item.IsFileCRCDefined) prop = item.FileCRC; break; case kpidEncrypted: { prop = IsEncrypted(index2); break; } #ifndef _SFX case kpidMethod: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Properties.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Properties.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Properties; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUInt32FromMemLE( ((const Byte *)coderInfo.Properties + 1)); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Properties.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Properties; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Properties.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Properties.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Properties[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _database.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _database.Folders[folderIndex]; if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif case kpidIsAnti: prop = item.IsAnti; break; } prop.Detach(value); return S_OK; COM_TRY_END } #ifdef _7Z_VOL static const wchar_t *kExt = L"7z"; static const wchar_t *kAfterPart = L".7z"; class CVolumeName { bool _first; UString _unchangedPart; UString _changedPart; UString _afterPart; public: bool InitName(const UString &name) { _first = true; int dotPos = name.ReverseFind('.'); UString basePart = name; if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (ext.CompareNoCase(kExt)==0 || ext.CompareNoCase(L"EXE") == 0) { _afterPart = kAfterPart; basePart = name.Left(dotPos); } } int numLetters = 1; bool splitStyle = false; if (basePart.Right(numLetters) == L"1") { while (numLetters < basePart.Length()) { if (basePart[basePart.Length() - numLetters - 1] != '0') break; numLetters++; } } else return false; _unchangedPart = basePart.Left(basePart.Length() - numLetters); _changedPart = basePart.Right(numLetters); return true; } UString GetNextName() { UString newName; // if (_newStyle || !_first) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = UString(c) + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } _changedPart = newName; } _first = false; return _unchangedPart + _changedPart + _afterPart; } }; #endif STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifdef _7Z_VOL CVolumeName seqName; CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; #endif #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif #ifdef _7Z_VOL if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback); } for (;;) { CMyComPtr<IInStream> inStream; if (!_volumes.IsEmpty()) { if (!openVolumeCallback) break; if(_volumes.Size() == 1) { UString baseName; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) break; baseName = prop.bstrVal; } seqName.InitName(baseName); } UString fullName = seqName.GetNextName(); HRESULT result = openVolumeCallback->GetStream(fullName, &inStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; } else inStream = stream; CInArchive archive; RINOK(archive.Open(inStream, maxCheckStartPosition)); _volumes.Add(CVolume()); CVolume &volume = _volumes.Back(); CArchiveDatabaseEx &database = volume.Database; volume.Stream = inStream; volume.StartRef2Index = _refs.Size(); HRESULT result = archive.ReadDatabase(database #ifndef _NO_CRYPTO , getTextPassword #endif ); if (result != S_OK) { _volumes.Clear(); return result; } database.Fill(); for(int i = 0; i < database.Files.Size(); i++) { CRef refNew; refNew.VolumeIndex = _volumes.Size() - 1; refNew.ItemIndex = i; _refs.Add(refNew); /* const CFileItem &file = database.Files[i]; int j; */ /* for (j = _refs.Size() - 1; j >= 0; j--) { CRef2 &ref2 = _refs[j]; const CRef &ref = ref2.Refs.Back(); const CVolume &volume2 = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database2 = volume2.Database; const CFileItem &file2 = database2.Files[ref.ItemIndex]; if (file2.Name.CompareNoCase(file.Name) == 0) { if (!file.IsStartPosDefined) continue; if (file.StartPos != ref2.StartPos + ref2.UnPackSize) continue; ref2.Refs.Add(refNew); break; } } */ /* j = -1; if (j < 0) { CRef2 ref2New; ref2New.Refs.Add(refNew); j = _refs.Add(ref2New); } CRef2 &ref2 = _refs[j]; ref2.UnPackSize += file.UnPackSize; ref2.PackSize += database.GetFilePackSize(i); if (ref2.Refs.Size() == 1 && file.IsStartPosDefined) ref2.StartPos = file.StartPos; */ } if (database.Files.Size() != 1) break; const CFileItem &file = database.Files.Front(); if (!file.IsStartPosDefined) break; } #else CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _database #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); _database.Fill(); _inStream = stream; #endif } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN #ifdef _7Z_VOL _volumes.Clear(); _refs.Clear(); #else _inStream.Release(); _database.Clear(); #endif return S_OK; COM_TRY_END } #ifdef _7Z_VOL STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; UInt64 pos = 0; const UString *fileName; for (int i = 0; i < _refs.Size(); i++) { const CRef &ref = _refs[i]; const CVolume &volume = _volumes[ref.VolumeIndex]; const CArchiveDatabaseEx &database = volume.Database; const CFileItem &file = database.Files[ref.ItemIndex]; if (i == 0) fileName = &file.Name; else if (fileName->Compare(file.Name) != 0) return S_FALSE; if (!file.IsStartPosDefined) return S_FALSE; if (file.StartPos != pos) return S_FALSE; CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex]; if (folderIndex == kNumNoIndex) { if (file.UnPackSize != 0) return E_FAIL; continue; } if (database.NumUnPackStreamsVector[folderIndex] != 1) return S_FALSE; const CFolder &folder = database.Folders[folderIndex]; if (folder.Coders.Size() != 1) return S_FALSE; const CCoderInfo &coder = folder.Coders.Front(); if (coder.NumInStreams != 1 || coder.NumOutStreams != 1) return S_FALSE; if (coder.MethodID != k_Copy) return S_FALSE; pos += file.UnPackSize; CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = volume.Stream; subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0); subStreamInfo.Size = file.UnPackSize; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } #endif #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifdef _7Z_VOL struct CRef { int VolumeIndex; int ItemIndex; }; struct CVolume { int StartRef2Index; CMyComPtr<IInStream> Stream; CArchiveDatabaseEx Database; }; #endif #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef _7Z_VOL public IInArchiveGetStream, #endif #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef _7Z_VOL MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream) #endif #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef _7Z_VOL STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); #endif #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: #ifdef _7Z_VOL CObjectVector<CVolume> _volumes; CObjectVector<CRef> _refs; #else CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _database; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForHeaders; oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = UInt32(kNumFastBytesForHeaders); oneMethodInfo.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = UInt32(kDictionaryForHeaders); oneMethodInfo.Properties.Add(property); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Properties = oneMethodInfo.Properties; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Properties.Size(); j++) { const CProp &prop = methodFull.Properties[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(index, propID, &propVariant)); if (propVariant.vt == VT_FILETIME) { filetime = propVariant.filetime; filetimeIsDefined = true; } else if (propVariant.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *database = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); database = &volume->Database; } #else if (_inStream != 0) database = &_database; #endif // CRecordVector<bool> compressStatuses; CObjectVector<CUpdateItem> updateItems; // CRecordVector<UInt32> copyIndices; // CMyComPtr<IUpdateCallback2> updateCallback2; // updateCallback->QueryInterface(&updateCallback2); for(UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem updateItem; updateItem.NewProperties = IntToBool(newProperties); updateItem.NewData = IntToBool(newData); updateItem.IndexInArchive = indexInArchive; updateItem.IndexInClient = i; updateItem.IsAnti = false; updateItem.Size = 0; if (updateItem.IndexInArchive != -1) { const CFileItem &fileItem = database->Files[updateItem.IndexInArchive]; updateItem.Name = fileItem.Name; updateItem.IsDirectory = fileItem.IsDirectory; updateItem.Size = fileItem.UnPackSize; updateItem.IsAnti = fileItem.IsAnti; updateItem.CreationTime = fileItem.CreationTime; updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined; updateItem.LastWriteTime = fileItem.LastWriteTime; updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined; updateItem.LastAccessTime = fileItem.LastAccessTime; updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined; } if (updateItem.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.AttributesAreDefined = false; else if (propVariant.vt != VT_UI4) return E_INVALIDARG; else { updateItem.Attributes = propVariant.ulVal; updateItem.AttributesAreDefined = true; } } RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined)); RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined)); { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant)); if (propVariant.vt == VT_EMPTY) nameIsDefined = false; else if (propVariant.vt != VT_BSTR) return E_INVALIDARG; else { updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant)); if (propVariant.vt == VT_EMPTY) folderStatusIsDefined = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else { updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant)); if (propVariant.vt == VT_EMPTY) updateItem.IsAnti = false; else if (propVariant.vt != VT_BOOL) return E_INVALIDARG; else updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE); } if (updateItem.IsAnti) { updateItem.AttributesAreDefined = false; updateItem.IsCreationTimeDefined = false; updateItem.IsLastWriteTimeDefined = false; updateItem.IsLastAccessTimeDefined = false; updateItem.Size = 0; } if (!folderStatusIsDefined && updateItem.AttributesAreDefined) updateItem.SetDirectoryStatusFromAttributes(); } if (updateItem.NewData) { NCOM::CPropVariant propVariant; RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant)); if (propVariant.vt != VT_UI8) return E_INVALIDARG; updateItem.Size = (UInt64)propVariant.uhVal.QuadPart; if (updateItem.Size != 0 && updateItem.IsAnti) return E_INVALIDARG; } updateItems.Add(updateItem); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it if (methodMode.PasswordIsDefined) { compressMainHeader = true; if(_encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || (methodMode.PasswordIsDefined && _encryptHeaders)) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteModified = WriteModified; options.HeaderOptions.WriteCreated = WriteCreated; options.HeaderOptions.WriteAccessed = WriteAccessed; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; return Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? database: 0, #else _inStream, database, #endif updateItems, outStream, updateCallback, options); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnPackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnPackSize, kNumUnPackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCreationTime, kLastAccessTime, kLastWriteTime, kWinAttributes, kComment, kEncodedHeader, kStartPos }; } }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" #include "7zIn.h" #include "7zDecode.h" #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" extern "C" { #include "../../../../C/7zCrc.h" } // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define SZ_LITTLE_ENDIAN_UNALIGN #endif #ifdef SZ_LITTLE_ENDIAN_UNALIGN static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; } static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; } static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; } #else static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); } static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); } static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); } #endif Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = GetUInt32FromMem(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = GetUInt64FromMem(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)GetUInt16FromMem(buf); p[i] = 0; s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { UInt32 processedSize; RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize)); if (processedSize != kHeaderSize) return S_FALSE; if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; UInt32 numReadBytes = kBufferSize - numPrevBytes; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); UInt32 numBytesInBuffer = numPrevBytes + processedSize; if (numBytesInBuffer < kHeaderSize) break; UInt32 numTests = numBytesInBuffer - kHeaderSize + 1; for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) { if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } numPrevBytes = numBytesInBuffer - numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propertiesSize = ReadNum(); coder.Properties.SetCapacity((size_t)propertiesSize); ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs; numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bindPair; bindPair.InIndex = ReadNum(); bindPair.OutIndex = ReadNum(); folder.BindPairs.Add(bindPair); } CNum numPackedStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackedStreams); if (numPackedStreams == 1) { for (CNum j = 0; j < numInStreams; j++) if (folder.FindBindPairForInStream(j) < 0) { folder.PackStreams.Add(j); break; } } else for(i = 0; i < numPackedStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for(int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { packCRCsDefined.Reserve(numPackStreams); packCRCsDefined.Clear(); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for(CNum i = 0; i < numPackStreams; i++) { packCRCsDefined.Add(false); packCRCs.Add(0); } } } void CInArchive::ReadUnPackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for(CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnPackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnPackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnPackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CRecordVector<bool> crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for(i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnPackCRCDefined = crcsDefined[i]; folder.UnPackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { numUnPackStreamsInFolders.Clear(); numUnPackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnPackStream) { for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnPackStreamsInFolders.IsEmpty()) for(int i = 0; i < folders.Size(); i++) numUnPackStreamsInFolders.Add(1); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unPackSizes.Add(size); sum += size; } unPackSizes.Add(folders[i].GetUnPackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for(i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnPackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnPackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnPackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { digestsDefined.Clear(); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) { digestsDefined.Add(false); digests.Add(0); } } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnPackInfo: { ReadUnPackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for(int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt32 type) { CBoolVector boolVector; ReadBoolVector2(files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; fileTime.dwLowDateTime = 0; fileTime.dwHighDateTime = 0; bool defined = boolVector[i]; if (defined) { fileTime.dwLowDateTime = ReadUInt32(); fileTime.dwHighDateTime = ReadUInt32(); } switch(type) { case NID::kCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case NID::kLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case NID::kLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { CRecordVector<UInt64> packSizes; CRecordVector<bool> packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnPackStreamsInFolders; CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for(int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unPackSize64 = folder.GetUnPackSize(); size_t unPackSize = (size_t)unPackSize64; if (unPackSize != unPackSize64) ThrowUnsupported(); data.SetCapacity(unPackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unPackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnPackCRCDefined) if (CrcCalc(data, unPackSize) != folder.UnPackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) dataStartPos += packSizes[packIndex++]; } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(database.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, database.ArchiveInfo.DataStartPosition, database.PackSizes, database.PackCRCsDefined, database.PackCRCs, database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests); database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for(int i = 0; i < database.Folders.Size(); i++) { database.NumUnPackStreamsVector.Add(1); CFolder &folder = database.Folders[i]; unPackSizes.Add(folder.GetUnPackSize()); digestsDefined.Add(folder.UnPackCRCDefined); digests.Add(folder.UnPackCRC); } } database.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); database.Files.Reserve(numFiles); CNum i; for(i = 0; i < numFiles; i++) database.Files.Add(CFileItem()); database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!database.PackSizes.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; emptyStreamVector.Reserve((int)numFiles); for(i = 0; i < numFiles; i++) emptyStreamVector.Add(false); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(int i = 0; i < database.Files.Size(); i++) _inByteBack->ReadString(database.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.AreAttributesDefined = boolVector[i]; if (file.AreAttributesDefined) file.Attributes = ReadUInt32(); } break; } case NID::kStartPos: { CBoolVector boolVector; ReadBoolVector2(database.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.IsStartPosDefined = boolVector[i]; if (file.IsStartPosDefined) file.StartPos = ReadUInt64(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; emptyFileVector.Reserve(numEmptyStreams); antiFileVector.Reserve(numEmptyStreams); for (i = 0; i < numEmptyStreams; i++) { emptyFileVector.Add(false); antiFileVector.Add(false); } break; } case NID::kEmptyFile: { ReadBoolVector(numEmptyStreams, emptyFileVector); break; } case NID::kAnti: { ReadBoolVector(numEmptyStreams, antiFileVector); break; } case NID::kCreationTime: case NID::kLastWriteTime: case NID::kLastAccessTime: { ReadTime(dataVector, database.Files, (UInt32)type); break; } default: isKnownType = false; } if (isKnownType) database.ArchiveInfo.FileInfoPopIDs.Add(type); else SkeepData(size); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem &file = database.Files[i]; file.HasStream = !emptyStreamVector[i]; if(file.HasStream) { file.IsDirectory = false; file.IsAnti = false; file.UnPackSize = unPackSizes[sizeIndex]; file.FileCRC = digests[sizeIndex]; file.IsFileCRCDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDirectory = !emptyFileVector[emptyFileIndex]; file.IsAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.UnPackSize = 0; file.IsFileCRCDefined = false; } } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for(int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for(int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnPackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnPackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { database.Clear(); database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; database.ArchiveInfo.Version.Major = _header[6]; database.ArchiveInfo.Version.Minor = _header[7]; if (database.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = GetUInt32FromMem(_header + 8); UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC); UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14); UInt32 nextHeaderCRC = GetUInt32FromMem(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); UInt32 realProcessedSize; RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize)); int i; for (i = (int)realProcessedSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = realProcessedSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); UInt32 realProcessedSize; RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize)); if (realProcessedSize != (UInt32)nextHeaderSize) return S_FALSE; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; for (;;) { UInt64 type = ReadID(); if (type == NID::kHeader) break; if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS database.ArchiveInfo.StartPositionAfterHeader, database.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); } return ReadHeader( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS database #ifndef _NO_CRYPTO , getTextPassword #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IStream.h" #include "../../IPassword.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; size_t _pos; public: void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnPackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CRecordVector<bool> &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnPackStreamsInFolders, CRecordVector<UInt64> &unPackSizes, CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadTime(const CObjectVector<CByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt32 type); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &database #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Properties; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnPackSizes; UInt32 UnPackCRC; bool UnPackCRCDefined; CFolder(): UnPackCRCDefined(false) {} UInt64 GetUnPackSize() const // test it { if (UnPackSizes.IsEmpty()) return 0; for (int i = UnPackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnPackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } }; typedef FILETIME CArchiveFileTime; class CFileItem { public: CArchiveFileTime CreationTime; CArchiveFileTime LastWriteTime; CArchiveFileTime LastAccessTime; UInt64 UnPackSize; UInt64 StartPos; UInt32 Attributes; UInt32 FileCRC; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDirectory; bool IsAnti; bool IsFileCRCDefined; bool AreAttributesDefined; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsStartPosDefined; /* const bool HasStream() const { return !IsDirectory && !IsAnti && UnPackSize != 0; } */ CFileItem(): HasStream(true), IsDirectory(false), IsAnti(false), IsFileCRCDefined(false), AreAttributesDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false), IsStartPosDefined(false) {} void SetAttributes(UInt32 attributes) { AreAttributesDefined = true; Attributes = attributes; } void SetCreationTime(const CArchiveFileTime &creationTime) { IsCreationTimeDefined = true; CreationTime = creationTime; } void SetLastWriteTime(const CArchiveFileTime &lastWriteTime) { IsLastWriteTimeDefined = true; LastWriteTime = lastWriteTime; } void SetLastAccessTime(const CArchiveFileTime &lastAccessTime) { IsLastAccessTimeDefined = true; LastAccessTime = lastAccessTime; } }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnPackStreamsVector; CObjectVector<CFileItem> Files; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnPackStreamsVector.Clear(); Files.Clear(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnPackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool IsSolid() const { for (int i = 0; i < NumUnPackStreamsVector.Size(); i++) if (NumUnPackStreamsVector[i] > 1) return true; return false; } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if(processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 value) { for (int i = 0; i < 4; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } UInt32 CrcUpdateUInt64(UInt32 crc, UInt64 value) { for (int i = 0; i < 8; i++, value >>= 8) crc = CRC_UPDATE_BYTE(crc, (Byte)value); return crc; } HRESULT COutArchive::WriteDirectUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteDirectUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { RINOK(WriteDirectByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteSignature() { RINOK(WriteDirect(kSignature, kSignatureSize)); RINOK(WriteDirectByte(kMajorVersion)); return WriteDirectByte(2); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { UInt32 crc = CRC_INIT_VAL; crc = CrcUpdateUInt64(crc, h.NextHeaderOffset); crc = CrcUpdateUInt64(crc, h.NextHeaderSize); crc = CrcUpdateUInt32(crc, h.NextHeaderCRC); RINOK(WriteDirectUInt32(CRC_GET_DIGEST(crc))); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); return WriteDirectUInt32(h.NextHeaderCRC); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } HRESULT COutArchive::WriteBytes(const void *data, size_t size) { if (_mainMode) { if (_dynamicMode) _dynamicBuffer.Write(data, size); else _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else { if (_countMode) _countSize += size; else RINOK(_outByte2.Write(data, size)); } return S_OK; } HRESULT COutArchive::WriteBytes(const CByteBuffer &data) { return WriteBytes(data, data.GetCapacity()); } HRESULT COutArchive::WriteByte(Byte b) { return WriteBytes(&b, 1); } HRESULT COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } HRESULT COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } RINOK(WriteByte(firstByte)); for (;i > 0; i--) { RINOK(WriteByte((Byte)value)); value >>= 8; } return S_OK; } #ifdef _7Z_VOL static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 0; i < 8; i++) if (value < ((UInt64(1) << ( 7 * (i + 1))))) break; return 1 + i; } UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif HRESULT COutArchive::WriteFolder(const CFolder &folder) { RINOK(WriteNumber(folder.Coders.Size())); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propertiesSize = coder.Properties.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propertiesSize != 0) ? 0x20 : 0 ); RINOK(WriteByte(b)); RINOK(WriteBytes(longID, idSize)); if (isComplex) { RINOK(WriteNumber(coder.NumInStreams)); RINOK(WriteNumber(coder.NumOutStreams)); } if (propertiesSize == 0) continue; RINOK(WriteNumber(propertiesSize)); RINOK(WriteBytes(coder.Properties, propertiesSize)); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; RINOK(WriteNumber(bindPair.InIndex)); RINOK(WriteNumber(bindPair.OutIndex)); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { RINOK(WriteNumber(folder.PackStreams[i])); } return S_OK; } HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for(int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { RINOK(WriteByte(b)); mask = 0x80; b = 0; } } if (mask != 0x80) { RINOK(WriteByte(b)); } return S_OK; } HRESULT COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for(i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return S_OK; RINOK(WriteByte(NID::kCRC)); if (numDefined == digestsDefined.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(digestsDefined)); } for(i = 0; i < digests.Size(); i++) { if(digestsDefined[i]) RINOK(WriteUInt32(digests[i])); } return S_OK; } HRESULT COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kPackInfo)); RINOK(WriteNumber(dataOffset)); RINOK(WriteNumber(packSizes.Size())); RINOK(WriteByte(NID::kSize)); for(int i = 0; i < packSizes.Size(); i++) RINOK(WriteNumber(packSizes[i])); RINOK(WriteHashDigests(packCRCsDefined, packCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteUnPackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return S_OK; RINOK(WriteByte(NID::kUnPackInfo)); RINOK(WriteByte(NID::kFolder)); RINOK(WriteNumber(folders.Size())); { RINOK(WriteByte(0)); for(int i = 0; i < folders.Size(); i++) RINOK(WriteFolder(folders[i])); } RINOK(WriteByte(NID::kCodersUnPackSize)); int i; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnPackSizes.Size(); j++) RINOK(WriteNumber(folder.UnPackSizes[j])); } CRecordVector<bool> unPackCRCsDefined; CRecordVector<UInt32> unPackCRCs; for(i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unPackCRCsDefined.Add(folder.UnPackCRCDefined); unPackCRCs.Add(folder.UnPackCRC); } RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { RINOK(WriteByte(NID::kSubStreamsInfo)); int i; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) { if (numUnPackStreamsInFolders[i] != 1) { RINOK(WriteByte(NID::kNumUnPackStream)); for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) RINOK(WriteNumber(numUnPackStreamsInFolders[i])); break; } } bool needFlag = true; CNum index = 0; for(i = 0; i < numUnPackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++) { if (j + 1 != numUnPackStreamsInFolders[i]) { if (needFlag) RINOK(WriteByte(NID::kSize)); needFlag = false; RINOK(WriteNumber(unPackSizes[index])); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnPackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnPackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } RINOK(WriteHashDigests(digestsDefined2, digests2)); return WriteByte(NID::kEnd); } HRESULT COutArchive::WriteTime( const CObjectVector<CFileItem> &files, Byte type) { ///////////////////////////////////////////////// // CreationTime CBoolVector boolVector; boolVector.Reserve(files.Size()); bool thereAreDefined = false; bool allDefined = true; int i; for(i = 0; i < files.Size(); i++) { const CFileItem &item = files[i]; bool defined; switch(type) { case NID::kCreationTime: defined = item.IsCreationTimeDefined; break; case NID::kLastWriteTime: defined = item.IsLastWriteTimeDefined; break; case NID::kLastAccessTime: defined = item.IsLastAccessTimeDefined; break; default: throw 1; } boolVector.Add(defined); thereAreDefined = (thereAreDefined || defined); allDefined = (allDefined && defined); } if (!thereAreDefined) return S_OK; RINOK(WriteByte(type)); size_t dataSize = 1 + 1; dataSize += files.Size() * 8; if (allDefined) { RINOK(WriteNumber(dataSize)); WriteByte(1); } else { RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize)); WriteByte(0); RINOK(WriteBoolVector(boolVector)); } RINOK(WriteByte(0)); for(i = 0; i < files.Size(); i++) { if (boolVector[i]) { const CFileItem &item = files[i]; CArchiveFileTime timeValue; timeValue.dwLowDateTime = 0; timeValue.dwHighDateTime = 0; switch(type) { case NID::kCreationTime: timeValue = item.CreationTime; break; case NID::kLastWriteTime: timeValue = item.LastWriteTime; break; case NID::kLastAccessTime: timeValue = item.LastAccessTime; break; } RINOK(WriteUInt32(timeValue.dwLowDateTime)); RINOK(WriteUInt32(timeValue.dwHighDateTime)); } } return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnPackCRCDefined = true; folderItem.UnPackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } static void WriteUInt32ToBuffer(Byte *data, UInt32 value) { for (int i = 0; i < 4; i++) { *data++ = (Byte)value; value >>= 8; } } static void WriteUInt64ToBuffer(Byte *data, UInt64 value) { for (int i = 0; i < 8; i++) { *data++ = (Byte)value; value >>= 8; } } HRESULT COutArchive::WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; ///////////////////////////////// // Names CNum numDefinedNames = 0; size_t namesDataSize = 0; for(i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; if (!name.IsEmpty()) numDefinedNames++; namesDataSize += (name.Length() + 1) * 2; } CByteBuffer namesData; if (numDefinedNames > 0) { namesData.SetCapacity((size_t)namesDataSize); size_t pos = 0; for(int i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; for (int t = 0; t < name.Length(); t++) { wchar_t c = name[t]; namesData[pos++] = Byte(c); namesData[pos++] = Byte(c >> 8); } namesData[pos++] = 0; namesData[pos++] = 0; } } ///////////////////////////////// // Write Attributes CBoolVector attributesBoolVector; attributesBoolVector.Reserve(database.Files.Size()); int numDefinedAttributes = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].AreAttributesDefined; attributesBoolVector.Add(defined); if (defined) numDefinedAttributes++; } CByteBuffer attributesData; if (numDefinedAttributes > 0) { attributesData.SetCapacity(numDefinedAttributes * 4); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.AreAttributesDefined) { WriteUInt32ToBuffer(attributesData + pos, file.Attributes); pos += 4; } } } ///////////////////////////////// // Write StartPos CBoolVector startsBoolVector; startsBoolVector.Reserve(database.Files.Size()); int numDefinedStarts = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].IsStartPosDefined; startsBoolVector.Add(defined); if (defined) numDefinedStarts++; } CByteBuffer startsData; if (numDefinedStarts > 0) { startsData.SetCapacity(numDefinedStarts * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsStartPosDefined) { WriteUInt64ToBuffer(startsData + pos, file.StartPos); pos += 8; } } } ///////////////////////////////// // Write Last Write Time // /* CNum numDefinedLastWriteTimes = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].IsLastWriteTimeDefined) numDefinedLastWriteTimes++; if (numDefinedLastWriteTimes > 0) { CByteBuffer lastWriteTimeData; lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsLastWriteTimeDefined) { WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime); pos += 4; WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime); pos += 4; } } } // */ UInt64 packedSize = 0; for(i = 0; i < database.PackSizes.Size(); i++) packedSize += database.PackSizes[i]; headerOffset = packedSize; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; RINOK(WriteByte(NID::kHeader)); // Archive Properties if (database.Folders.Size() > 0) { RINOK(WriteByte(NID::kMainStreamsInfo)); RINOK(WritePackInfo(0, database.PackSizes, database.PackCRCsDefined, database.PackCRCs)); RINOK(WriteUnPackInfo(database.Folders)); CRecordVector<UInt64> unPackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) continue; unPackSizes.Add(file.UnPackSize); digestsDefined.Add(file.IsFileCRCDefined); digests.Add(file.FileCRC); } RINOK(WriteSubStreamsInfo( database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests)); RINOK(WriteByte(NID::kEnd)); } if (database.Files.IsEmpty()) { RINOK(WriteByte(NID::kEnd)); return _outByte.Flush(); } RINOK(WriteByte(NID::kFilesInfo)); RINOK(WriteNumber(database.Files.Size())); CBoolVector emptyStreamVector; emptyStreamVector.Reserve(database.Files.Size()); int numEmptyStreams = 0; for(i = 0; i < database.Files.Size(); i++) if (database.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { RINOK(WriteByte(NID::kEmptyStream)); RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyStreamVector)); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDirectory); if (!file.IsDirectory) numEmptyFiles++; antiVector.Add(file.IsAnti); if (file.IsAnti) numAntiItems++; } } if (numEmptyFiles > 0) { RINOK(WriteByte(NID::kEmptyFile)); RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyFileVector)); } if (numAntiItems > 0) { RINOK(WriteByte(NID::kAnti)); RINOK(WriteNumber((antiVector.Size() + 7) / 8)); RINOK(WriteBoolVector(antiVector)); } } if (numDefinedNames > 0) { ///////////////////////////////////////////////// RINOK(WriteByte(NID::kName)); { RINOK(WriteNumber(1 + namesData.GetCapacity())); RINOK(WriteByte(0)); RINOK(WriteBytes(namesData)); } } if (headerOptions.WriteCreated) { RINOK(WriteTime(database.Files, NID::kCreationTime)); } if (headerOptions.WriteModified) { RINOK(WriteTime(database.Files, NID::kLastWriteTime)); } if (headerOptions.WriteAccessed) { RINOK(WriteTime(database.Files, NID::kLastAccessTime)); } if (numDefinedAttributes > 0) { RINOK(WriteByte(NID::kWinAttributes)); size_t size = 2; if (numDefinedAttributes != database.Files.Size()) size += (attributesBoolVector.Size() + 7) / 8 + 1; size += attributesData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedAttributes == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(attributesBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(attributesData)); } } if (numDefinedStarts > 0) { RINOK(WriteByte(NID::kStartPos)); size_t size = 2; if (numDefinedStarts != database.Files.Size()) size += (startsBoolVector.Size() + 7) / 8 + 1; size += startsData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedStarts == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(startsBoolVector)); } { RINOK(WriteByte(0)); RINOK(WriteBytes(startsData)); } } RINOK(WriteByte(NID::kEnd)); // for files RINOK(WriteByte(NID::kEnd)); // for headers return _outByte.Flush(); } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (database.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { _dynamicBuffer.Init(); _dynamicMode = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) _dynamicMode = true; RINOK(WriteHeader(database, headerOptions, headerOffset)); if (_dynamicMode) { CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, _dynamicBuffer, _dynamicBuffer.GetSize(), packSizes, folders)); _dynamicMode = false; _mainMode = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; if (folders.Size() == 0) throw 1; RINOK(WriteID(NID::kEncodedHeader)); RINOK(WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>())); RINOK(WriteUnPackInfo(folders)); RINOK(WriteByte(NID::kEnd)); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; RINOK(_outByte.Flush()); } headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" #include "../../../Common/DynamicBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _pos = 0; _data = data; _size = size; } HRESULT Write(const void *data, size_t size) { if (_pos + size > _size) return E_FAIL; memmove(_data + _pos, data, size); _pos += size; return S_OK; } }; class CWriteDynamicBuffer { CByteDynamicBuffer _buffer; size_t _pos; public: CWriteDynamicBuffer(): _pos(0) {} void Init() { _pos = 0; } void Write(const void *data, size_t size) { if (_pos + size > _buffer.GetCapacity()) _buffer.EnsureCapacity(_pos + size); memmove(((Byte *)_buffer) +_pos, data, size); _pos += size; } operator Byte *() { return (Byte *)_buffer; }; operator const Byte *() const { return (const Byte *)_buffer; }; size_t GetSize() const { return _pos; } }; struct CHeaderOptions { // bool UseAdditionalHeaderStreams; bool CompressMainHeader; bool WriteModified; bool WriteCreated; bool WriteAccessed; CHeaderOptions(): // UseAdditionalHeaderStreams(false), CompressMainHeader(true), WriteModified(true), WriteCreated(false), WriteAccessed(false) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); } HRESULT WriteDirectUInt32(UInt32 value); HRESULT WriteDirectUInt64(UInt64 value); HRESULT WriteBytes(const void *data, size_t size); HRESULT WriteBytes(const CByteBuffer &data); HRESULT WriteByte(Byte b); HRESULT WriteUInt32(UInt32 value); HRESULT WriteNumber(UInt64 value); HRESULT WriteID(UInt64 value) { return WriteNumber(value); } HRESULT WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); HRESULT WriteBoolVector(const CBoolVector &boolVector); HRESULT WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); HRESULT WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); HRESULT WriteUnPackInfo(const CObjectVector<CFolder> &folders); HRESULT WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); /* HRESULT WriteStreamsInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs, bool externalFolders, UInt64 externalFoldersStreamIndex, const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnPackStreamsInFolders, const CRecordVector<UInt64> &unPackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); */ HRESULT WriteTime(const CObjectVector<CFileItem> &files, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT WriteHeader( const CArchiveDatabase &database, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _mainMode; bool _dynamicMode; bool _countMode; size_t _countSize; COutBuffer _outByte; CWriteBufferLoc _outByte2; CWriteDynamicBuffer _dynamicBuffer; UInt32 _crc; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &database, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME}, { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME}, { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, // { 97, NULL, kpidSolid, VT_BOOL}, #ifndef _SFX { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_database = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // UpdateMain.cpp #include "StdAfx.h" #include "7zUpdate.h" #include "7zFolderInStream.h" #include "7zEncode.h" #include "7zHandler.h" #include "7zOut.h" #include "../../Compress/Copy/CopyCoder.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LimitedStreams.h" #include "../Common/ItemNameUtils.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Properties, c2.Properties); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnPackStreamsVector[i1], db.NumUnPackStreamsVector[i2])); if (db.NumUnPackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { UInt32 Index; const CUpdateItem *UpdateItem; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType): Index(index), UpdateItem(&updateItem), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(updateItem.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = updateItem.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = updateItem.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = updateItem.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDirectory != u2.IsDirectory) return (u1.IsDirectory) ? 1 : -1; if (u1.IsDirectory) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined) RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp property; property.Id = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kMatchFinder; property.Value = kMatchFinderForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kDictionarySize; property.Value = kDictionaryForBCJ2_LZMA; methodFull.Properties.Add(property); } { CProp property; property.Id = NCoderPropID::kNumFastBytes; property.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Properties.Add(property); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (!updateItem.NewData) continue; if (!updateItem.HasStream()) continue; if (useFilters) { const UString name = updateItem.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &updateItem, CFileItem &file) { file.Name = NItemName::MakeLegalName(updateItem.Name); if (updateItem.AttributesAreDefined) file.SetAttributes(updateItem.Attributes); if (updateItem.IsCreationTimeDefined) file.SetCreationTime(updateItem.CreationTime); if (updateItem.IsLastWriteTimeDefined) file.SetLastWriteTime(updateItem.LastWriteTime); if (updateItem.IsLastAccessTimeDefined) file.SetLastAccessTime(updateItem.LastAccessTime); file.UnPackSize = updateItem.Size; file.IsDirectory = updateItem.IsDirectory; file.IsAnti = updateItem.IsAnti; file.HasStream = updateItem.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = database != 0 ? database->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (database != 0) { fileIndexToUpdateIndexMap.Reserve(database->Files.Size()); for (int i = 0; i < database->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (database != 0) { for(i = 0; i < database->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnPackStreams = database->NumUnPackStreamsVector[i]; for (CNum fileIndex = database->FolderStartFileIndex[i]; indexInFolder < numUnPackStreams; fileIndex++) { if (database->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnPackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)database); } CArchiveDatabase newDatabase; //////////////////////////// COutArchive archive; RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += database->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { complexity += updateItem.Size; if (numSolidFiles == 1) { if (updateItem.Size > inSizeForReduce) inSizeForReduce = updateItem.Size; } else inSizeForReduce += updateItem.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = database->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, database->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = database->Folders[folderIndex]; CNum startIndex = database->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex]; newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); CNum indexInFolder = 0; for (CNum fi = database->FolderStartFileIndex[folderIndex]; indexInFolder < numUnPackStreams; fi++) { CFileItem file = database->Files[fi]; if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &updateItem = updateItems[updateIndex]; if (updateItem.NewProperties) { CFileItem file2; FromUpdateItemToFileItem(updateItem, file2); file2.UnPackSize = file.UnPackSize; file2.FileCRC = file.FileCRC; file2.IsFileCRCDefined = file.IsFileCRCDefined; file2.HasStream = file.HasStream; file = file2; } } newDatabase.Files.Add(file); } } } ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &updateItem = updateItems[index]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database.Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]]; totalSize += updateItem.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = updateItem.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnPackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnPackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &updateItem = updateItems[indices[i + subIndex]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.FileCRC = inStreamSpec->CRCs[subIndex]; file.UnPackSize = inStreamSpec->Sizes[subIndex]; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { file.IsFileCRCDefined = false; file.HasStream = false; } newDatabase.Files.Add(file); } // numUnPackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); i += numSubFiles; } } { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &updateItem = updateItems[i]; if (updateItem.NewData) { if (updateItem.HasStream()) continue; } else if (updateItem.IndexInArchive != -1) if (database->Files[updateItem.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for(i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &updateItem = updateItems[emptyRefs[i]]; CFileItem file; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; newDatabase.Files.Add(file); } } /* if (newDatabase.Files.Size() != updateItems.Size()) return E_FAIL; */ return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); } #ifdef _7Z_VOL static const UInt64 k_Copy = 0x0; static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options) { CCoderInfo coder; coder.NumInStreams = coder.NumOutStreams = 1; coder.MethodID = k_Copy; CFolder folder; folder.Coders.Add(coder); folder.PackStreams.Add(0); CNum numUnPackStreams = 0; if (file.UnPackSize != 0) { file.IsFileCRCDefined = true; file.HasStream = true; numUnPackStreams++; } else { throw 1; file.IsFileCRCDefined = false; file.HasStream = false; } folder.UnPackSizes.Add(file.UnPackSize); CArchiveDatabase newDatabase; newDatabase.Files.Add(file); newDatabase.Folders.Add(folder); newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams); newDatabase.PackSizes.Add(file.UnPackSize); newDatabase.PackCRCsDefined.Add(false); newDatabase.PackCRCs.Add(file.FileCRC); return archive.WriteDatabase(newDatabase, options.HeaderMethod, false, false); } HRESULT UpdateVolume( IInStream *inStream, const CArchiveDatabaseEx *database, CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { if (updateItems.Size() != 1) return E_NOTIMPL; CMyComPtr<IArchiveUpdateCallback2> volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; CMyComPtr<ISequentialInStream> fileStream; HRESULT result = updateCallback->GetStream(0, &fileStream); if (result != S_OK && result != S_FALSE) return result; if (result == S_FALSE) return E_FAIL; CFileItem file; const CUpdateItem &updateItem = updateItems[0]; if (updateItem.NewProperties) FromUpdateItemToFileItem(updateItem, file); else file = database->Files[updateItem.IndexInArchive]; if (file.IsAnti || file.IsDirectory) return E_FAIL; UInt64 complexity = 0; file.IsStartPosDefined = true; file.StartPos = 0; for (UInt64 volumeIndex = 0; true; volumeIndex++) { UInt64 volSize; RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize)); UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true); CMyComPtr<ISequentialOutStream> volumeStream; RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream)); COutArchive archive; RINOK(archive.Create(volumeStream, true)); RINOK(archive.SkeepPrefixArchiveHeader()); CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC; CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec; inCrcStreamSpec->Init(fileStream); RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity)); file.UnPackSize = inCrcStreamSpec->GetSize(); if (file.UnPackSize == 0) break; file.FileCRC = inCrcStreamSpec->GetCRC(); RINOK(WriteVolumeHeader(archive, file, options)); file.StartPos += file.UnPackSize; if (file.UnPackSize < pureSize) break; } return S_OK; } class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (!_volumeStream) { RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize)); RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream)); _volIndex++; _curPos = 0; RINOK(_archive.Create(_volumeStream, true)); RINOK(_archive.SkeepPrefixArchiveHeader()); _crc.Init(); continue; } UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length()); UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos); _crc.Update(data, curSize); UInt32 realProcessed; RINOK(_volumeStream->Write(data, curSize, &realProcessed)) data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _curPos += realProcessed; if (realProcessed != curSize && realProcessed == 0) return E_FAIL; if (_curPos == pureSize) { RINOK(Flush()); } } return S_OK; } #endif HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { #ifdef _7Z_VOL if (seqOutStream) #endif return Update2( EXTERNAL_CODECS_LOC_VARS inStream, database, updateItems, seqOutStream, updateCallback, options); #ifdef _7Z_VOL if (options.VolumeMode) return UpdateVolume(inStream, database, updateItems, seqOutStream, updateCallback, options); COutVolumeStream *volStreamSpec = new COutVolumeStream; CMyComPtr<ISequentialOutStream> volStream = volStreamSpec; CMyComPtr<IArchiveUpdateCallback2> volumeCallback; RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback)); if (!volumeCallback) return E_NOTIMPL; volStreamSpec->Init(volumeCallback, L"a.7z"); volStreamSpec->_options = options; RINOK(Update2(inStream, database, updateItems, volStream, updateCallback, options)); return volStreamSpec->Flush(); #endif } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { bool NewData; bool NewProperties; int IndexInArchive; int IndexInClient; UInt32 Attributes; FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt64 Size; UString Name; bool IsAnti; bool IsDirectory; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool AttributesAreDefined; bool HasStream() const { return !IsDirectory && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), AttributesAreDefined(false), IsCreationTimeDefined(false), IsLastWriteTimeDefined(false), IsLastAccessTimeDefined(false) {} void SetDirectoryStatusFromAttributes() { IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *database, const CObjectVector<CUpdateItem> &updateItems, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (UInt32 i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL) return result; } for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOutCommon.cpp #include "StdAfx.h" #include "HandlerOut.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ParseProperties.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Properties.Size(); j++) if (oneMethodInfo.Properties[j].Id == propID) return; CProp property; property.Id = propID; property.Value = value; oneMethodInfo.Properties.Add(property); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp property; if ( name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); if (name.CompareNoCase(L"D") == 0) property.Id = NCoderPropID::kDictionarySize; else property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { bool res; if (StringToBool(s, res)) { if (res) InitSolid(); else _numSolidFiles = 1; return S_OK; } UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: InitSolid(); return S_OK; case VT_BSTR: return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeaders = false; WriteModified = true; WriteCreated = false; WriteAccessed = false; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) return SetBoolProperty(_encryptHeaders, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteModified, value); if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCreated, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteAccessed, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp property; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); property.Id = NCoderPropID::kDictionarySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); property.Id = NCoderPropID::kUsedMemorySize; property.Value = dicSize; oneMethodInfo.Properties.Add(property); if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; property.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, property.Value)) return E_INVALIDARG; oneMethodInfo.Properties.Add(property); } } return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../Common/MethodProps.h" #include "../../Common/CreateCoder.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Properties; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeaders; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; DECL_EXTERNAL_CODECS_VARS }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUTSTREAMWITHCRC_H #define __OUTSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE; STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) PURE; // GetStream OUT: S_OK - OK, S_FALSE - skeep this file STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE; STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE; }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, // 1 - new data, 0 - old data Int32 *newProperties, // 1 - new properties, 0 - old properties UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter ) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult) PURE; }; ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE; STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE; }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFDecoder.h # End Source File # Begin Source File SOURCE=..\..\Common\MSBFEncoder.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86.h # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\Branch\x86_2.h # End Source File # End Group # Begin Group "Copy" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Copy\CopyRegister.cpp # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMAEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA\LZMARegister.cpp # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.cpp !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 Debug" !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # ADD CPP /O1 !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" !ENDIF # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(C_OBJS) \ $(C_BRANCH_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ BRANCH_OPT_OBJS = \ $O\BranchCoder.obj \ $O\x86.obj \ $O\x86_2.obj \ $O\ARM.obj \ $O\ARMThumb.obj \ $O\IA64.obj \ $O\PPC.obj \ $O\SPARC.obj \ $O\BranchRegister.obj \ $O\BCJRegister.obj \ $O\BCJ2Register.obj \ SWAP_OPT_OBJS = \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ COPY_OBJS = \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ $O\LZMARegister.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Sort.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ C_BRANCH_OBJS = \ $O\BranchARM.obj \ $O\BranchARMThumb.obj \ $O\BranchIA64.obj \ $O\BranchPPC.obj \ $O\BranchSPARC.obj \ $O\BranchX86.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(BZIP2_OBJS) \ $(BZIP2_OPT_OBJS) \ $(COMPRESS_OBJS) \ $(BRANCH_OPT_OBJS) \ $(SWAP_OPT_OBJS) \ $(COPY_OBJS) \ $(DEFLATE_OPT_OBJS) \ $(LZ_OBJS) \ $(LZMA_OPT_OBJS) \ $(PPMD_OPT_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $(C_BRANCH_OBJS) \ $O\RangeCoderBit.obj \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL) $(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp $(COMPL_O2) $(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp $(COMPL_O2) $(COPY_OBJS): ../../Compress/Copy/$(*B).cpp $(COMPL) $(LZ_OBJS): ../../Compress/LZ/$(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp $(COMPL_O2) $O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) $(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/7z/7z.ico" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return lastError; #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return File.SetTime(creationTime, lastAccessTime, lastWriteTime); } bool SetLastWriteTime(const FILETIME *lastWriteTime) { return File.SetLastWriteTime(lastWriteTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } UInt32 processedSize = 0; RINOK(WriteStream(outStream, _buffer, size, &processedSize)); if (size != processedSize) return E_FAIL; _nowPos64 += processedSize; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { UInt32 processedSize; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize)); UInt32 endPos = bufferPos + processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } UInt32 processedSize; RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize)); if (_bufferPos != processedSize) return E_FAIL; _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; UInt32 processedSizeTemp; UInt32 size0 = kBufferSize - _bufferPos; // Optimize it: RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp)); _bufferPos = _bufferPos + processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "MethodProps.h" #include "../../Common/MyCom.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProperties = method.Properties.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProperties != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties]; HRESULT res = S_OK; try { for (int i = 0; i < numProperties; i++) { const CProp &prop = method.Properties[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "MethodId.h" #include "../../Windows/PropVariant.h" #include "../../Common/MyVector.h" #include "../ICoder.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Properties; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { MoveMemory(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 numBytesToRead = (UInt32)(MyMin(_pos + size, _size) - _pos); memmove(data, _dataPointer + _pos, numBytesToRead); _pos += numBytesToRead; if(processedSize != NULL) *processedSize = numBytesToRead; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memmove(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 newSize = size; if (_pos + size > _size) newSize = (UInt32)(_size - _pos); memmove(_buffer + _pos, data, newSize); if(processedSize != NULL) *processedSize = newSize; _pos += newSize; if (newSize != size) return E_FAIL; return S_OK; } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } HRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); HRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARM.h" } UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" extern "C" { #include "../../../../C/Compress/Branch/BranchARMThumb.h" } UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86_2.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "x86.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "PPC.h" #include "IA64.h" #include "ARM.h" #include "ARMThumb.h" #include "SPARC.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC_B) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMThumb) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC_B, 0x02, 0x05, L"BC_PPC_B"), METHOD_ITEM(BC_IA64, 0x04, 1, L"BC_IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"BC_ARM"), METHOD_ITEM(BC_ARMThumb,0x07, 1, L"BC_ARMThumb"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"BC_SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" extern "C" { #include "../../../../C/Compress/Branch/BranchIA64.h" } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchPPC.h" } UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" extern "C" { #include "../../../../C/Compress/Branch/BranchSPARC.h" } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" extern "C" { #include "../../../../C/Alloc.h" } namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h ================================================ // ByteSwap.h #ifndef __BYTESWAP_H #define __BYTESWAP_H #include "../../ICoder.h" #include "Common/MyCom.h" // {23170F69-40C1-278B-0203-020000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap2, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); // {23170F69-40C1-278B-0203-040000000000} DEFINE_GUID(CLSID_CCompressConvertByteSwap4, 0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00); class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (UInt32 i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/Alloc.h" } #include "CopyCoder.h" #include "../../Common/StreamUtils.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Copy/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPYCODER_H #define __COMPRESS_COPYCODER_H #include "../../ICoder.h" #include "../../../Common/MyCom.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Copy/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/Copy/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" #ifndef _NO_EXCEPTIONS typedef COutBufferException CLZOutWindowException; #endif class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (distance >= _pos) { if (!_overDict || distance >= _bufferSize) return false; pos += _bufferSize; } if (_limitPos - _pos > len && _bufferSize - pos > len) { const Byte *src = _buffer + pos; Byte *dest = _buffer + _pos; _pos += len; do *dest++ = *src++; while(--len != 0); } else do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); for (;;) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" extern "C" { #include "../../../../C/Alloc.h" } #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include <stdio.h> #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // extern "C" { #include "../../../../C/7zCrc.h" } // #define SHOW_STAT namespace NCompress { namespace NLZMA { // struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit; const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = kNumLogBits * 2; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; #endif void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < kNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < kNumLowSymbols + kNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); } for (; i < numSymbols; i++) prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _matchFinderCycles(0), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { MatchFinder_Construct(&_matchFinderBase); // _maxMode = false; _fastMode = false; #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&_matchFinderMt); _matchFinderMt.MatchFinder = &_matchFinderBase; #endif } static void *SzAlloc(size_t size) { return BigAlloc(size); } static void SzFree(void *address) { BigFree(address); } ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::~CEncoder() { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc); #endif MatchFinder_Free(&_matchFinderBase, &g_Alloc); } static const UInt32 kBigHashDicLimit = (UInt32)1 << 24; HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; bool btMode = (_matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT _mtMode = (_multiThread && !_fastMode && btMode); #endif if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit); UInt32 numCycles = 16 + (_numFastBytes >> 1); if (!btMode) numCycles >>= 1; if (_matchFinderCycles != 0) numCycles = _matchFinderCycles; _matchFinderBase.cutValue = numCycles; #ifdef COMPRESS_MF_MT if (_mtMode) { RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)); _matchFinderObj = &_matchFinderMt; MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder); } else #endif { if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc)) return E_OUTOFMEMORY; _matchFinderObj = &_matchFinderBase; MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder); } return S_OK; } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); /* int skipModeBitsLoc = 0; if (c == L'D') { skipModeBitsLoc = 2; c = GetUpperChar(*s++); } */ if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; // *skipModeBits = skipModeBitsLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kMatchFinderCycles: { if (prop.vt != VT_UI4) return E_INVALIDARG; _matchFinderCycles = prop.ulVal; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); // _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; } case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kNumThreads: { if (prop.vt != VT_UI4) return E_INVALIDARG; #ifdef COMPRESS_MF_MT Bool newMultiThread = (prop.ulVal > 1) ? True : False; if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } #endif break; } case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } #ifdef SHOW_STAT static int ttt = 0; #endif void CEncoder::MovePos(UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { _additionalOffset += num; _matchFinder.Skip(_matchFinderObj, num); } } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; const Byte *data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = *data; Byte matchByte = *(data - (reps[0] + 1)); if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)-1; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); COptimal &optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while(--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > matchDistances[offs]) offs += 2; for(; ; len++) { UInt32 distance = matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); COptimal &optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + kNumRepDistances; optimum.Prev1IsChar = false; } if (len == matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; for (;;) { cur++; if(cur == lenEnd) { return Backward(backRes, cur); } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 newLen, numDistancePairs; newLen = ReadMatchDistances(numDistancePairs); if(newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 curPrice = curOptimum.Price; const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; const Byte currentByte = *data; const Byte matchByte = *(data - (reps[0] + 1)); UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } /* if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) // speed optimization { // try Literal + rep0 const Byte *data2 = data - (reps[0] + 1); UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); UInt32 temp; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++); while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 lenTestTemp = lenTest; UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while(startLen > matchDistances[offs]) offs += 2; UInt32 curBack = matchDistances[offs + 1]; UInt32 posSlot = GetPosSlot2(curBack); for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice; UInt32 lenToPosState = GetLenToPosState(lenTest); if (curBack < kNumFullDistances) curAndLenPrice += _distancesPrices[lenToPosState][curBack]; else curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (/*_maxMode && */lenTest == matchDistances[offs]) { // Try Match + Literal + Rep0 const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( true, data2[lenTest], data[lenTest]); state2.UpdateChar(); posStateNext = (posStateNext + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = cur + lenTest + 1 + lenTest2; while(lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; curBack = matchDistances[offs + 1]; if (curBack >= kNumFullDistances) posSlot = GetPosSlot2(curBack); } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { return ((bigDist >> 7) > smallDist); } UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs) { UInt32 lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2); if (ttt >= 61994) ttt = ttt; ttt++; for (UInt32 i = 0; i < numDistancePairs; i += 2) printf("%2d %6d | ", _matchDistances[i], _matchDistances[i + 1]); #endif if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) { UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1; const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; UInt32 distance = _matchDistances[numDistancePairs - 1] + 1; if (numAvail > kMatchMaxLen) numAvail = kMatchMaxLen; const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } _additionalOffset++; return lenRes; } UInt32 CEncoder::GetOptimumFast(UInt32 &backRes) { UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; if (numAvailableBytes > kMatchMaxLen) numAvailableBytes = kMatchMaxLen; if (numAvailableBytes < 2) { backRes = (UInt32)(-1); return 1; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if(len >= _numFastBytes) { backRes = i; MovePos(len - 1); return len; } repLens[i] = len; if (len > repLens[repMaxIndex]) repMaxIndex = i; } UInt32 *matchDistances = _matchDistances; if(lenMain >= _numFastBytes) { backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; MovePos(lenMain - 1); return lenMain; } UInt32 backMain = 0; // for GCC if (lenMain >= 2) { backMain = matchDistances[numDistancePairs - 1]; while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) { if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) break; numDistancePairs -= 2; lenMain = matchDistances[numDistancePairs - 2]; backMain = matchDistances[numDistancePairs - 1]; } if (lenMain == 2 && backMain >= 0x80) lenMain = 1; } if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2 && numAvailableBytes > 2) { numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj); _longestMatchLength = ReadMatchDistances(_numDistancePairs); if (_longestMatchLength >= 2) { UInt32 newDistance = matchDistances[_numDistancePairs - 1]; if (_longestMatchLength >= lenMain && newDistance < backMain || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1; for(UInt32 i = 0; i < kNumRepDistances; i++) { const Byte *data2 = data - (_repDistances[i] + 1); if (data[1] != data2[1] || data[2] != data2[2]) { repLens[i] = 0; continue; } UInt32 len; for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++); if (len + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); return 1; } } backRes = backMain + kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = UInt32(-1); return 1; } HRESULT CEncoder::Flush(UInt32 nowPos) { // ReleaseMFStream(); if (_matchFinderBase.result != SZ_OK) return _matchFinderBase.result; WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { // _needReleaseMFStream = false; #ifdef COMPRESS_MF_MT #ifdef USE_ALLOCA alloca(0x300); #endif #endif CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); for (;;) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) break; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } return S_OK; } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; return S_OK; } static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize) { return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize); } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { _seqInStream.RealStream = _inStream; _seqInStream.SeqInStream.Read = MyRead; _matchFinderBase.stream = &_seqInStream.SeqInStream; _matchFinder.Init(_matchFinderObj); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return _matchFinderBase.result; _finished = true; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush((UInt32)nowPos64); UInt32 len, numDistancePairs; len = ReadMatchDistances(numDistancePairs); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } UInt32 nowPos32 = (UInt32)nowPos64; UInt32 progressPosValuePrev = nowPos32; if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); for (;;) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos, len; if (_fastMode) len = GetOptimumFast(pos); else len = GetOptimum(nowPos32, pos); UInt32 posState = nowPos32 & _posStateMask; if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); if(_state.IsCharState()) subCoder->Encode(&_rangeEncoder, curByte); else { Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); } else { UInt32 distance = _repDistances[pos]; _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); if (pos == 3) _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; } _repDistances[1] = _repDistances[0]; _repDistances[0] = distance; } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); _state.UpdateRep(); } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); _alignPriceCount++; } } _repDistances[3] = _repDistances[2]; _repDistances[2] = _repDistances[1]; _repDistances[1] = _repDistances[0]; _repDistances[0] = pos; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos32 += len; if (_additionalOffset == 0) { if (!_fastMode) { if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= kAlignTableSize) FillAlignPrices(); } if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0) return Flush(nowPos32); if (nowPos32 - progressPosValuePrev >= (1 << 14)) { nowPos64 += nowPos32 - progressPosValuePrev; *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); _finished = false; *finished = 0; return _matchFinderBase.result; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillDistancesPrices() { UInt32 tempPrices[kNumFullDistances]; for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] = encoder.GetPrice(posSlot); for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); UInt32 *distancesPrices = _distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../ICoder.h" extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/Compress/Lz/MatchFinder.h" #ifdef COMPRESS_MF_MT #include "../../../../C/Compress/Lz/MatchFinderMt.h" #endif } #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; // #define LZMA_LOG_BRANCH #if _MSC_VER >= 1400 // Must give gain in core 2. but slower ~2% on k8. // #define LZMA_LOG_BSR #endif #ifndef LZMA_LOG_BSR static const int kNumLogBits = 13; // don't change it ! extern Byte g_FastPos[]; #endif inline UInt32 GetPosSlot(UInt32 pos) { #ifdef LZMA_LOG_BSR if (pos < 2) return pos; unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else if (pos < (1 << kNumLogBits)) return g_FastPos[pos]; if (pos < (1 << (kNumLogBits * 2 - 1))) return g_FastPos[pos >> (kNumLogBits - 1)] + (kNumLogBits - 1) * 2; return g_FastPos[pos >> (kNumLogBits - 1) * 2] + (kNumLogBits - 1) * 4; #endif } inline UInt32 GetPosSlot2(UInt32 pos) { #ifdef LZMA_LOG_BSR unsigned long index; _BitScanReverse(&index, pos); return (index + index) + ((pos >> (index - 1)) & 1); #else #ifdef LZMA_LOG_BRANCH if (pos < (1 << (kNumLogBits + 6))) return g_FastPos[pos >> 6] + 12; if (pos < (1 << (kNumLogBits * 2 + 5))) return g_FastPos[pos >> (kNumLogBits + 5)] + (kNumLogBits + 5) * 2; return g_FastPos[pos >> (kNumLogBits * 2 + 4)] + (kNumLogBits * 2 + 4) * 2; #else // it's faster with VC6-32bit. UInt32 s = 6 + ((kNumLogBits - 1) & (UInt32)((Int32)(((1 << (kNumLogBits + 6)) - 1) - pos) >> 31)); return g_FastPos[pos >> s] + (s * 2); #endif #endif } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices[posState]); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) { CEncoder::Encode(rangeEncoder, symbol, posState); if (updatePrice) if (--_counters[posState] == 0) UpdateTable(posState); } }; } typedef struct _CSeqInStream { ISeqInStream SeqInStream; CMyComPtr<ISequentialInStream> RealStream; } CSeqInStream; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { NRangeCoder::CEncoder _rangeEncoder; IMatchFinder _matchFinder; void *_matchFinderObj; #ifdef COMPRESS_MF_MT Bool _multiThread; Bool _mtMode; CMatchFinderMt _matchFinderMt; #endif CMatchFinder _matchFinderBase; #ifdef COMPRESS_MF_MT Byte _pad1[kMtCacheLineDummy]; #endif COptimal _optimum[kNumOpts]; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; bool _fastMode; // bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _matchPriceCount; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; CSeqInStream _seqInStream; UInt32 _matchFinderCycles; // int _numSkip bool _writeEndMark; bool _needReleaseMFStream; void ReleaseMatchFinder() { _matchFinder.Init = 0; _seqInStream.RealStream.Release(); } void ReleaseMFStream() { if (_matchFinderObj && _needReleaseMFStream) { #ifdef COMPRESS_MF_MT if (_mtMode) MatchFinderMt_ReleaseStream(&_matchFinderMt); #endif _needReleaseMFStream = false; } _seqInStream.RealStream.Release(); } UInt32 ReadMatchDistances(UInt32 &numDistancePairs); void MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const { UInt32 price; if(repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + GetPureRepPrice(repIndex, state, posState); } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); UInt32 GetOptimum(UInt32 position, UInt32 &backRes); UInt32 GetOptimumFast(UInt32 &backRes); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp ================================================ // LZMARegister.cpp #include "StdAfx.h" #include "../../Common/RegisterCodec.h" #include "LZMADecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CDecoder); } #ifndef EXTRACT_ONLY #include "LZMAEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "C-Lz" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lzma\LzmaTypes.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBenchCon.h" #include "LzmaRam.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif #include "../../MyVersion.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kMatchFinderCycles, kLitContext, kLitPos, kPosBits, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary - [0,30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = (UInt32)-1; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dictionary); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 1; UInt32 numFastBytes = 128; UInt32 matchFinderCycles = 16 + numFastBytes / 2; bool matchFinderCyclesDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs; if (matchFinderCyclesDefined) if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionary; properties[1].ulVal = (UInt32)posStateBits; properties[2].ulVal = (UInt32)litContextBits; properties[3].ulVal = (UInt32)litPosBits; properties[4].ulVal = (UInt32)algorithm; properties[5].ulVal = (UInt32)numFastBytes; properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; properties[8].vt = VT_UI4; properties[8].ulVal = (UInt32)numThreads; // it must be last in property list properties[9].vt = VT_UI4; properties[9].ulVal = (UInt32)matchFinderCycles; int numProps = kNumPropsMax; if (!matchFinderCyclesDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/Alloc.h" #include "../../../../C/7zCrc.h" } #include "../../../Common/MyCom.h" #include "../../ICoder.h" #ifdef BENCH_MT #include "../../../Windows/Thread.h" #include "../../../Windows/Synchronization.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #else #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); // UInt64 numCommandsForOne = 1000 + ((t * t * 7) >> (2 * kSubBits)); // AMD K8 UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); // Intel Core2 UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { // UInt64 numCommands = (inSize * 216 + outSize * 14) * numIterations; // AMD K8 UInt64 numCommands = (inSize * 220 + outSize * 8) * numIterations; // Intel Core2 return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLZMA::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLZMA::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { size_t allocaSize = ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF; HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , allocaSize #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../../../../C/Compress/Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { if (size > (Size - Pos)) size = (UInt32)(Size - Pos); for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZ_RAM_E_FAIL (1) #define SZ_RAM_E_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZ_RAM_E_OUTOFMEMORY; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZ_RAM_E_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1); } size_t minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZ_RAM_E_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZ_RAM_E_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZ_RAM_E_OUTOFMEMORY; } #endif } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include <stdlib.h> #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../../../../C/Compress/Lzma/LzmaDecode.h" #include "../../../../C/Compress/Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(outBuffer, (SizeT)outSizeProcessedLoc, 0, &x86State, 0); } return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include <stdlib.h> /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/comp.cc ================================================ /* * Copyright (C) 2006-2007 Junjiro Okajima * Copyright (C) 2006-2007 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: comp.cc,v 1.3 2007-11-13 13:27:23 jro Exp $ */ // extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <errno.h> #include "StdAfx.h" #include "../../../Common/MyInitGuid.h" //#include "../../../Common/MyWindows.h" #include "../../../Common/StringConvert.h" //#include "../../../Common/StringToInt.h" //#include "../../Common/StreamUtils.h" #include "../LZMA/LZMAEncoder.h" #include <pthread.h> #include <zlib.h> #include "sqlzma.h" ////////////////////////////////////////////////////////////////////// class CMemoryStream { protected: Bytef *m_data; UInt64 m_limit; UInt64 m_pos; public: CMemoryStream(Bytef *data, UInt64 size) : m_data(data), m_limit(size), m_pos(0) {} virtual ~CMemoryStream() {} }; class CInMemoryStream : public CMemoryStream, public IInStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialInStream> m_stream; public: MY_UNKNOWN_IMP1(IInStream); CInMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~CInMemoryStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { UInt64 room = m_limit - m_pos; if (size > room) size = room; if (size) { memcpy(data, m_data + m_pos, size); m_pos += size; } if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } }; class COutMemoryStream : public CMemoryStream, public IOutStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialOutStream> m_stream; public: MY_UNKNOWN_IMP1(IOutStream); COutMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~COutMemoryStream() {} UInt32 GetSize() {return m_pos;} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (m_pos + size > m_limit) return -ENOSPC; memcpy(m_data + m_pos, data, size); m_pos += size; if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } STDMETHOD(SetSize)(Int64 newSize) { assert(0); return E_NOTIMPL; } }; ////////////////////////////////////////////////////////////////////// static int LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, struct sqlzma_opts *opts, uLong *total_out) { int err; HRESULT res; const Byte a[] = { avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, 0, 0, 0, 0 }; NCompress::NLZMA::CEncoder encoderSpec; CMyComPtr<ICompressCoder> encoder = &encoderSpec; encoder->AddRef(); CInMemoryStream inStreamSpec(next_in, avail_in); CMyComPtr<ISequentialInStream> inStream = &inStreamSpec; inStream->AddRef(); COutMemoryStream outStreamSpec(next_out, avail_out); CMyComPtr<ISequentialOutStream> outStream = &outStreamSpec; outStream->AddRef(); // these values are dpending upon is_lzma() macro in sqlzma.h const UInt32 dictionary = opts->dicsize; //fprintf(stderr, "dic %u\n", dictionary); const UString mf = L"BT4"; const UInt32 posStateBits = 2; const UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data const UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data //const UInt32 algorithm = 2; const UInt32 algorithm = 1; const UInt32 numFastBytes = 128; const UInt32 matchFinderCycles = 16 + numFastBytes / 2; //const bool matchFinderCyclesDefined = false; const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_FALSE; // EOS properties[8].vt = VT_UI4; properties[8].ulVal = 1; // numThreads properties[9].vt = VT_UI4; properties[9].ulVal = UInt32(matchFinderCycles); err = -EINVAL; res = encoderSpec.SetCoderProperties(propIDs, properties, kNumPropsMax - 1); if (res) goto out; res = encoderSpec.WriteCoderProperties(outStream); if (res) goto out; UInt32 r; res = outStream->Write(a, sizeof(a), &r); if (res || r != sizeof(a)) goto out; err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); if (err) goto out; *total_out = outStreamSpec.GetSize(); out: return err; } ////////////////////////////////////////////////////////////////////// #define Failure(p) do { \ fprintf(stderr, "%s:%d: please report to jro " \ "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ __func__, __LINE__, \ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ abort(); \ } while(0) extern "C" int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out) { int err; Bytef *p = next_out; uInt l = avail_out; stream->next_in = next_in; stream->avail_in = avail_in; stream->next_out = p; stream->avail_out = l; err = deflate(stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) goto out_err; if (avail_in < stream->total_out) return err; if (is_lzma(*p)) Failure(p); if (opts->try_lzma) { unsigned char a[stream->total_out]; uLong processed; memcpy(a, p, stream->total_out); // malloc family in glibc and stdc++ seems to be thread-safe err = LzmaCompress(next_in, avail_in, p, l, opts, &processed); if (!err && processed <= stream->total_out) { if (!is_lzma(*next_out)) Failure(next_out); stream->total_out = processed; err = Z_STREAM_END; } else { //puts("by zlib"); memcpy(p, a, stream->total_out); err = Z_STREAM_END; } } return err; out_err: fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); return err; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LIBS = $(LIBS) oleaut32.lib user32.lib !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope -W4 -Wp64 -DUNICODE -D_UNICODE !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZOutWindow.obj \ C_OBJS = \ $O\Alloc.obj \ $O\7zCrc.obj \ $O\Threads.obj \ C_LZ_OBJS = \ $O\MatchFinder.obj \ $O\MatchFinderMt.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $(C_OBJS) \ $(C_LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../../../../C/Compress/Lzma/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../../../../C/Compress/Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaRam.o \ LZMADecoder.o \ LZMAEncoder.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ BranchX86.o \ MatchFinder.o \ LzmaDecode.o \ LzmaRamDecode.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c BranchX86.o: ../../../../C/Compress/Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Branch/BranchX86.c MatchFinder.o: ../../../../C/Compress/Lz/MatchFinder.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lz/MatchFinder.c LzmaDecode.o: ../../../../C/Compress/Lzma/LzmaDecode.c $(CXX_C) $(CFLAGS) ../../../../C/Compress/Lzma/LzmaDecode.c LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef UseDebugFlags DebugFlags = -Wall -O0 -g -UNDEBUG endif # -pthread CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} Tgt = liblzma_r.a all: ${Tgt} RObjs = LZMAEncoder_r.o Alloc_r.o StreamUtils_r.o MatchFinder_r.o \ RangeCoderBit_r.o OutBuffer_r.o 7zCrc_r.o %_r.cc: ../LZMA/%.cpp ln $< $@ %_r.c: ../../../../C/%.c ln $< $@ %_r.c: ../../../../C/Compress/Lz/%.c ln $< $@ %_r.cc: ../../Common/%.cpp ln $< $@ %_r.cc: ../RangeCoder/%.cpp ln $< $@ LZMAEncoder_r.o: CXXFLAGS += -I../LZMA Alloc_r.o: CFLAGS += -I../../../../C StreamUtils_r.o: CXXFLAGS += -I../../Common MatchFinder_r.o: CFLAGS += -I../../../../C/Compress/Lz RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder OutBuffer_r.o: CXXFLAGS += -I../../Common 7zCrc_r.o: CFLAGS += -I../../../../C comp.o: CXXFLAGS += -I${Sqlzma} comp.o: comp.cc ${Sqlzma}/sqlzma.h liblzma_r.a: ${RObjs} comp.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) comp.o *_r.o ${Tgt} *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template <int numMoveBits, int NumBitLevels> class CBitTreeEncoder { CBitEncoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template <int numMoveBits, int NumBitLevels> class CBitTreeDecoder { CBitDecoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template <int numMoveBits> void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template <int numMoveBits> UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template <int numMoveBits> UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" DECL_INTERFACE(IProgress, 0, 5) { STDMETHOD(SetTotal)(UInt64 total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 57 #define MY_VER_BUILD 0 #define MY_VERSION "4.57" #define MY_7ZIP_VERSION "7-Zip 4.57" #define MY_DATE "2007-12-06" #define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/PropID.h ================================================ // Interface/PropID.h #ifndef __INTERFACE_PROPID_H #define __INTERFACE_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsFolder, kpidSize, kpidPackedSize, kpidAttributes, kpidCreationTime, kpidLastAccessTime, kpidLastWriteTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubFolders, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME UTCLastWriteTime; UInt32 Attributes; bool IsDirectory; bool AttributesAreDefined; bool UTCLastWriteTimeIsDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant)); UString fullPath; if(propVariant.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if(propVariant.vt != VT_BSTR) return E_FAIL; fullPath = propVariant.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attributes NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant)); if (propVariant.vt == VT_EMPTY) { _processedFileInfo.Attributes = 0; _processedFileInfo.AttributesAreDefined = false; } else { if (propVariant.vt != VT_UI4) throw "incorrect item"; _processedFileInfo.Attributes = propVariant.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); { // Get Modified Time NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant)); _processedFileInfo.UTCLastWriteTimeIsDefined = false; switch(propVariant.vt) { case VT_EMPTY: // _processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault; break; case VT_FILETIME: _processedFileInfo.UTCLastWriteTime = propVariant.filetime; _processedFileInfo.UTCLastWriteTimeIsDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant propVariant; RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant)); bool newFileSizeDefined = (propVariant.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(propVariant); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.IsDirectory) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.UTCLastWriteTimeIsDefined) _outFileStreamSpec->SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if(newData != NULL) *newData = BoolToInt(true); if(newProperties != NULL) *newProperties = BoolToInt(true); if(indexInArchive != NULL) *indexInArchive = UInt32(-1); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = false; propVariant.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } propVariant.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if(dirItem.IsDirectory()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ////////////////////////////////////////////////////////////////////////// // Main function int #ifdef _MSC_VER __cdecl #endif main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.CompareNoCase("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem item; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(name, fileInfo)) { PrintString(UString(L"Can't find file") + name); return 1; } item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = name; item.FullPath = name; dirItems.Add(item); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.CompareNoCase("l") == 0) listCommand = true; else if (command.CompareNoCase("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidSize, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant propVariant; archive->GetProperty(i, kpidPath, &propVariant); UString s = ConvertPropVariantToString(propVariant); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, kPassword, kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for(int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for(int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for(int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for(int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if(options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if(postString.IsEmpty()) { if(options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if(parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if(parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if(numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if(curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if(options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); CObjectVector<CDirItem> dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } UStringVector archivePaths; int i; for (i = 0; i < dirItems.Size(); i++) { const CDirItem &dirItem = dirItems[i]; if (!dirItem.IsDirectory()) archivePaths.Add(dirItem.FullPath); } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if(parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if(parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if(options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; if(parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if(updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if(options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if(options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; bool PasswordEnabled; UString Password; bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcLastWriteTimeDefault = utcLastWriteTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCreationTime, _processedFileInfo.CreationTime, _processedFileInfo.IsCreationTimeDefined)); RINOK(GetTime(index, kpidLastWriteTime, _processedFileInfo.LastWriteTime, _processedFileInfo.IsLastWriteTimeDefined)); RINOK(GetTime(index, kpidLastAccessTime, _processedFileInfo.LastAccessTime, _processedFileInfo.IsLastAccessTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDirectory) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDirectory) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDirectory) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size, fullPath, _processedFileInfo.IsLastWriteTimeDefined ? &_processedFileInfo.LastWriteTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDirectory, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDirectory) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IExtractCallBack STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteModified; bool WriteCreated; bool WriteAccessed; bool _encrypted; struct CProcessedFileInfo { FILETIME CreationTime; FILETIME LastWriteTime; FILETIME LastAccessTime; UInt32 Attributes; bool IsCreationTimeDefined; bool IsLastWriteTimeDefined; bool IsLastAccessTimeDefined; bool IsDirectory; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcLastWriteTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteModified(true), WriteCreated(false), WriteAccessed(false), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcLastWriteTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == '\\') { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDirectory() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (!Callback) return S_OK; return Callback->SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant propVariant; if (_subArchiveMode) { switch(propID) { case kpidName: propVariant = _subArchiveName; break; } propVariant.Detach(value); return S_OK; } switch(propID) { case kpidName: propVariant = _fileInfo.Name; break; case kpidIsFolder: propVariant = _fileInfo.IsDirectory(); break; case kpidSize: propVariant = _fileInfo.Size; break; case kpidAttributes: propVariant = (UInt32)_fileInfo.Attributes; break; case kpidLastAccessTime: propVariant = _fileInfo.LastAccessTime; break; case kpidCreationTime: propVariant = _fileInfo.CreationTime; break; case kpidLastWriteTime: propVariant = _fileInfo.LastWriteTime; break; } propVariant.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDirectory()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!Callback) return E_NOTIMPL; return Callback->CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" struct IOpenCallbackUI { virtual HRESULT CheckBreak() = 0; virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0; virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0; #ifndef _NO_CRYPTO virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0; virtual HRESULT GetPasswordIfAny(UString &password) = 0; virtual bool WasPasswordAsked() = 0; virtual void ClearPasswordWasAskedFlag() = 0; #endif }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); // IArchiveOpenVolumeCallback STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); #ifndef _NO_CRYPTO // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static const wchar_t *kEmptyFileAlias = L"[Content]"; UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; return kEmptyFileAlias; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" struct CDirItem { UInt32 Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; UString Name; UString FullPath; bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; struct CArchiveItem { bool IsDirectory; // DWORD Attributes; // NWindows::NCOM::CPropVariant LastWriteTime; FILETIME LastWriteTime; bool SizeIsDefined; UInt64 Size; UString Name; bool Censored; int IndexInServer; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo( const UString &prefix, // prefix for logical path const UString &fullPathName, // path on disk: can be relative to some basePrefix const NFind::CFileInfoW &fileInfo, CObjectVector<CDirItem> &dirItems) { CDirItem item; item.Attributes = fileInfo.Attributes; item.Size = fileInfo.Size; item.CreationTime = fileInfo.CreationTime; item.LastAccessTime = fileInfo.LastAccessTime; item.LastWriteTime = fileInfo.LastWriteTime; item.Name = prefix + fileInfo.Name; item.FullPath = fullPathName; dirItems.Add(item); } static void EnumerateDirectory( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UString &directory, // additional disk prefix starting from baseFolderPrefix const UString &prefix, // logical prefix CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + directory); return; } if (!found) break; AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } void EnumerateDirItems( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UStringVector &fileNames, // names relative to baseFolderPrefix const UString &archiveNamePrefix, CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for(int i = 0; i < fileNames.Size(); i++) { const UString &fileName = fileNames[i]; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + fileName); continue; } AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } } static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const UString &diskPrefix, // full disk path prefix const UString &archivePrefix, // prefix from root const UStringVector &addArchivePrefix, // prefix from curNode CObjectVector<CDirItem> &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->CheckBreak()); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = diskPrefix + name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fileInfo.IsDirectory(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } const UString realName = fileInfo.Name; const UString realDiskPath = diskPrefix + realName; { UStringVector pathParts; pathParts.Add(fileInfo.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support } RINOK(EnumerateDirItems(*nextNode, realDiskPath + wchar_t(kDirDelimiter), archivePrefix + realName + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = diskPrefix + nextNode.Name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fileInfo.IsDirectory()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems(nextNode, diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter), archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter), UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(diskPrefix); break; } if (!found) break; if (callback) RINOK(callback->CheckBreak()); const UString &name = fileInfo.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory())) { AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems); if (fileInfo.IsDirectory()) enterToSubFolders2 = true; } if (!fileInfo.IsDirectory()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems(*nextNode, diskPrefix + name + wchar_t(kDirDelimiter), archivePrefix + name + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "DirItem.h" #include "Windows/FileFind.h" void AddDirFileInfo( const UString &prefix, const UString &fullPathName, const NWindows::NFile::NFind::CFileInfoW &fileInfo, CObjectVector<CDirItem> &dirItems); void EnumerateDirItems( const UString &baseFolderPrefix, const UStringVector &fileNames, const UString &archiveNamePrefix, CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); struct IEnumDirItemCallback { virtual HRESULT CheckBreak() { return S_OK; } }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const UString &defaultName, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", defaultName); if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.LastWriteTime, options.ArchiveFileInfo.Attributes, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "can't decompress folder"; archiveSizes.Add(archiveFileInfo.Size); totalPackSize += archiveFileInfo.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; options.ArchiveFileInfo = archiveFileInfo; #ifndef _NO_CRYPTO openCallback->ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback); bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), archiveFileInfo.Size + archiveLink.VolumesSize, archiveLink.GetDefaultItemName(), wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; virtual HRESULT SetPassword(const UString &password) = 0; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software\\7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fileInfo; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fileInfo)) if (!fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDirectory()) continue; RINOK(LoadDll(folderPrefix + fileInfo.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } int CCodecs::FindFormatForArchiveName(const UString &archivePath) const { int slashPos1 = archivePath.ReverseFind(L'\\'); int slashPos2 = archivePath.ReverseFind(L'.'); int dotPos = archivePath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = archivePath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(arcType) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UINT32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UINT32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UINT32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); int FindFormatForArchiveName(const UString &archivePath) const; int FindFormatForArchiveType(const UString &arcType) const; MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UINT32 *numMethods); STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UINT32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UINT32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) result = defaultName; return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsFolder, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const UInt32 kBufferSize = (200 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); for (UInt32 pos = 0; pos < processedSize; pos++) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() == 0) continue; if (pos + sig.GetCapacity() > processedSize) continue; if (TestSignature(buffer + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices.Delete(i--); } } } orderIndices2 += orderIndices; orderIndices = orderIndices2; } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); UInt32 processedSize; RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] && 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif HRESULT badResult = S_OK; for(i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; if(result != S_OK) { badResult = result; if(result == E_ABORT) break; continue; } *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } if (badResult != S_OK) return badResult; return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { HRESULT result = OpenArchive(codecs, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || getStream == 0) return S_OK; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK) return S_OK; CMyComPtr<IInStream> subStream; if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK) return S_OK; if (!subStream) return S_OK; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return S_OK; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, openCallback); int formatInfo; return OpenArchive(codecs, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(fileName, NULL, openCallback); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } bool IsOpen; CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCreationTime: case kpidLastWriteTime: case kpidLastAccessTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttributes: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDirectory(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; if (!property.Value.IsEmpty()) ParseNumberString(property.Value, propVariant); realNames.Add(property.Name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #ifdef _WIN32 #include <mapi.h> #endif #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Common/CommandLineParser.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" // #include "Windows/Synchronization.h" #include "../../Common/FileStreams.h" #include "../../Compress/Copy/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/UpdateProduce.h" #include "../Common/OpenArchive.h" #include "TempFiles.h" #include "UpdateCallback.h" #include "EnumDirItems.h" #include "SetProperties.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NCommandLineParser; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType) { if (!arcType.IsEmpty()) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(arcType); else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArchiveItem> &archiveItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CObjectVector<CDirItem> &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kDOS: case NFileTimeType::kUnix: fileTimeType = NFileTimeType::EEnum(value); break; default: return E_FAIL; } CObjectVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!! CObjectVector<CUpdatePair2> updatePairs2; UpdateProduce(updatePairs, actionSet, updatePairs2); UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArchiveItems = &archiveItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArchiveItem> &archiveItems) { archiveItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); archiveItems.Reserve(numItems); for(UInt32 i = 0; i < numItems; i++) { CArchiveItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory)); ai.Censored = censor.CheckPath(ai.Name.IsEmpty() ? defaultItemName : ai.Name, !ai.IsDirectory); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.LastWriteTime, ai.LastWriteTime)); CPropVariant propertySize; RINOK(archive->GetProperty(i, kpidSize, &propertySize)); ai.SizeIsDefined = (propertySize.vt != VT_EMPTY); if (ai.SizeIsDefined) ai.Size = ConvertPropVariantToUInt64(propertySize); ai.IndexInServer = i; archiveItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArchiveItem> &archiveItems, const CObjectVector<CDirItem> &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, archiveItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT CheckBreak() { return Callback->CheckBreak(); } }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, openCallback); RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CObjectVector<CDirItem> dirItems; if (options.StdInMode) { CDirItem item; item.FullPath = item.Name = options.StdInFileName; item.Size = (UInt64)(Int64)-1; item.Attributes = 0; SYSTEMTIME st; FILETIME ft; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft; dirItems.Add(item); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if(res != S_OK) { errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArchiveItem> archiveItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, archiveItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, archiveItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArchiveItems(0), UpdatePairs(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsFolder, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidLastAccessTime, VT_FILETIME}, { NULL, kpidCreationTime, VT_FILETIME}, { NULL, kpidLastWriteTime, VT_FILETIME}, { NULL, kpidAttributes, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; */ STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return E_NOTIMPL; /* return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); */ } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(newData != NULL) *newData = BoolToInt(updatePair.NewData); if(newProperties != NULL) *newProperties = BoolToInt(updatePair.NewProperties); if(indexInArchive != NULL) { if (updatePair.ExistInArchive) { if (ArchiveItems == 0) *indexInArchive = updatePair.ArchiveItemIndex; else *indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; } else *indexInArchive = UInt32(-1); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant propVariant; if (propID == kpidIsAnti) { propVariant = updatePair.IsAnti; propVariant.Detach(value); return S_OK; } if (updatePair.IsAnti) { switch(propID) { case kpidIsFolder: case kpidPath: break; case kpidSize: propVariant = (UInt64)0; propVariant.Detach(value); return S_OK; default: propVariant.Detach(value); return S_OK; } } if(updatePair.ExistOnDisk) { const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; switch(propID) { case kpidPath: propVariant = dirItem.Name; break; case kpidIsFolder: propVariant = dirItem.IsDirectory(); break; case kpidSize: propVariant = dirItem.Size; break; case kpidAttributes: propVariant = dirItem.Attributes; break; case kpidLastAccessTime: propVariant = dirItem.LastAccessTime; break; case kpidCreationTime: propVariant = dirItem.CreationTime; break; case kpidLastWriteTime: propVariant = dirItem.LastWriteTime; break; } } else { if (propID == kpidPath) { if (updatePair.NewNameIsDefined) { propVariant = updatePair.NewName; propVariant.Detach(value); return S_OK; } } if (updatePair.ExistInArchive && Archive) { UInt32 indexInArchive; if (ArchiveItems == 0) indexInArchive = updatePair.ArchiveItemIndex; else indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } propVariant.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &updatePair = (*UpdatePairs)[index]; if(!updatePair.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if(updatePair.IsAnti) { return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true); } const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex]; RINOK(Callback->GetStream(dirItem.Name, false)); if(dirItem.IsDirectory()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if(!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if(!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IUpdateCallback STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; UString DirPrefix; bool ShareForWrite; bool StdInMode; const CObjectVector<CDirItem> *DirItems; const CObjectVector<CArchiveItem> *ArchiveItems; const CObjectVector<CUpdatePair2> *UpdatePairs; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; if (!FileTimeToUnixTime(time1, unixTime1)) { unixTime1 = 0; // throw 4191614; } if (!FileTimeToUnixTime(time2, unixTime2)) { unixTime2 = 0; // throw 4191615; } return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); /* if (!FileTimeToDosTime(time1, dosTime1)) throw 4191616; if (!FileTimeToDosTime(time2, dosTime2)) throw 4191617; */ return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; /* static const char *kNotCensoredCollisionMessaged = "Internal file name collision:\n"; static const char *kSameTimeChangedSizeCollisionMessaged = "Collision between files with same date/time and different sizes:\n"; */ static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) { UString message = kDuplicateFileNameMessage; message += L"\n"; message += strings[indices[i]]; message += L"\n"; message += strings[indices[i + 1]]; throw message; } } void GetUpdatePairInfoList( const CObjectVector<CDirItem> &dirItems, const CObjectVector<CArchiveItem> &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, archiveIndices; UStringVector dirNames, archiveNames; int numDirItems = dirItems.Size(); int i; for(i = 0; i < numDirItems; i++) dirNames.Add(dirItems[i].Name); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); int numArchiveItems = archiveItems.Size(); for(i = 0; i < numArchiveItems; i++) archiveNames.Add(archiveItems[i].Name); SortFileNames(archiveNames, archiveIndices); TestDuplicateString(archiveNames, archiveIndices); int dirItemIndex = 0, archiveItemIndex = 0; CUpdatePair pair; while(dirItemIndex < numDirItems && archiveItemIndex < numArchiveItems) { int dirItemIndex2 = dirIndices[dirItemIndex], archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CDirItem &dirItem = dirItems[dirItemIndex2]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; int compareResult = CompareFileNames(dirItem.Name, archiveItem.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirItemIndex2; dirItemIndex++; } else if (compareResult > 0) { pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; archiveItemIndex++; } else { if (!archiveItem.Censored) throw 1082022;; // TTString(kNotCensoredCollisionMessaged + dirItem.Name); pair.DirItemIndex = dirItemIndex2; pair.ArchiveItemIndex = archiveItemIndex2; switch (MyCompareTime(fileTimeType, dirItem.LastWriteTime, archiveItem.LastWriteTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (archiveItem.SizeIsDefined) if (dirItem.Size != archiveItem.Size) // throw 1082034; // kSameTimeChangedSizeCollisionMessaged; pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirItemIndex++; archiveItemIndex++; } updatePairs.Add(pair); } for(;dirItemIndex < numDirItems; dirItemIndex++) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirItemIndex = dirIndices[dirItemIndex]; updatePairs.Add(pair); } for(;archiveItemIndex < numArchiveItems; archiveItemIndex++) { int archiveItemIndex2 = archiveIndices[archiveItemIndex]; const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2]; pair.State = archiveItem.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArchiveItemIndex = archiveItemIndex2; updatePairs.Add(pair); } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArchiveItemIndex; int DirItemIndex; }; void GetUpdatePairInfoList( const CObjectVector<CDirItem> &dirItems, const CObjectVector<CArchiveItem> &archiveItems, NFileTimeType::EEnum fileTimeType, CObjectVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CObjectVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector<CUpdatePair2> &operationChain) { for(int i = 0; i < updatePairs.Size(); i++) { // CUpdateArchiveRange aRange; const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 pair2; pair2.IsAnti = false; pair2.ArchiveItemIndex = pair.ArchiveItemIndex; pair2.DirItemIndex = pair.DirItemIndex; pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk); pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive && pair.State != NPairState::kNotMasked); switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]); // cout << "deleting"; */ break; case NPairAction::kCopy: { if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = false; operationChain.Add(pair2); break; } case NPairAction::kCompress: { if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } case NPairAction::kCompressAsAnti: { pair2.IsAnti = true; pair2.NewData = pair2.NewProperties = true; operationChain.Add(pair2); break; } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { // bool OperationIsCompress; bool NewData; bool NewProperties; bool ExistInArchive; bool ExistOnDisk; bool IsAnti; int ArchiveItemIndex; int DirItemIndex; bool NewNameIsDefined; UString NewName; CUpdatePair2(): NewNameIsDefined(false) {} }; void UpdateProduce( const CObjectVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CObjectVector<CUpdatePair2> &operationChain); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRename: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractingString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestingString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkippingString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (encrypted) (*OutStream) << "Can not open encrypted archive. Wrong password?"; else (*OutStream) << "Can not open file as archive"; (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword) STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *password); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); HRESULT SetPassword(const UString &password); public: bool PasswordIsDefined; UString Password; UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsFolder, L"Folder" }, { kpidSize, L"Size" }, { kpidPackedSize, L"Packed Size" }, { kpidAttributes, L"Attributes" }, { kpidCreationTime, L"Created" }, { kpidLastAccessTime, L"Accessed" }, { kpidLastWriteTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubFolders, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" } }; static const char kEmptyAttributeChar = '.'; static const char kDirectoryAttributeChar = 'D'; static const char kReadonlyAttributeChar = 'R'; static const char kHiddenAttributeChar = 'H'; static const char kSystemAttributeChar = 'S'; static const char kArchiveAttributeChar = 'A'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttributesString(DWORD wa, bool directory, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? kDirectoryAttributeChar: kEmptyAttributeChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? kReadonlyAttributeChar: kEmptyAttributeChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? kHiddenAttributeChar: kEmptyAttributeChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? kSystemAttributeChar: kEmptyAttributeChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? kArchiveAttributeChar: kEmptyAttributeChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidLastWriteTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; return L"?"; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &propVariant) { if (propVariant.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&propVariant.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant)); if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (propVariant.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: propVariant = defaultItemName; break; case kpidLastWriteTime: propVariant = archiveFileInfo.LastWriteTime; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidLastWriteTime) { PrintTime(propVariant); } else if (fieldInfo.PropID == kpidAttributes) { if (propVariant.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = propVariant.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttributesString(attributes, isFolder, s); g_StdOut << s; } else if (propVariant.vt == VT_BSTR) { if (techMode) g_StdOut << propVariant.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal); } else { UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant propVariant; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackedSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant propVariant; if (archive->GetProperty(index, propID, &propVariant) != S_OK) throw "GetPropertyValue error"; if (propVariant.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(propVariant); return true; } HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl; numErrors++; continue; } if (archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback); if (result != S_OK) { g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackedSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" " -p{Password}: set Password\n" " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UINT32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, options.PasswordEnabled, options.Password, numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, options.ArchiveName, options.ArcType)) throw "Unsupported archive type"; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int #ifdef _MSC_VER __cdecl #endif main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/XP/2003/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::SetTotal(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *, const UInt64 *) { return CheckBreak(); } HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } CMyComBSTR temp(Password); *password = temp.Detach(); return S_OK; } HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: HRESULT CheckBreak(); HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes); HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes); HRESULT CryptoGetTextPassword(BSTR *password); HRESULT GetPasswordIfAny(UString &password); bool WasPasswordAsked(); void ClearPasswordWasAskedFlag(); CStdOutStream *OutStream; bool PasswordIsDefined; UString Password; bool PasswordWasAsked; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { /* if (NConsoleClose::TestBreakSignal()) return E_ABORT; */ return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); CMyComBSTR tempName(Password); *password = tempName.Detach(); return S_OK; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; bool PasswordIsDefined; UString Password; bool AskPassword; CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), PasswordIsDefined(false), AskPassword(false), StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRename = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? "; // return true if pressed Quite; // in: anAll // out: anAll, anYes; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRename: return NUserAnswerMode::kAutoRename; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRename, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/7zip/UI/Console/afxres.h ================================================ #include <winresrc.h> ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Build.mak ================================================ !IFDEF CPU LIBS = $(LIBS) bufferoverflowU.lib CFLAGS = $(CFLAGS) -GS- -Zc:forScope !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -EHsc -Gz -WX -Gy !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS_O1 = $(CFLAGS) -O1 -W4 -Wp64 CFLAGS_O2 = $(CFLAGS) -O2 -W4 -Wp64 !ELSE CFLAGS_O1 = $(CFLAGS) -O1 -W3 CFLAGS_O2 = $(CFLAGS) -O2 -W3 !ENDIF LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if(_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } class CCRCTableInit { public: CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if(buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while(pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for(int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include <ctype.h> #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { Free(); } void CBaseRecordVector::Free() { delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if (newCapacity <= _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void Free(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while(--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if(!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if(intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if(c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if(c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if(!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; char defaultChar = '_'; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED typedef unsigned char Byte; #endif #ifndef _7ZIP_INT16_DEFINED #define _7ZIP_INT16_DEFINED typedef short Int16; #endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; #endif #ifndef _7ZIP_INT32_DEFINED #define _7ZIP_INT32_DEFINED typedef int Int32; #endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED typedef unsigned int UInt32; #endif #ifdef _MSC_VER #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef __int64 Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned __int64 UInt64; #endif #else #ifndef _7ZIP_INT64_DEFINED #define _7ZIP_INT64_DEFINED typedef long long int Int64; #endif #ifndef _7ZIP_UINT64_DEFINED #define _7ZIP_UINT64_DEFINED typedef unsigned long long int UInt64; #endif #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; // These functions are for UTF8 <-> UTF16 conversion. bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { Byte c = (Byte)src[i++]; if (c < 0x80) { dest += (wchar_t)c; continue; } if(c < 0xC0) return false; int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { if (i >= src.Length()) return false; Byte c2 = (Byte)src[i++]; if (c2 < 0x80 || c2 >= 0xC0) return false; value <<= 6; value |= (c2 - 0x80); numAdds--; } while(numAdds > 0); if (value < 0x10000) dest += (wchar_t)(value); else { value -= 0x10000; if (value >= 0x100000) return false; dest += (wchar_t)(0xD800 + (value >> 10)); dest += (wchar_t)(0xDC00 + (value & 0x3FF)); } } return true; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); for(int i = 0; i < src.Length();) { UInt32 value = (UInt32)src[i++]; if (value < 0x80) { dest += (char)value; continue; } if (value >= 0xD800 && value < 0xE000) { if (value >= 0xDC00) return false; if (i >= src.Length()) return false; UInt32 c2 = (UInt32)src[i++]; if (c2 < 0xDC00 || c2 >= 0xE000) return false; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } int numAdds; for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; dest += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; dest += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); } return true; } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for(i = path.Length() - 1; i >= 0; i--) if(IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if(CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if(!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if(::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for(int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if(string.IsEmpty()) { if(i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if(errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if(MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDirectory()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while(pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if(fileInfo.IsDirectory()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while(enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if(number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if(NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDirectory() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfo &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATAW &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = findData.cFileName; #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo( const WIN32_FIND_DATA &findData, CFileInfoW &fileInfo) { fileInfo.Attributes = findData.dwFileAttributes; fileInfo.CreationTime = findData.ftCreationTime; fileInfo.LastAccessTime = findData.ftLastAccessTime; fileInfo.LastWriteTime = findData.ftLastWriteTime; fileInfo.Size = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fileInfo.ReparseTag = findData.dwReserved0; #else fileInfo.ObjectID = findData.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA findData; _handle = ::FindFirstFile(wildcard, &findData); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW findData; _handle = ::FindFirstFileW(wildcard, &findData); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &findData); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &findData); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA findData; bool result = BOOLToBool(::FindNextFile(_handle, &findData)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW findData; if (!::FindNextFileW(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } else { WIN32_FIND_DATAA findData; if (!::FindNextFileA(_handle, &findData)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for(UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for(UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDirectory(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attributes & mask) != 0); } public: DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; UInt64 Size; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDirectory() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif #ifdef _WIN32 const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } #endif }}} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif #ifdef _WIN32 void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); #endif }}} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if(hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if(vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" // #include <stdio.h> #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(UInt32 value, char *s, int numPos) { char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if(!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(st.wYear, s, 4); *s++ = '-'; s = UIntToStringSpec(st.wMonth, s, 2); *s++ = '-'; s = UIntToStringSpec(st.wDay, s, 2); if (includeTime) { *s++ = ' '; s = UIntToStringSpec(st.wHour, s, 2); *s++ = ':'; s = UIntToStringSpec(st.wMinute, s, 2); if (includeSeconds) { *s++ = ':'; UIntToStringSpec(st.wSecond, s, 2); } } /* sprintf(s, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay); if (includeTime) { sprintf(s + strlen(s), " %02d:%02d", st.wHour, st.wMinute); if (includeSeconds) sprintf(s + strlen(s), ":%02d", st.wSecond); } */ return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return propVariant.bstrVal; case VT_UI1: return ConvertUInt64ToString(propVariant.bVal); case VT_UI2: return ConvertUInt64ToString(propVariant.uiVal); case VT_UI4: return ConvertUInt64ToString(propVariant.ulVal); case VT_UI8: return ConvertUInt64ToString(propVariant.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(propVariant.filetime, true, true); /* case VT_I1: return ConvertInt64ToString(propVariant.cVal); */ case VT_I2: return ConvertInt64ToString(propVariant.iVal); case VT_I4: return ConvertInt64ToString(propVariant.lVal); case VT_I8: return ConvertInt64ToString(propVariant.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(propVariant.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant) { switch (propVariant.vt) { case VT_UI1: return propVariant.bVal; case VT_UI2: return propVariant.uiVal; case VT_UI4: return propVariant.ulVal; case VT_UI8: return (UInt64)propVariant.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } HRes Close() { return Event_Close(&_object); } #ifdef _WIN32 HRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif HRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } HRes Reset() { return Event_Reset(&_object); } HRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: HRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 HRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: HRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } HRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: HRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: HRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } HRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } HRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } HRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } HRes Release() { return Semaphore_Release1(&_object); } HRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } HRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } HRes Close() { return Thread_Close(&thread); } HRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } HRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-3.3-lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { inline bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime(UInt16(dosTime >> 16), UInt16(dosTime & 0xFFFF), &fileTime)); } const UInt32 kHighDosTime = 0xFF9FBF7D; const UInt32 kLowDosTime = 0x210000; inline bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { if (fileTime.dwHighDateTime >= 0x01C00000) // 2000 dosTime = kHighDosTime; else dosTime = kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } const UInt32 kNumTimeQuantumsInSecond = 10000000; const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; inline void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } inline bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } }} #endif ================================================ FILE: src/others/squashfs-3.3-lzma/Makefile ================================================ # Copyright (C) 2006-2008 Junjiro Okajima # Copyright (C) 2006-2008 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: Makefile,v 1.30 2008-03-12 16:24:54 jro Exp $ # paths Sqlzma = ${CURDIR} LzmaVer = Lzma = ${Sqlzma}/${LzmaVer} SqVer = squashfs3.3 Squashfs = ${Sqlzma}/${SqVer} #KVer = linux-2.6.24.3 SqFs = ${Squashfs}/kernel-patches/${KVer}/fs/squashfs #KDir = /lib/modules/$(shell uname -r)/build LzmaC = ${Lzma}/C/Compress/Lzma LzmaAlone = ${Lzma}/CPP/7zip/Compress/LZMA_Alone SqTools = ${Squashfs}/squashfs-tools # enable it if you want to add -g option when compiling UseDebugFlags = # disable it if you don't want to compile squashfs kernel module here BuildSquashfs = 1 export all: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ clean: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ ${RM} *~ ######################################## #-include priv.mk #ifdef BuildSquashfs #CONFIG_SQUASHFS = m #CONFIG_SQUASHFS_EMBEDDED = #CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE = 3 #EXTRA_CFLAGS = -I${Sqlzma} -I${SqFs}/../../include -Wall -Werror #EXTRA_CFLAGS += -DCONFIG_SQUASHFS_MODULE -UCONFIG_SQUASHFS #EXTRA_CFLAGS += -UCONFIG_SQUASHFS_EMBEDDED -DCONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # if you enabled CONFIG_PREEMPT, but want CPU to try concentrating # the uncompression, then define UnsquashNoPreempt. # if you don't define UnsquashNoPreempt, the behaviour follows # the CONFIG_PREEMPT. #EXTRA_CFLAGS += -DUnsquashNoPreempt #export # the environment variables are not inherited since 2.6.23 #MAKE += SQLZMA_EXTRA_CFLAGS="$(shell echo ${EXTRA_CFLAGS} | sed -e 's/\"/\\\\\\"/g')" # #all: all_sq # #FORCE: #all_sq: # ${MAKE} -C ${KDir} M=${SqFs} modules #clean: clean_sq #clean_sq: # ${MAKE} -C ${KDir} M=${SqFs} clean #endif ######################################## # #load: # for i in ${LzmaC}/kmod/unlzma.ko ${LzmaC}/kmod/sqlzma.ko \ # ${SqFs}/squashfs.ko; \ # do sudo insmod $$i; done # #unload: # -sudo rmmod squashfs sqlzma unlzma ================================================ FILE: src/others/squashfs-3.3-lzma/sqlzma.h ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma. */ /* $Id: sqlzma.h,v 1.20 2008-03-12 16:58:34 jro Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include <stdlib.h> #include <string.h> #include <zlib.h> #ifdef _REENTRANT #include <pthread.h> #endif #else #include <linux/zlib.h> #endif #define _7ZIP_BYTE_DEFINED /* * detect the compression method automatically by the first byte of compressed * data. * according to rfc1950, the first byte of zlib compression must be 0x?8. */ #define is_lzma(c) (c == 0x5d) /* ---------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif #ifndef __KERNEL__ /* for mksquashfs only */ struct sqlzma_opts { unsigned int try_lzma; unsigned int dicsize; }; int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out); #endif /* ---------------------------------------------------------------------- */ /* * Three patterns for sqlzma uncompression. very dirty code. * - kernel space (squashfs kernel module) * - user space with pthread (mksquashfs) * - user space without pthread (unsquashfs) */ struct sized_buf { unsigned int sz; unsigned char *buf; }; enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST}; struct sqlzma_un { int un_lzma; struct sized_buf un_a[SQUN_LAST]; unsigned char un_prob[31960]; /* unlzma 64KB - 1MB */ z_stream un_stream; #define un_cmbuf un_stream.next_in #define un_cmlen un_stream.avail_in #define un_resbuf un_stream.next_out #define un_resroom un_stream.avail_out #define un_reslen un_stream.total_out }; int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz); int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst); void sqlzma_fin(struct sqlzma_un *un); /* ---------------------------------------------------------------------- */ #ifdef __cplusplus }; #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.2 2006-11-27 03:54:58 jro Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/Makefile ================================================ ifndef Sqlzma $(error Sqlzma is not defined) endif INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ifdef UseDebugFlags DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG endif CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} LDLIBS += -lz -lm -L${LzmaAlone} -L${LzmaC} Tgt = mksquashfs unsquashfs all: ${Tgt} read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a mksquashfs: LDLIBS += -lpthread -lunlzma_r -llzma_r -lstdc++ mksquashfs: mksquashfs.o read_fs.o sort.o unsquashfs.o: CFLAGS += -U_REENTRANT unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a unsquashfs: LDLIBS += -lunlzma unsquashfs: unsquashfs.o $(CC) unsquashfs.o -o unsquashfs $(LDLIBS) -lz clean: ${RM} *~ *.o ${Tgt} -include test.mk # Local variables: ; # compile-command: (concat "make Sqlzma=../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include <squashfs_fs.h> #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "sqlzma.h" #include "sqmagic.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; struct sqlzma_un un; struct sqlzma_opts sqlzma_opts = { .try_lzma = 1, .dicsize = SQUASHFS_FILE_SIZE }; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* data allocator status struct. Allocators are used to keep track of memory buffers passed between different threads */ struct allocator { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait; }; /* struct describing a memory buffer passed between threads */ struct file_buffer { long long file_size; struct allocator *allocator; void (*release)(int); int release_data; long long block; int size; int c_byte; unsigned int block_order; int fragment; int error; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct allocator *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; struct allocator *alloc_init(int buffer_size, int max_buffers) { struct allocator *allocator = malloc(sizeof(struct allocator)); if(allocator == NULL) return NULL; allocator->max_buffers = max_buffers; allocator->buffer_size = buffer_size; allocator->count = 0; pthread_mutex_init(&allocator->mutex, NULL); pthread_cond_init(&allocator->wait, NULL); return allocator; } struct file_buffer *alloc_get(struct allocator *allocator) { struct file_buffer *file_buffer; pthread_mutex_lock(&allocator->mutex); while(allocator->count == allocator->max_buffers) pthread_cond_wait(&allocator->wait, &allocator->mutex); if((file_buffer = malloc(sizeof(struct file_buffer) + allocator->buffer_size)) == NULL) goto failed; file_buffer->release = NULL; file_buffer->allocator = allocator; allocator->count ++; failed: pthread_mutex_unlock(&allocator->mutex); return file_buffer; } struct file_buffer *alloc_get_2(struct allocator *allocator, void (*release)(int), int release_data) { struct file_buffer *file_buffer = alloc_get(allocator); if(file_buffer) { file_buffer->release = release; file_buffer->release_data = release_data; } return file_buffer; } void alloc_free(struct file_buffer *file_buffer) { struct allocator *allocator; if(file_buffer == NULL) return; allocator = file_buffer->allocator; if(file_buffer->release) file_buffer->release(file_buffer->release_data); pthread_mutex_lock(&allocator->mutex); free(file_buffer); if(allocator->count == 0) ERROR("alloc_free: freeing buffer for empty allocator!\n"); else allocator->count --; pthread_cond_signal(&allocator->wait); pthread_mutex_unlock(&allocator->mutex); } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } res = sqlzma_cm(&sqlzma_opts, stream, (void *)s, size, (void *)d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL); #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment, int *cached_fragment) { squashfs_fragment_entry *disk_fragment; int size; if(fragment->index == *cached_fragment || fragment->index == SQUASHFS_INVALID_FRAG) return buffer + fragment->offset; if(fragment_data && fragment->index == fragments) return fragment_data->data + fragment->offset; pthread_mutex_lock(&fragment_mutex); while(fragment_table[fragment->index].pending) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)cbuffer, .sz = size}, {.buf = (void *)buffer, .sz = bytes} }; read_bytes(fd, disk_fragment->start_block, size, cbuffer); res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); } else read_bytes(fd, disk_fragment->start_block, size, buffer); *cached_fragment = fragment->index; return buffer + fragment->offset; } void ensure_fragments_flushed() { pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) pthread_cond_wait(&fragment_waiting, &fragment_mutex); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].pending = TRUE; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } void frag_release(int block) { pthread_mutex_lock(&fragment_mutex); fragment_table[block].pending = FALSE; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = alloc_get(fragment_buffer); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l) { unsigned short chksum = 0; unsigned int bytes; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); start += bytes; } return chksum; } unsigned short get_checksum_buffer(struct buffer_list *buffer_list, unsigned int blocks) { unsigned short chksum = 0; int block; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) chksum = get_checksum(b->read_buffer->data, b->read_buffer->size, chksum); else if(b->size != 0) chksum = get_checksum(read_from_disk(b->start, b->size), b->size, chksum); } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } int cached_frag = -1; char fragdata[SQUASHFS_FILE_MAX_SIZE]; #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } char cached_fragment[SQUASHFS_FILE_MAX_SIZE]; int cached_frag1 = -1; int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), file_size); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } char buffer2[SQUASHFS_FILE_MAX_SIZE]; struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long dup_start = dupl_ptr->start; char *buffer; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_buffer(buffer_list, blocks); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes); dupl_ptr->fragment_checksum = get_checksum_mem(get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1), frag_bytes); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; if(b->read_buffer) buffer = b->read_buffer->data; else if(b->size) buffer = read_from_disk(b->start, b->size); else continue; read_bytes(fd, dup_start, b->size, buffer2); if(memcmp(buffer, buffer2, b->size) != 0) break; dup_start += b->size; } if(block == blocks) { char *fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment, &cached_frag1); if(frag_bytes == 0 || memcmp(file_buffer->data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int block_order = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = alloc_get(reader_buffer); byte = file_buffer->size = read(file, file_buffer->data, block_size); file_buffer->block_order = block_order ++; file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read(file, &buffer, 1) == 1) goto restat; } file_buffer->fragment = (file_buffer->block == frag_block); if(file_buffer->fragment) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = alloc_get(reader_buffer); file_buffer->block_order = block_order ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { perror("Write on destination failed"); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); alloc_free(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = alloc_get(writer_buffer); if(sparse_files && all_zero(file_buffer)) write_buffer->c_byte = 0; else write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->block_order = file_buffer->block_order; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; alloc_free(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = alloc_get_2(writer_buffer, frag_release, file_buffer->block); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); pthread_mutex_lock(&fragment_mutex); fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->size = compressed_size; write_buffer->block = bytes; queue_put(to_writer, write_buffer); bytes += compressed_size; total_uncompressed += file_buffer->size; total_compressed += compressed_size; TRACE("Writing fragment %lld, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); fragments_outstanding --; pthread_cond_signal(&fragment_waiting); pthread_mutex_unlock(&fragment_mutex); alloc_free(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->block_order); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int block_order = 0; int hash = BLOCK_HASH(block_order); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->block_order == block_order) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->block_order == block_order) break; push_buffer(file_buffer); } } block_order ++; return file_buffer; } int progress_bar(long long current, long long max, int columns) { int max_digits = ceil(log10(max)); int used = max_digits * 2 + 10; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(!progress || columns - used < 0) return 0; printf("\r["); while (hashes --) putchar('='); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return 0; } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; alloc_free(file_buffer); total_bytes += size; file_count ++; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); alloc_free(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; int status; *duplicate_file = FALSE; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else alloc_free(read_buffer); progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } else read_buffer = NULL; fragment = get_and_fill_fragment(read_buffer); alloc_free(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } free(block_list); alloc_free(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block, thresh; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct buffer_list *buffer_list; int status; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); ensure_fragments_flushed(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - processors) ? blocks - (writer_buffer_size - processors): 0; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; buffer_list[block].start = bytes; buffer_list[block].size = read_buffer->size; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; } else { buffer_list[block].read_buffer = NULL; alloc_free(read_buffer); } progress_bar(++cur_uncompressed, estimated_uncompressed, columns); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block].read_buffer) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) alloc_free(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) ftruncate(fd, bytes); } alloc_free(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; if(block && thresh) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); bytes = start; if(!block_device) ftruncate(fd, bytes); } for(blocks = thresh; blocks < block; blocks ++) alloc_free(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); alloc_free(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { alloc_free(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); alloc_free(read_buffer); } else if(!no_fragments && (read_size < block_size)) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, new, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(processors * 2); reader_buffer = alloc_init(block_size, reader_buffer_size); writer_buffer = alloc_init(block_size, writer_buffer_size); fragment_buffer = alloc_init(block_size, processors * 2); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing exclude which subsumes the exclude currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific excludes, delete as they're subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with -wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories in the * filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n"); read_bytes(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) BAD_ERROR("Failed to create recovery file, because %s. Aborting\n", strerror(errno)); if(write(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int readbytes; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n"); if((readbytes = read(recoverfd, metadata, bytes)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(readbytes != bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_bytes(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 3.3-CVS (2007/12/04)\n");\ printf("copyright (C) 2007 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { struct winsize winsize; struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT; int s_minor; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-lzmadic") == 0) { long bs; unsigned int bl; if(++i == argc) { ERROR("%s: -b|-lzmadic missing block size\n", argv[0]); exit(1); } bs = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') bs *= 1048576; else if(*b == 'k' || *b == 'K') bs *= 1024; else if(*b != '\0') { ERROR("%s: -b|-lzmadic invalid size\n", argv[0]); exit(1); } bl = slog(bs); if(bl == 0) { ERROR("%s: -b|-lzmadic size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } if (!strcmp(argv[i - 1], "-b")) { block_size = bs; block_log = bl; } sqlzma_opts.dicsize = bs; } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { un.un_lzma = 0; sqlzma_opts.try_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors <number>\tUse <number> processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); ERROR("-lzmadic <dic_size>\tset the LZMA dictionary" " size to <dic_size>\n" "\t\t\tDefault value always follow the block" " size\n" "\t\t\tUse this alone or AFTER -b option\n"); ERROR("-nolzma\t\t\tnever try LZMA compression\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); if(block_size <= 65536 && sparse_files == FALSE) s_minor = 0; else s_minor = SQUASHFS_MINOR; for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } be = orig_be; block_log = slog(block_size = sBlk.block_size); //sqlzma_opts.dicsize = block_size; s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { ERROR("%s:%d: %d\n", __func__, __LINE__, i); EXIT_MKSQUASHFS(); } if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = (char *)malloc(scache_bytes); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(progress) { if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC_LZMA; if (!un.un_lzma) sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { ensure_fragments_flushed(); queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_uids = uid_count; if(sBlk.no_uids) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; sBlk.no_guids = guid_count; if(sBlk.no_guids) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { int uid = uids[i]; struct passwd *user = getpwuid(uid); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC_LZMA: if (!un.un_lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_LZMA_SWAP: if (!un.un_lzma) goto bad; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.3-lzma/squashfs3.3/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include <stdlib.h> #include <time.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("unsquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ exit(1); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(char *pathname, unsigned int block_start, unsigned int offset); char *(*read_fragment)(unsigned int fragment); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; struct test { int mask; int value; int position; char mode; }; squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; struct sqlzma_un un; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } /* printf("i%d ", inode->inode_number); */ if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)data, .sz = c_byte}, {.buf = (void *)block, .sz = bytes} }; if(read_bytes(start, c_byte, data) == FALSE) return 0; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } char *read_fragment_2(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int lseek_broken = FALSE; char *zero_data; long long hole; int write_block(int file_fd, char *buffer, int size) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } hole = 0; } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } int write_file(long long file_size, char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; int file_end = file_size / block_size; TRACE("write_file: regular file, blocks %d\n", blocks); hole = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } s_ops.read_block_list(block_list, block_ptr, blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if(block_list[i] == 0) { /* sparse file */ hole += i == file_end ? file_size & (block_size - 1) : block_size; continue; } if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write_block(file_fd, file_data, bytes) == FALSE) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = s_ops.read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write_block(file_fd, fragment_data + offset, frag_bytes) == FALSE) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } if(hole) { /* corner case for hole extending to end of file */ if(lseek(file_fd, hole, SEEK_CUR) == -1) { /* for broken lseeks which cannot seek beyond end of * file, write_block will do the right thing */ hole --; if(write_block(file_fd, "\0", 1) == FALSE) { ERROR("write_file: failed to write sparse data block\n"); goto failure; } } else if(ftruncate(file_fd, file_size) == -1) { ERROR("write_file: failed to write sparse data block\n"); goto failure; } } close(file_fd); free(block_list); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i->data, pathname, i->fragment, i->frag_bytes, i->offset, i->blocks, i->start, i->block_ptr, i->mode)) { set_attributes(pathname, i->mode, i->uid, i->gid, i->time, force); file_count ++; } break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser! %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(char *pathname, unsigned int block_start, unsigned int offset) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; struct inode *i; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + i->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } if(lsonly || info) print_filename(pathname, i); bytes += i->offset; size = i->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = i->mode; dir->uid = i->uid; dir->guid = i->gid; dir->mtime = i->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') *target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { struct dir *dir = s_ops.squashfs_opendir(parent_name, start_block, offset); unsigned int type; char *name, pathname[1024]; struct pathnames *new; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) create_inode(pathname, i); } free_subdir(new); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ un.un_lzma = 1; swap = 0; switch (sBlk.s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } #define VERSION() \ printf("unsquashfs version 1.5-CVS (2007/01/25)\n");\ printf("copyright (C) 2007 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("and LZMA support for slax.org by jro.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { fputs("sqlzma_init failed", stderr); abort(); } read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.49 Copyright (c) 1999-2007 Igor Pavlov 2006-07-05\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.42 Copyright (c) 1999-2006 Igor Pavlov 2006-05-15\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.3-lzma/unuse/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.4-cisco/Makefile ================================================ SQDIR=squashfs-tools all: make -C $(SQDIR) cp $(SQDIR)/unsquashfs . cp $(SQDIR)/mksquashfs . clean: make -C $(SQDIR) clean rm -f unsquashfs mksquashfs ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.62 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CFileItem *f = db.db.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zBuf.c ================================================ /* 7zBuf.c -- Byte Buffer 2008-03-28 Igor Pavlov Public domain */ #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)alloc->Alloc(alloc, size); if (p->data != 0) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zBuf.h ================================================ /* 7zBuf.h -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zBuf2.c ================================================ /* 7zBuf2.c -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)alloc->Alloc(alloc, newSize); if (data == 0) return 0; p->size = newSize; memcpy(data, p->data, p->pos); alloc->Free(alloc, p->data); p->data = data; } memcpy(p->data + p->pos, buf, size); p->pos += size; return 1; } void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zCrc.c ================================================ /* 7zCrc.c -- CRC32 calculation 2008-08-05 Igor Pavlov Public domain */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zCrc.h ================================================ /* 7zCrc.h -- CRC32 calculation 2008-03-13 Igor Pavlov Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zFile.c ================================================ /* 7zFile.c -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include <errno.h> #endif #ifdef USE_WINDOWS_FILE /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #define kChunkSizeMax (1 << 22) #endif void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #else p->file = NULL; #endif } static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #else p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #else if (p->file != NULL) { int res = fclose(p->file); if (res != 0) return res; p->file = NULL; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fread(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fwrite(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE LARGE_INTEGER value; DWORD moveMethod; value.LowPart = (DWORD)*pos; value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ switch (origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)value.HighPart << 32) | value.LowPart; return 0; #else int moveMethod; int res; switch (origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return 1; } res = fseek(p->file, (long)*pos, moveMethod); *pos = ftell(p->file); return res; #endif } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #else long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) { CFileSeqInStream *p = (CFileSeqInStream *)pp; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->s.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(void *pp, void *buf, size_t *size) { CFileInStream *p = (CFileInStream *)pp; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) { CFileInStream *p = (CFileInStream *)pp; return File_Seek(&p->file, pos, origin); } void FileInStream_CreateVTable(CFileInStream *p) { p->s.Read = FileInStream_Read; p->s.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(void *pp, const void *data, size_t size) { CFileOutStream *p = (CFileOutStream *)pp; File_Write(&p->file, data, &size); return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->s.Write = FileOutStream_Write; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zFile.h ================================================ /* 7zFile.h -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE #endif #ifdef USE_WINDOWS_FILE #include <windows.h> #else #include <stdio.h> #endif #include "Types.h" /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #else FILE *file; #endif } CSzFile; void File_Construct(CSzFile *p); WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream s; CSzFile file; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream s; CSzFile file; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream s; CSzFile file; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zStream.c ================================================ /* 7zStream.c -- 7z Stream functions 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "Types.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) { Int64 t = offset; return stream->Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); memcpy(buf, lookBuf, *size); return stream->Skip(stream, *size); } SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; size2 = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, &size2); p->size = size2; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; if (*size > LookToRead_BUF_SIZE) *size = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Skip(void *pp, size_t offset) { CLookToRead *p = (CLookToRead *)pp; p->pos += offset; return SZ_OK; } static SRes LookToRead_Read(void *pp, void *buf, size_t *size) { CLookToRead *p = (CLookToRead *)pp; size_t rem = p->size - p->pos; if (rem == 0) return p->realStream->Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) { CLookToRead *p = (CLookToRead *)pp; p->pos = p->size = 0; return p->realStream->Seek(p->realStream, pos, origin); } void LookToRead_CreateVTable(CLookToRead *p, int lookahead) { p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact; p->s.Skip = LookToRead_Skip; p->s.Read = LookToRead_Read; p->s.Seek = LookToRead_Seek; } void LookToRead_Init(CLookToRead *p) { p->pos = p->size = 0; } static SRes SecToLook_Read(void *pp, void *buf, size_t *size) { CSecToLook *p = (CSecToLook *)pp; return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->s.Read = SecToLook_Read; } static SRes SecToRead_Read(void *pp, void *buf, size_t *size) { CSecToRead *p = (CSecToRead *)pp; return p->realStream->Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->s.Read = SecToRead_Read; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/7zVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Alloc.c ================================================ /* Alloc.c -- Memory allocation functions 2008-09-24 Igor Pavlov Public domain */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG { void *p = malloc(size); fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); return p; } #else return malloc(size); #endif } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" #include "7zDecode.h" #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_Construct(&state); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) { if (state.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(inStream->Skip((void *)inStream, curSize)); } return SZ_OK; } #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } UInt64 GetSum(const UInt64 *values, UInt32 index) { UInt64 sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CSzCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; UInt64 unpackSize = folder->UnpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); if (temp == 0 && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = GetSum(packSizes, si); inSize = packSizes[si]; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } else { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZ_ERROR_UNSUPPORTED; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); UInt64 s3Size = packSizes[1]; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZ_ERROR_MEM; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) res = Bcj2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], tempBuf[2], tempSizes[2], outBuffer, outSize); RINOK(res) } else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SRes res = SzDecode2(packSizes, folder, inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) IAlloc_Free(allocMain, tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "7zDecode.h" #include "7zExtract.h" SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzAr_Extract( const CSzArEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c -- 7z Input functions 2008-12-31 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "../../CpuArch.h" #include "7zDecode.h" #include "7zIn.h" #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->FolderStartPackStreamIndex = 0; p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } /* UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CSzFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) { UInt32 startPos = 0; UInt64 startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); for (i = 0; i < p->db.NumFolders; i++) { p->FolderStartPackStreamIndex[i] = startPos; startPos += p->db.Folders[i].NumPackStreams; } MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); for (i = 0; i < p->db.NumPackStreams; i++) { p->PackStreamStartPositions[i] = startPosSize; startPosSize += p->db.PackSizes[i]; } MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); for (i = 0; i < p->db.NumFiles; i++) { CSzFileItem *file = p->db.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { p->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderStartFileIndex[folderIndex] = i; if (p->db.Folders[folderIndex].NumUnpackStreams != 0) break; folderIndex++; } } p->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) { return p->dataPos + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) { UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; CSzFolder *folder = p->db.Folders + folderIndex; UInt64 size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; if (t < size) /* check it */ return SZ_ERROR_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SRes SzReadTime(const CObjectVector<CBuf> &dataVector, CObjectVector<CSzFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for (int i = 0; i < files.Size(); i++) { CSzFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; } } return SZ_OK; } */ static int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; static SRes SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZ_ERROR_ARCHIVE; sd->Size--; *b = *sd->Data++; return SZ_OK; } static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } static SRes SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } static SRes SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static SRes SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } static SRes SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZ_ERROR_ARCHIVE; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } static SRes SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SzSkeepData(sd)); } } static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, alloc); MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } static SRes SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, ISzAlloc *alloc) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); MY_ALLOC(UInt32, *digests, numItems, alloc); for (i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } static SRes SzReadPackInfo( CSzData *sd, UInt64 *dataOffset, UInt32 *numPackStreams, UInt64 **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, ISzAlloc *alloc) { UInt32 i; RINOK(SzReadNumber(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { RINOK(SzReadNumber(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } static SRes SzReadStreamsInfo( CSzData *sd, UInt64 *dataOffset, CSzAr *p, UInt32 *numUnpackStreams, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ ISzAlloc *alloc, ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZ_ERROR_UNSUPPORTED; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); break; } case k7zIdUnpackInfo: { RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZ_ERROR_UNSUPPORTED; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) { UInt32 i; for (i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CSzFileItem *file = files + i; while (pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZ_ERROR_ARCHIVE; if (pos + 2 > sd->Size) return SZ_ERROR_ARCHIVE; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZ_ERROR_ARCHIVE; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, alloc); len = 0; while (2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += numAdds; } } return SZ_OK; } static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->FileCRCDefined = 0; } } } return SzArEx_Fill(p, allocMain); } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; } static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzDecode(p->PackSizes, folder, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; } static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h -- 7z Input functions 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 *FolderStartPackStreamIndex; UInt64 *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; } CSzArEx; void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #include "7zItem.h" void SzCoderInfo_Init(CSzCoderInfo *p) { Buf_Init(&p->Props); } void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) { Buf_Free(&p->Props, alloc); SzCoderInfo_Init(p); } void SzFolder_Init(CSzFolder *p) { p->Coders = 0; p->BindPairs = 0; p->PackStreams = 0; p->UnpackSizes = 0; p->NumCoders = 0; p->NumBindPairs = 0; p->NumPackStreams = 0; p->UnpackCRCDefined = 0; p->UnpackCRC = 0; p->NumUnpackStreams = 0; } void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { UInt32 i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); } UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) { UInt32 result = 0; UInt32 i; for (i = 0; i < p->NumCoders; i++) result += p->Coders[i].NumOutStreams; return result; } int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } UInt64 SzFolder_GetUnpackSize(CSzFolder *p) { int i = (int)SzFolder_GetNumOutStreams(p); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolder_FindBindPairForOutStream(p, i) < 0) return p->UnpackSizes[i]; /* throw 1; */ return 0; } void SzFile_Init(CSzFileItem *p) { p->HasStream = 1; p->IsDir = 0; p->IsAnti = 0; p->FileCRCDefined = 0; p->MTimeDefined = 0; p->Name = 0; } static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Name); SzFile_Init(p); } void SzAr_Init(CSzAr *p) { p->PackSizes = 0; p->PackCRCsDefined = 0; p->PackCRCs = 0; p->Folders = 0; p->Files = 0; p->NumPackStreams = 0; p->NumFolders = 0; p->NumFiles = 0; } void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { UInt32 i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); if (p->Files) for (i = 0; i < p->NumFiles; i++) SzFile_Free(&p->Files[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" typedef struct { UInt32 NumInStreams; UInt32 NumOutStreams; UInt64 MethodID; CBuf Props; } CSzCoderInfo; void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); typedef struct { UInt32 InIndex; UInt32 OutIndex; } CBindPair; typedef struct { CSzCoderInfo *Coders; CBindPair *BindPairs; UInt32 *PackStreams; UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; int UnpackCRCDefined; UInt32 UnpackCRC; UInt32 NumUnpackStreams; } CSzFolder; void SzFolder_Init(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { CNtfsFileTime MTime; UInt64 Size; char *Name; UInt32 FileCRC; Byte HasStream; Byte IsDir; Byte IsAnti; Byte FileCRCDefined; Byte MTimeDefined; } CSzFileItem; void SzFile_Init(CSzFileItem *p); typedef struct { UInt64 *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; CSzFolder *Folders; CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; UInt32 NumFiles; } CSzAr; void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c - Test application for 7z Decoder 2008-11-23 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "7zAlloc.h" #include "7zExtract.h" #include "7zIn.h" static void ConvertNumberToString(UInt64 value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } if (InFile_Open(&archiveStream.file, args[2])) { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *f = db.db.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) ConvertFileTimeToString(&f->MTime, t); else strcpy(t, " "); printf("%s %10s %s\n", t, s, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (f->IsDir) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) { printf("\n"); continue; } res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { CSzFile outFile; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } if (OutFile_Open(&outFile, fileName)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/makefile ================================================ MY_STATIC_LINK=1 PROG = 7zDec.exe C_OBJS = \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ $O\7zStream.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c 7zBuf2.o: ../../7zBuf2.c $(CXX) $(CFLAGS) ../../7zBuf2.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c Bcj2.o: ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c 7zFile.o: ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c 7zStream.o: ../../7zStream.c $(CXX) $(CFLAGS) ../../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Bcj2.c ================================================ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bcj2.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *buffer, *bufferLim; UInt32 range, code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; buffer = buf3; bufferLim = buffer + size3; RC_INIT2 if (outSize == 0) return SZ_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; UInt32 ttt; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IF_BIT_0(prob) { UPDATE_0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UPDATE_1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return SZ_ERROR_DATA; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return SZ_ERROR_DATA; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Bcj2.h ================================================ /* Bcj2.h -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). Returns: SZ_OK SZ_ERROR_DATA - Data error */ int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Bra.c ================================================ /* Bra.c -- Converters for RISC code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 8; for (i = 0; i <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 4; for (i = 0; i <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) { UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Bra.h ================================================ /* Bra.h -- Branch converters for executables 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. Type Endian Alignment LookAhead x86 little 1 4 ARMT little 2 2 ARM little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 size must be >= Alignment + LookAhead, if it's not last block. If (size < Alignment + LookAhead), converter returns 0. Example: UInt32 ip = 0; for () { ; size must be >= Alignment + LookAhead, if it's not last block SizeT processed = Convert(data, size, ip, 1); data += processed; size -= processed; ip += processed; } */ #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Bra86.c ================================================ /* Bra86.c -- Converter for x86 code (BCJ) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *state & 0x7; if (size < 5) return 0; ip += 5; prevPosT = (SizeT)0 - 1; for (;;) { Byte *p = data + bufferPos; Byte *limit = data + size - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - data); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (ip + (UInt32)bufferPos) + src; else dest = src - (ip + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/BraIA64.c ================================================ /* BraIA64.c -- Converter for IA-64 code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" static const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 16) return 0; size -= 16; for (i = 0; i <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)data[i + j + bytePos] << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/CpuArch.h ================================================ /* CpuArch.h 2008-08-05 Igor Pavlov Public domain */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #ifdef LITTLE_ENDIAN_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #endif #if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzFindMt.c ================================================ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include "LzHash.h" #include "LzFindMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads2(name, v, action) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ { action; for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #define NO_INLINE MY_FAST_CALL Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->crc = mf->crc; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzFindMt.h ================================================ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFINDMT_H #define __LZFINDMT_H #include "Threads.h" #include "LzFind.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #include <string.h> #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ #include <string.h> /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include <stdio.h> #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifdef COMPRESS_MF_MT ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/LzmaLib.def ================================================ EXPORTS LzmaCompress LzmaUncompress ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/LzmaLib.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # End Group # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\IStream.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\LzmaLib.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/LzmaLib.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/LzmaLibExports.c ================================================ /* LzmaLibExports.c -- LZMA library DLL Entry point 2008-10-04 : Igor Pavlov : Public domain */ #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance = hInstance; dwReason = dwReason; lpReserved = lpReserved; return TRUE; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/makefile ================================================ MY_STATIC_LINK=1 SLIB = sLZMA.lib PROG = LZMA.dll SLIBPATH = $O\$(SLIB) DEF_FILE = LzmaLib.def CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIBS = $(LIBS) oleaut32.lib LIB_OBJS = \ $O\LzmaLibExports.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzmaLib.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../CPP/Build.mak" $(SLIBPATH): $O $(OBJS) lib -out:$(SLIBPATH) $(OBJS) $(LIBS) $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib/resource.rc ================================================ #include "../../CPP/7zip/MyVersionInfo.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib.c ================================================ /* LzmaLib.c -- LZMA library wrapper 2008-08-05 Igor Pavlov Public domain */ #include "LzmaEnc.h" #include "LzmaDec.h" #include "Alloc.h" #include "LzmaLib.h" static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaLib.h ================================================ /* LzmaLib.h -- LZMA library interface 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMALIB_H #define __LZMALIB_H #include "Types.h" #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 16 KB 0 32 1: 64 KB 0 32 2: 256 KB 0 32 3: 1 MB 0 32 4: 4 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7+: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/Lzma86Dec.c ================================================ /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2008-04-07 Igor Pavlov Public domain */ #include "Lzma86Dec.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaDec.h" #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(dest, *destLen, 0, &x86State, 0); } return SZ_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/Lzma86Dec.h ================================================ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86DEC_H #define __LZMA86DEC_H #include "../Types.h" /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/Lzma86Enc.c ================================================ /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #include <string.h> #include "Lzma86Enc.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaEnc.h" #define SZE_OUT_OVERFLOW SZE_DATA_ERROR static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; Bool useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, srcLen, 0, &x86State, 1); } } { size_t minSize = 0; Bool bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/Lzma86Enc.h ================================================ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86ENC_H #define __LZMA86ENC_H #include "../Types.h" /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, = 1 - x86 filter 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/LzmaUtil.c ================================================ /* LzmaUtil.c -- Test application for LZMA compression 2008-11-23 : Igor Pavlov : Public domain */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../Alloc.h" #include "../7zFile.h" #include "../7zVersion.h" #include "../LzmaDec.h" #include "../LzmaEnc.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; const char *kDataErrorMessage = "Data error"; static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; void PrintHelp(char *buffer) { strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" "\nUsage: lzma <e|d> inputFile outputFile\n" " e: encode file\n" " d: decode file\n"); } int PrintError(char *buffer, const char *message) { strcat(buffer, "\nError: "); strcat(buffer, message); strcat(buffer, "\n"); return 1; } int PrintErrorNumber(char *buffer, SRes val) { sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); return 1; } int PrintUserError(char *buffer) { return PrintError(buffer, "Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) { int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)); inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || thereIsSize && unpackSize == 0) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ RINOK(SeqInStream_Read(inStream, header, sizeof(header))); unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_Construct(&state); RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; rs = rs; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int main2(int numArgs, const char *args[], char *rs) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; Bool useOutFile = False; FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); if (numArgs == 1) { PrintHelp(rs); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(rs); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(rs); { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError(rs, "Incorrect UInt32 or UInt64"); } if (InFile_Open(&inStream.file, args[2]) != 0) return PrintError(rs, "Can not open input file"); if (numArgs > 3) { useOutFile = True; if (OutFile_Open(&outStream.file, args[3]) != 0) return PrintError(rs, "Can not open output file"); } else if (encodeMode) PrintUserError(rs); if (encodeMode) { UInt64 fileSize; File_GetLength(&inStream.file, &fileSize); res = Encode(&outStream.s, &inStream.s, fileSize, rs); } else { res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(rs, kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(rs, kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError(rs, kCantWriteMessage); else if (res == SZ_ERROR_READ) return PrintError(rs, kCantReadMessage); return PrintErrorNumber(rs, res); } return 0; } int MY_CDECL main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/LzmaUtil.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\7zFile.c # End Source File # Begin Source File SOURCE=..\7zFile.h # End Source File # Begin Source File SOURCE=..\7zStream.c # End Source File # Begin Source File SOURCE=..\7zVersion.h # End Source File # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\CpuArch.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/LzmaUtil.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/makefile ================================================ MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/LzmaUtil/makefile.gcc ================================================ PROG = lzma CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = \ LzmaUtil.o \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ 7zFile.o \ 7zStream.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaUtil.o: LzmaUtil.c $(CXX) $(CFLAGS) LzmaUtil.c Alloc.o: ../Alloc.c $(CXX) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CXX) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CXX) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CXX) $(CFLAGS) ../LzmaEnc.c 7zFile.o: ../7zFile.c $(CXX) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CXX) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Threads.c ================================================ /* Threads.c -- multithreading library 2008-08-05 Igor Pavlov Public domain */ #include "Threads.h" #include <process.h> static WRes GetError() { DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return 0; } WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(thread->handle); } WRes WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } WRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } WRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return HandleToWRes(p->handle); } WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return HandleToWRes(p->handle); } WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Threads.h ================================================ /* Threads.h -- multithreading library 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); WRes Thread_Wait(CThread *thread); WRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); WRes Event_Set(CEvent *event); WRes Event_Reset(CEvent *event); WRes Event_Wait(CEvent *event); WRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include <stddef.h> #ifdef _WIN32 #include <windows.h> #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zDecode.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnpackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnpackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _db.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &db = _db; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = db.Folders[folderIndex]; UInt64 unpackSize = folderInfo.GetUnpackSize(); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; // Count partial_folder_size // efi.UnpackSize += unpackSize; // importantTotalUnpacked += unpackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnpacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnpacked = 0; UInt64 totalFolderUnpacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnpacked += totalFolderUnpacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnpacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnpacked = efi.UnpackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &db = volume.Database; #else const CArchiveDatabaseEx &db = _db; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = db.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&db, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = db.Folders[folderIndex]; totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef _NO_CRYPTO bool passwordIsDefined; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &db.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; UInt64 fileSize = fi.Size; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fi.CrcDefined && _checkCrc) digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/CpuArch.h" } #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _db.Files.Size(); return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidPhySize, VT_UI8}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidOffset, VT_UI8} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _db.Folders.Size(); i++) { const CFolder &f = _db.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) { UInt64 value; if (v.GetItem(index, value)) { FILETIME ft; ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); prop = ft; } } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { case kpidPath: if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; case kpidIsDir: prop = item.IsDir; break; case kpidSize: { prop = item.Size; // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _db.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; case kpidEncrypted: prop = IsEncrypted(index2); break; case kpidIsAnti: prop = _db.IsItemAnti(index2); break; #ifndef _SFX case kpidMethod: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Props.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Props.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Props; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Props.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Props; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Props.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Props.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Props[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); #ifndef _NO_CRYPTO _passwordIsDefined = false; UString password; #endif HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO , getTextPassword, _passwordIsDefined #endif ); RINOK(result); _db.Fill(); _inStream = stream; } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); return S_OK; COM_TRY_END } #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _db; #ifndef _NO_CRYPTO bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif DECL_EXTERNAL_CODECS_VARS }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = (UInt32)kNumFastBytesForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = (UInt32)kDictionaryForHeaders; oneMethodInfo.Props.Add(prop); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Props = oneMethodInfo.Props; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Props.Size(); j++) { const CProp &prop = methodFull.Props[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) { ft = 0; ftDefined = false; if (!writeTime) return S_OK; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream != 0) db = &_db; #endif CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem ui; ui.NewProperties = IntToBool(newProperties); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; if (ui.IndexInArchive != -1) { const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; ui.Size = fi.Size; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } if (ui.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) nameIsDefined = false; else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { ui.Name = NItemName::MakeLegalName(prop.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } if (ui.NewData) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } updateItems.Add(ui); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef _NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if(encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; options.HeaderOptions.WriteATime = WriteATime; options.HeaderOptions.WriteMTime = WriteMTime; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; COutArchive archive; CArchiveDatabase newDatabase; HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, archive, newDatabase, outStream, updateCallback, options); RINOK(res); updateItems.ClearAndFree(); return archive.WriteDatabase(EXTERNAL_CODECS_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttributes, kComment, kEncodedHeader, kStartPos, kDummy }; } }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" } #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { static void BoolVector_Fill_False(CBoolVector &v, int size) { v.Clear(); v.Reserve(size); for (int i = 0; i < size; i++) v.Add(false); } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) { if (index >= (UInt32)v.Size()) return true; bool res = v[index]; v[index] = true; return res; } bool CFolder::CheckStructure() const { const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax const int kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); int i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; BoolVector_Fill_False(v, UnpackSizes.Size()); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; int i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { CIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; const CCoderInfo &coder = Coders[i]; for (j = 0; j < coder.NumInStreams; j++) inStreamToCoder.Add(i); for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } for (i = 0; i < kMaskSize; i++) for (int j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; for (i = 0; i < kMaskSize; i++) if (((1 << i) & mask[i]) != 0) return false; return true; } class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); coder.Props.SetCapacity((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bp; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { folder.PackStreams.Add(i); break; } if (folder.PackStreams.Size() != 1) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { BoolVector_Fill_False(packCRCsDefined, numPackStreams); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for (CNum i = 0; i < numPackStreams; i++) packCRCs.Add(0); } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnpackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CBoolVector crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnpackCRCDefined = crcsDefined[i]; folder.UnpackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { numUnpackStreamsInFolders.Clear(); numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnpackStreamsInFolders.IsEmpty()) for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(1); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CBoolVector digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { BoolVector_Fill_False(digestsDefined, numDigestsTotal); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) digests.Add(0); } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnpackInfo: { ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for (int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles) { ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Values.Reserve(numFiles); for (int i = 0; i < numFiles; i++) { UInt64 t = 0; if (v.Defined[i]) t = ReadUInt64(); v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArchiveInfo.DataStartPosition, db.PackSizes, db.PackCRCsDefined, db.PackCRCs, db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for (int i = 0; i < db.Folders.Size(); i++) { db.NumUnpackStreamsVector.Add(1); CFolder &folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digestsDefined.Add(folder.UnpackCRCDefined); digests.Add(folder.UnpackCRC); } } db.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!db.PackSizes.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; BoolVector_Fill_False(emptyStreamVector, (int)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); size_t ppp = _inByteBack->_pos; bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (int i = 0; i < db.Files.Size(); i++) _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; file.AttribDefined = boolVector[i]; if (file.AttribDefined) file.Attrib = ReadUInt32(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; BoolVector_Fill_False(emptyFileVector, numEmptyStreams); BoolVector_Fill_False(antiFileVector, numEmptyStreams); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThrowIncorrect(); addPropIdToList = false; break; } default: addPropIdToList = isKnownType = false; } if (isKnownType) { if(addPropIdToList) db.ArchiveInfo.FileInfoPopIDs.Add(type); } else SkeepData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; CNum numAntiItems = 0; for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti.Add(isAnti); } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; public: size_t _pos; void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnpackSizes; UInt32 UnpackCRC; bool UnpackCRCDefined; CFolder(): UnpackCRCDefined(false) {} UInt64 GetUnpackSize() const // test it { if (UnpackSizes.IsEmpty()) return 0; for (int i = UnpackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnpackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } bool CheckStructure() const; }; struct CUInt64DefVector { CRecordVector<UInt64> Values; CRecordVector<bool> Defined; void Clear() { Values.Clear(); Defined.Clear(); } void ReserveDown() { Values.ReserveDown(); Values.ReserveDown(); } bool GetItem(int index, UInt64 &value) const { if (index < Defined.Size() && Defined[index]) { value = Values[index]; return true; } value = 0; return false; } void SetItem(int index, bool defined, UInt64 value) { while (index >= Defined.Size()) Defined.Add(false); Defined[index] = defined; if (!defined) return; while (index >= Values.Size()) Values.Add(0); Values[index] = value; } bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } }; struct CFileItem { UInt64 Size; UInt32 Attrib; UInt32 Crc; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; bool AttribDefined; CFileItem(): HasStream(true), IsDir(false), CrcDefined(false), AttribDefined(false) {} void SetAttrib(UInt32 attrib) { AttribDefined = true; Attrib = attrib; } }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnpackStreamsVector; CObjectVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnpackStreamsVector.Clear(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); } void ReserveDown() { PackSizes.ReserveDown(); PackCRCsDefined.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); Files.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { int size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsSolid() const { for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } void SetItemAnti(int index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; void AddFile(const CFileItem &file, const CFileItem2 &file2); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if (processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 3; return WriteDirect(buf, 8); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[24]; SetUInt64(buf + 4, h.NextHeaderOffset); SetUInt64(buf + 12, h.NextHeaderSize); SetUInt32(buf + 20, h.NextHeaderCRC); SetUInt32(buf, CrcCalc(buf + 4, 20)); return WriteDirect(buf, 24); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) { _outByte.WriteByte(b); _crc = CRC_UPDATE_BYTE(_crc, b); } else _outByte2.WriteByte(b); } void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } WriteByte(firstByte); for (;i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef _7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propsSize = coder.Props.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propsSize != 0) ? 0x20 : 0 ); WriteByte(b); WriteBytes(longID, idSize); if (isComplex) { WriteNumber(coder.NumInStreams); WriteNumber(coder.NumOutStreams); } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; WriteNumber(bindPair.InIndex); WriteNumber(bindPair.OutIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { WriteNumber(folder.PackStreams[i]); } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for (int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } void COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for (i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); if (numDefined == digestsDefined.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(digestsDefined); } for (i = 0; i < digests.Size(); i++) if (digestsDefined[i]) WriteUInt32(digests[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); for (int i = 0; i < packSizes.Size(); i++) WriteNumber(packSizes[i]); WriteHashDigests(packCRCsDefined, packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); for (int i = 0; i < folders.Size(); i++) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); int i; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnpackSizes.Size(); j++) WriteNumber(folder.UnpackSizes[j]); } CRecordVector<bool> unpackCRCsDefined; CRecordVector<UInt32> unpackCRCs; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unpackCRCsDefined.Add(folder.UnpackCRCDefined); unpackCRCs.Add(folder.UnpackCRC); } WriteHashDigests(unpackCRCsDefined, unpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { WriteByte(NID::kSubStreamsInfo); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } } bool needFlag = true; CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) { if (j + 1 != numUnpackStreamsInFolders[i]) { if (needFlag) WriteByte(NID::kSize); needFlag = false; WriteNumber(unpackSizes[index]); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnpackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } WriteHashDigests(digestsDefined2, digests2); WriteByte(NID::kEnd); } void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) { return; } /* 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } */ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) { const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8; const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); WriteByte(type); WriteNumber(dataSize); if (numDefined == v.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(v); } WriteByte(0); } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { int numDefined = 0; int i; for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) numDefined++; if (numDefined == 0) return; WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) WriteUInt64(v.Values[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnpackCRCDefined = true; folderItem.UnpackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } void COutArchive::WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; headerOffset = packedSize; WriteByte(NID::kHeader); // Archive Properties if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCsDefined, db.PackCRCs); WriteUnpackInfo(db.Folders); CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digestsDefined.Add(file.CrcDefined); digests.Add(file.Crc); } WriteSubStreamsInfo( db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.Reserve(db.Files.Size()); int numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) if (db.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { WriteByte(NID::kEmptyStream); WriteNumber((emptyStreamVector.Size() + 7) / 8); WriteBoolVector(emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDir); if (!file.IsDir) numEmptyFiles++; bool isAnti = db.IsItemAnti(i); antiVector.Add(isAnti); if (isAnti) numAntiItems++; } } if (numEmptyFiles > 0) { WriteByte(NID::kEmptyFile); WriteNumber((emptyFileVector.Size() + 7) / 8); WriteBoolVector(emptyFileVector); } if (numAntiItems > 0) { WriteByte(NID::kAnti); WriteNumber((antiVector.Size() + 7) / 8); WriteBoolVector(antiVector); } } } { /* ---------- Names ---------- */ int numDefined = 0; size_t namesDataSize = 0; for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; if (!name.IsEmpty()) numDefined++; namesDataSize += (name.Length() + 1) * 2; } if (numDefined > 0) { namesDataSize++; SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; for (int t = 0; t <= name.Length(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } } } } if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); int numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; boolVector.Add(defined); if (defined) numDefined++; } if (numDefined > 0) { WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (file.AttribDefined) WriteUInt32(file.Attrib); } } } WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (db.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { bool encodeHeaders = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, headerOptions, headerOffset); if (encodeHeaders) { CByteBuffer buf; buf.SetCapacity(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, headerOptions, headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, (const Byte *)buf, _countSize, packSizes, folders)); _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>()); WriteUnpackInfo(folders); WriteByte(NID::kEnd); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const { file = Files[index]; file2.CTimeDefined = CTime.GetItem(index, file2.CTime); file2.ATimeDefined = ATime.GetItem(index, file2.ATime); file2.MTimeDefined = MTime.GetItem(index, file2.MTime); file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); file2.IsAnti = IsItemAnti(index); } void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) { int index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); SetItemAnti(index, file2.IsAnti); Files.Add(file); } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; bool WriteCTime; bool WriteATime; bool WriteMTime; CHeaderOptions(): CompressMainHeader(true), WriteCTime(false), WriteATime(false), WriteMTime(true) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); void WriteUnpackInfo(const CObjectVector<CFolder> &folders); void WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); void WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCTime, NULL, kpidCTime, VT_FILETIME}, { NID::kMTime, NULL, kpidMTime, VT_FILETIME}, { NID::kATime, NULL, kpidATime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttrib, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, #ifndef _SFX { 97, NULL, kpidEncrypted, VT_BOOL}, { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if ((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // 7zUpdate.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnpackStreamsVector[i1], db.NumUnpackStreamsVector[i2])); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = ui.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = ui.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kMatchFinderForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = kDictionaryForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Props.Add(prop); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData) continue; if (!ui.HasStream()) continue; if (useFilters) { const UString name = ui.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); for (int i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (db != 0) { for(i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; for (CNum fileIndex = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fileIndex++) { if (db->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnpackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)db); } //////////////////////////// RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; if (numSolidFiles == 1) { if (ui.Size > inSizeForReduce) inSizeForReduce = ui.Size; } else inSizeForReduce += ui.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = db->Folders[folderIndex]; CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; db->GetFile(fi, file, file2); if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewProperties) { CFileItem uf; FromUpdateItemToFileItem(ui, uf, file2); uf.Size = file.Size; uf.Crc = file.Crc; uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; } } newDatabase.AddFile(file, file2); } } } folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = ui.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; if (file.Size != 0) { file.CrcDefined = true; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } newDatabase.AddFile(file, file2); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; } } groups.ClearAndFree(); { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1) if (db->Files[ui.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); newDatabase.AddFile(file, file2); } } newDatabase.ReserveDown(); return S_OK; } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { return Update2( EXTERNAL_CODECS_LOC_VARS inStream, db, updateItems, archive, newDatabase, seqOutStream, updateCallback, options); } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { int IndexInArchive; int IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; UInt32 Attrib; bool NewData; bool NewProperties; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL && result != S_FALSE) return result; } RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../../ICoder.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Props.Size(); j++) if (oneMethodInfo.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; oneMethodInfo.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); prop.Id = (name.CompareNoCase(L"D") == 0) ? NCoderPropID::kDictionarySize : NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { bool isSolid; switch(value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; WriteCTime = false; WriteATime = false; WriteMTime = true; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) { RINOK(SetBoolProperty(_encryptHeaders, value)); _encryptHeadersSpecified = true; return S_OK; } if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp prop; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); prop.Id = NCoderPropID::kDictionarySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(1).CompareNoCase(L"C") == 0) { UInt32 blockSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); prop.Id = NCoderPropID::kBlockSize; prop.Value = blockSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); prop.Id = NCoderPropID::kUsedMemorySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); } return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (value.boolVal != VARIANT_FALSE); return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } #define INTERFACE_IArchiveOpenCallback(x) \ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { INTERFACE_IArchiveOpenCallback(PURE); }; #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { INTERFACE_IArchiveExtractCallback(PURE) }; #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { INTERFACE_IArchiveOpenVolumeCallback(PURE); }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ Int32 *newData, /*1 - new data, 0 - old data */ \ Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ ) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { INTERFACE_IArchiveUpdateCallback(PURE); }; #define INTERFACE_IArchiveUpdateCallback2(x) \ INTERFACE_IArchiveUpdateCallback(x) \ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { INTERFACE_IArchiveUpdateCallback2(PURE); }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp ================================================ // LzmaArcRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "LzmaHandler.h" static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } static CArcInfo g_ArcInfo = { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; REGISTER_ARC(Lzma) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp ================================================ // LzmaFiltersDecode.cpp #include "StdAfx.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; HRESULT CDecoder::Code( DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress) { *inProcessedSize = (UInt64)(Int64)-1; if (block.FilterMethod > 1) return E_NOTIMPL; if (!_lzmaDecoder) { RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); if (_lzmaDecoder == 0) return E_NOTIMPL; } { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); } bool filteredMode = (block.FilterMethod == 1); CMyComPtr<ICompressSetOutStream> setOutStream; if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { RINOK(flush->Flush()); } RINOK(setOutStream->ReleaseOutStream()); } CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); if (getInStreamProcessedSize) { RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); } return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h ================================================ // LzmaFiltersDecode.h #ifndef __LZMA_FILTERS_DECODE_H #define __LZMA_FILTERS_DECODE_H #include "../../Common/CreateCoder.h" #include "LzmaItem.h" namespace NArchive { namespace NLzma { class CDecoder { CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; public: HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.cpp ================================================ // LzmaHandler.cpp #include "StdAfx.h" #include "LzmaHandler.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/DummyOutStream.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { STATPROPSTG kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_UI1} }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = 1; return S_OK; } static void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s + MyStringLen(s)); } static void DictSizeToString(UInt32 value, wchar_t *s) { for (int i = 0; i <= 31; i++) if ((UInt32(1) << i) == value) { ConvertUInt32ToString(i, s); return; } wchar_t c = L'b'; if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = L'm'; } else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = L'k'; } ConvertUInt32ToString(value, s); int p = MyStringLen(s); s[p++] = c; s[p++] = L'\0'; } static void MyStrCat(wchar_t *d, const wchar_t *s) { MyStringCopy(d + MyStringLen(d), s); } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { if (index != 0) return E_INVALIDARG; NWindows::NCOM::CPropVariant propVariant; switch(propID) { case kpidSize: if (m_StreamInfo.HasUnpackSize()) propVariant = (UInt64)m_StreamInfo.UnpackSize; break; case kpidPackSize: propVariant = (UInt64)m_PackSize; break; case kpidMethod: { wchar_t s[64]; s[0] = '\0'; if (m_StreamInfo.IsThereFilter) { const wchar_t *f; if (m_StreamInfo.FilterMethod == 0) f = L"Copy"; else if (m_StreamInfo.FilterMethod == 1) f = L"BCJ"; else f = L"Unknown"; MyStrCat(s, f); MyStrCat(s, L" "); } MyStrCat(s, L"LZMA:"); DictSizeToString(m_StreamInfo.GetDicSize(), s); propVariant = s; break; } } propVariant.Detach(value); return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* openArchiveCallback */) { { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); if (res != S_OK) return S_FALSE; Byte b; RINOK(ReadStream_FALSE(inStream, &b, 1)); if (b != 0) return S_FALSE; UInt64 endPos; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); m_Stream = inStream; } return S_OK; } STDMETHODIMP CHandler::Close() { m_Stream.Release(); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN bool allFilesMode = (numItems == UInt32(-1)); if (!allFilesMode) { if (numItems == 0) return S_OK; if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); RINOK(extractCallback->SetTotal(m_PackSize)); UInt64 currentTotalPacked = 0; CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); { CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(); if(!testMode && !realOutStream) return S_OK; extractCallback->PrepareOperation(askMode); } CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); CDecoder decoder; RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); UInt64 streamPos = m_StreamStartPosition; Int32 opRes = NArchive::NExtract::NOperationResult::kOK; bool firstItem = true; for (;;) { CHeader st; HRESULT result = ReadStreamHeader(m_Stream, st); if (result != S_OK) { if (firstItem) return E_FAIL; break; } firstItem = false; lps->OutSize = outStreamSpec->GetSize(); lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); streamPos += st.GetHeaderSize(); UInt64 packProcessed; { result = decoder.Code( EXTERNAL_CODECS_VARS st, m_Stream, outStream, &packProcessed, progress); if (result == E_NOTIMPL) { opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; } if (result == S_FALSE) { opRes = NArchive::NExtract::NOperationResult::kDataError; break; } RINOK(result); } if (packProcessed == (UInt64)(Int64)-1) break; RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); currentTotalPacked += packProcessed; streamPos += packProcessed; } outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.h ================================================ // Lzma/Handler.h #ifndef __GZIP_HANDLER_H #define __GZIP_HANDLER_H #include "Common/MyCom.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #include "LzmaIn.h" namespace NArchive { namespace NLzma { // const UInt64 k_LZMA = 0x030101; class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(IInArchive) QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Open)(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); STDMETHOD(Close)(); STDMETHOD(GetNumberOfItems)(UInt32 *numItems); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); UString GetMethodString(); public: CHandler() { } private: CHeader m_StreamInfo; UInt64 m_StreamStartPosition; UInt64 m_PackSize; CMyComPtr<IInStream> m_Stream; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaIn.cpp ================================================ // Archive/LzmaIn.cpp #include "StdAfx.h" #include "LzmaIn.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace NLzma { static bool CheckDictSize(const Byte *p) { UInt32 dicSize = GetUi32(p); int i; for (i = 1; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return false; } HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) { Byte sig[5 + 9]; RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); const Byte kMaxProp0Val = 5 * 5 * 9 - 1; if (sig[0] > kMaxProp0Val) return S_FALSE; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i]; block.IsThereFilter = false; block.FilterMethod = 0; if (!CheckDictSize(sig + 1)) { if (sig[0] > 1 || sig[1] > kMaxProp0Val) return S_FALSE; block.IsThereFilter = true; block.FilterMethod = sig[0]; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i + 1]; if (!CheckDictSize(block.LzmaProps + 1)) return S_FALSE; RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); } UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); block.UnpackSize = GetUi64(sig + unpOffset); if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) return S_FALSE; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaIn.h ================================================ // Archive/LzmaIn.h #ifndef __ARCHIVE_LZMA_IN_H #define __ARCHIVE_LZMA_IN_H #include "LzmaItem.h" #include "../../IStream.h" namespace NArchive { namespace NLzma { HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/LzmaItem.h ================================================ // Archive/LzmaItem.h #ifndef __ARCHIVE_LZMA_ITEM_H #define __ARCHIVE_LZMA_ITEM_H #include "Common/Types.h" #include "../../../../C/CpuArch.h" namespace NArchive { namespace NLzma { struct CHeader { UInt64 UnpackSize; bool IsThereFilter; Byte FilterMethod; Byte LzmaProps[5]; UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Lzma/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Split/SplitHandler.cpp ================================================ // SplitHandler.cpp #include "StdAfx.h" #include "Common/ComTry.h" #include "Common/Defs.h" #include "Common/NewHandler.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/MultiStream.h" #include "SplitHandler.h" using namespace NWindows; using namespace NTime; namespace NArchive { namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO class CSeqName { public: UString _unchangedPart; UString _changedPart; bool _splitStyle; UString GetNextName() { UString newName; if (_splitStyle) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { c = 'a'; newName = c + newName; continue; } else if (c == 'Z') { c = 'A'; newName = c + newName; continue; } c++; if ((c == 'z' || c == 'Z') && i == 0) { _unchangedPart += c; wchar_t newChar = (c == 'z') ? L'a' : L'A'; newName.Empty(); numLetters++; for (int k = 0; k < numLetters; k++) newName += newChar; break; } newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } else { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } _changedPart = newName; return _unchangedPart + _changedPart; } }; STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); if (openArchiveCallback == 0) return S_FALSE; // try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback) != S_OK) return S_FALSE; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; _name = prop.bstrVal; } int dotPos = _name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { prefix = _name.Left(dotPos + 1); ext = _name.Mid(dotPos + 1); } else ext = _name; UString extBig = ext; extBig.MakeUpper(); CSeqName seqName; int numLetters = 2; bool splitStyle = false; if (extBig.Right(2) == L"AA") { splitStyle = true; while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != 'A') break; numLetters++; } } else if (ext.Right(2) == L"01") { while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Length()) return S_FALSE; } else return S_FALSE; _streams.Add(stream); seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); seqName._changedPart = ext.Right(numLetters); seqName._splitStyle = splitStyle; if (prefix.Length() < 1) _subName = L"file"; else _subName = prefix.Left(prefix.Length() - 1); _totalSize = 0; UInt64 size; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName = seqName.GetNextName(); CMyComPtr<IInStream> nextStream; HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } } /* catch(...) { return S_FALSE; } */ return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { _sizes.Clear(); _streams.Clear(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; } prop.Detach(value); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) { COM_TRY_BEGIN if (numItems != UInt32(-1)) { if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; extractCallback->SetTotal(_totalSize); /* CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) return E_FAIL; */ UInt64 currentTotalSize = 0; UInt64 currentItemSize; RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = 0; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->PrepareOperation(askMode)); if (testMode) { RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); return S_OK; } if (!testMode && (!realOutStream)) return S_OK; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); currentItemSize = copyCoderSpec->TotalSize; } realOutStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; for (int i = 0; i < _streams.Size(); i++) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Split/SplitHandler.h ================================================ // Split/Handler.h #ifndef __SPLIT_HANDLER_H #define __SPLIT_HANDLER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../IArchive.h" namespace NArchive { namespace NSplit { class CHandler: public IInArchive, public IInArchiveGetStream, // public IOutArchive, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); private: UString _subName; UString _name; CObjectVector<CMyComPtr<IInStream> > _streams; CRecordVector<UInt64> _sizes; UInt64 _totalSize; }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Split/SplitHandlerOut.cpp ================================================ // Split/OutHandler.cpp #include "StdAfx.h" #include "SplitHandler.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" using namespace NWindows; namespace NArchive { namespace NSplit { /* STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN if (numItems != 1) return E_INVALIDARG; UInt64 volumeSize = 0; CMyComPtr<IArchiveUpdateCallback2> callback2; updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&callback2); RINOK(callback2->GetVolumeSize(0, &volumeSize)); Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; UInt32 fileIndex = 0; RINOK(updateCallback->GetUpdateItemInfo(fileIndex, &newData, &newProperties, &indexInArchive)); if (newProperties != 0) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } } UInt64 newSize; bool thereIsCopyData = false; if (newData != 0) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; newSize = prop.uhVal.QuadPart; } else thereIsCopyData = true; UInt64 pos = 0; while(pos < newSize) { } return S_OK; COM_TRY_END } */ }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Split/SplitRegister.cpp ================================================ // SplitRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "SplitHandler.h" static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } /* #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } #else #define CreateArcOut 0 #endif */ static CArcInfo g_ArcInfo = { L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; REGISTER_ARC(Split) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/Split/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Archive/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwapRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderOpt.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # Begin Group "LZM" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaItem.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ LZM_OBJS = \ $O\LzmaArcRegister.obj \ $O\LzmaFiltersDecode.obj \ $O\LzmaHandler.obj \ $O\LzmaIn.obj \ SPLIT_OBJS = \ $O\SplitHandler.obj \ $O\SplitHandlerOut.obj \ $O\SplitRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(LZM_OBJS) \ $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp $(COMPL) $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } RINOK(WriteStream(outStream, _buffer, size)); _nowPos64 += size; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { size_t processedSize = kBufferSize - bufferPos; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } RINOK(WriteStream(_outStream, _buffer, _bufferPos)); _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; size_t processedSizeTemp = kBufferSize - _bufferPos; RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); _bufferPos = _bufferPos + (UInt32)processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if (_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } UInt32 ReadBytes(Byte *buf, UInt32 size) { if ((UInt32)(_bufferLimit - _buffer) >= size) { for (UInt32 i = 0; i < size; i++) buf[i] = _buffer[i]; _buffer += size; return size; } for (UInt32 i = 0; i < size; i++) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return i; buf[i] = *_buffer++; } return size; } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; if (processedSize != NULL) *processedSize = 0; if (size > _size) { size = (UInt32)_size; if (size == 0) { _overflow = true; return E_FAIL; } } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize != NULL) *processedSize = size; return result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size) { _size = size; _overflow = false; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "MethodProps.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProps = method.Props.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProps != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; HRESULT res = S_OK; try { for (int i = 0; i < numProps; i++) { const CProp &prop = method.Props[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "../../Common/MyVector.h" #include "../../Windows/PropVariant.h" #include "MethodId.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Props; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { memcpy(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(data, _dataPointer + _pos, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memcpy(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, (size_t)size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return (rem == size ? S_OK : E_FAIL); } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); WRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/Bcj2Coder.cpp ================================================ // Bcj2Coder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/Bcj2Coder.h ================================================ // Bcj2Coder.h #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "RangeCoderBit.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/Bcj2Register.cpp ================================================ // Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BcjCoder.cpp ================================================ // BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BcjCoder.h ================================================ // BcjCoder.h #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H extern "C" { #include "../../../C/Bra.h" } #include "BranchCoder.h" struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BcjRegister.cpp ================================================ // BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BranchCoder.h ================================================ // BranchCoder.h #ifndef __COMPRESS_BRANCH_CODER_H #define __COMPRESS_BRANCH_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BranchMisc.cpp ================================================ // BranchMisc.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Bra.h" } #include "BranchMisc.h" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BranchMisc.h ================================================ // BranchMisc.h #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) MyClassA(BC_ARMT, 0x07, 1) MyClassA(BC_PPC, 0x02, 5) MyClassA(BC_SPARC, 0x08, 5) MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMT) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/ByteSwap.h ================================================ // ByteSwap.h #ifndef __COMPRESS_BYTE_SWAP_H #define __COMPRESS_BYTE_SWAP_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPY_CODER_H #define __COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/CopyRegister.cpp ================================================ // CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaEncoder.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "LzmaUtil" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #include "LzmaBenchCon.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif extern "C" { #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/LzmaUtil/Lzma86Dec.h" #include "../../../../C/LzmaUtil/Lzma86Enc.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } static void ParseUInt32(const CParser &parser, int index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) IncorrectCommand(); } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictDefined = false; UInt32 dict = (UInt32)-1; if(parser[NKey::kDict].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dict); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; size_t inSize = (size_t)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; Byte *outBuffer = 0; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictDefined) dict = 1 << 23; int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictDefined) dict = 1 << 23; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = (BSTR)(const wchar_t *)mf; props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; int numProps = kNumPropsMax; if (!mcDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; decoderSpec->FinishStream = true; const UInt32 kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int MY_CDECL main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" } #include "../../../Common/MyCom.h" #ifdef BENCH_MT #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #else #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLzma::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLzma::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe LIBS = $(LIBS) user32.lib CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ LZMA_OPT_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra86.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ C_LZMAUTIL_OBJS = \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ OBJS = \ $O\StdAfx.obj \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(C_OBJS) \ $(C_LZMAUTIL_OBJS) \ $O\FileStreams.obj \ $O\FileIO.obj \ !include "../../../Build.mak" $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZMAUTIL_OBJS): ../../../../C/LzmaUtil/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaDecoder.o \ LzmaEncoder.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ Bra86.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ Lzma86Dec.o \ Lzma86Enc.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaDecoder.o: ../LzmaDecoder.cpp $(CXX) $(CFLAGS) ../LzmaDecoder.cpp LzmaEncoder.o: ../LzmaEncoder.cpp $(CXX) $(CFLAGS) ../LzmaEncoder.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c Bra86.o: ../../../../C/Bra86.c $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c LzFind.o: ../../../../C/LzFind.c $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c LzmaDec.o: ../../../../C/LzmaDec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c LzmaEnc.o: ../../../../C/LzmaEnc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c Lzma86Dec.o: ../../../../C/LzmaUtil/Lzma86Dec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Dec.c Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma86Enc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LzmaDecoder.cpp ================================================ // LzmaDecoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) { LzmaDec_Construct(&_state); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); MyFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; LzmaDec_Init(&_state); _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.dicPos; SizeT curSize = _state.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; } #endif }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LzmaDecoder.h ================================================ // LzmaDecoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H extern "C" { #include "../../../C/LzmaDec.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif bool FinishStream; CDecoder(); virtual ~CDecoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LzmaEncoder.cpp ================================================ // LzmaEncoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; // case SZ_ERROR_THREAD: return E_FAIL; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(void *object, void *data, size_t *size) { UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); *size = curSize; return (SRes)res; } static size_t MyWrite(void *object, const void *data, size_t size) { CSeqOutStream *p = (CSeqOutStream *)object; p->Res = WriteStream(p->RealStream, data, size); if (p->Res != 0) return 0; return size; } static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } static void SzFree(void *, void *address) { MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { _seqInStream.SeqInStream.Read = MyRead; _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) throw 1; } CEncoder::~CEncoder() { if (_encoder != 0) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; switch (propIDs[i]) { case NCoderPropID::kNumFastBytes: if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; case NCoderPropID::kMatchFinderCycles: if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; case NCoderPropID::kAlgorithm: if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; case NCoderPropID::kDictionarySize: if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; case NCoderPropID::kPosStateBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; case NCoderPropID::kLitPosBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; case NCoderPropID::kLitContextBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; case NCoderPropID::kMultiThread: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; case NCoderPropID::kMatchFinder: if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; default: return E_INVALIDARG; } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte props[LZMA_PROPS_SIZE]; size_t size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); return WriteStream(outStream, props, size); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _seqOutStream.RealStream = outStream; _seqOutStream.Res = S_OK; return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _seqOutStream.RealStream.Release(); return S_OK; } typedef struct _CCompressProgressImp { ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; } CCompressProgressImp; #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) { CCompressProgressImp *p = (CCompressProgressImp *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { CCompressProgressImp progressImp; progressImp.p.Progress = CompressProgress; progressImp.Progress = progress; progressImp.Res = SZ_OK; _seqInStream.RealStream = inStream; SetOutStream(outStream); SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); ReleaseOutStream(); if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) return _seqOutStream.Res; if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) return progressImp.Res; return SResToHRESULT(res); } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LzmaEncoder.h ================================================ // LzmaEncoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H extern "C" { #include "../../../C/LzmaEnc.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { struct CSeqInStream { ISeqInStream SeqInStream; ISequentialInStream *RealStream; }; struct CSeqOutStream { ISeqOutStream SeqOutStream; CMyComPtr<ISequentialOutStream> RealStream; HRESULT Res; }; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; CSeqInStream _seqInStream; CSeqOutStream _seqOutStream; public: CEncoder(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/LzmaRegister.cpp ================================================ // LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/RangeCoder.h ================================================ // Compress/RangeCoder.h #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) { Range >>= 1; Low += Range & (0 - ((value >> numBits) & 1)); if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/RangeCoderBit.h ================================================ // Compress/RangeCoderBit.h #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 4; const int kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/Compress/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kBlockSize, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define INTERFACE_IProgress(x) \ STDMETHOD(SetTotal)(UInt64 total) x; \ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ DECL_INTERFACE(IProgress, 0, 5) { INTERFACE_IProgress(PURE) }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_7ZIP_VERSION "7-Zip 4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/PropID.h ================================================ // PropID.h #ifndef __7ZIP_PROPID_H #define __7ZIP_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; UInt32 Attrib; bool isDir; bool AttribDefined; bool MTimeDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (NFile::NFind::FindFile(fullProcessedPath, fi)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.MTimeDefined) _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if (newData != NULL) *newData = BoolToInt(true); if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) *indexInArchive = (UInt32)-1; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: prop = dirItem.Name; break; case kpidIsDir: prop = dirItem.isDir(); break; case kpidSize: prop = dirItem.Size; break; case kpidAttrib: prop = dirItem.Attrib; break; case kpidCTime: prop = dirItem.CTime; break; case kpidATime: prop = dirItem.ATime; break; case kpidMTime: prop = dirItem.MTime; break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if (dirItem.isDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////////////////// // Main function int MY_CDECL main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; command.MakeLower(); UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.Compare("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem di; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(name, fi)) { PrintString(UString(L"Can't find file") + name); return 1; } di.Attrib = fi.Attrib; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Name = name; di.FullPath = name; dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.Compare("l") == 0) listCommand = true; else if (command.Compare("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, #ifndef _NO_CRYPTO kPassword, #endif kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, #ifndef _NO_CRYPTO { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, #endif { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for (int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for (int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for (int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); UStringVector archivePaths; { CDirItems dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } for (int i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) archivePaths.Add(dirItems.GetPhyPath(i)); } } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; int i; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if (parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if (options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if (options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO bool PasswordEnabled; UString Password; #endif bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcMTimeDefault = utcMTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDir) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) INTERFACE_IArchiveExtractCallback(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _encrypted; struct CProcessedFileInfo { FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attributes; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool IsDir; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcMTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), WriteMTime(true), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch(propID) { case kpidName: prop = _subArchiveName; break; } else switch(propID) { case kpidName: prop = _fileInfo.Name; break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; case kpidCTime: prop = _fileInfo.CTime; break; case kpidATime: prop = _fileInfo.ATime; break; case kpidMTime: prop = _fileInfo.MTime; break; } prop.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (ReOpenCallback) { CMyComPtr<ICryptoGetTextPassword> getTextPassword; ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" #ifdef _NO_CRYPTO #define INTERFACE_IOpenCallbackUI_Crypto(x) #else #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ #endif #define INTERFACE_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI { INTERFACE_IOpenCallbackUI(=0) }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L"~"; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" #include "../../Archive/IArchive.h" struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UInt32 Attrib; int PhyParent; int LogParent; CDirItem(): PhyParent(-1), LogParent(-1) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; public: CObjectVector<CDirItem> Items; int GetNumFolders() const { return Prefixes.Size(); } UString GetPhyPath(int index) const; UString GetLogPath(int index) const; int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; struct CArcItem { UInt64 Size; FILETIME MTime; UString Name; bool IsDir; bool SizeDefined; bool Censored; UInt32 IndexInServer; int TimeType; CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include <stdio.h> #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; di.Name = fi.Name; dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; int len = name.Length(); int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Length(); int totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; len -= name.Length(); memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; len -= s.Length(); memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } UString CDirItems::GetPhyPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } UString CDirItems::GetLogPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); for (;;) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParent, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; if (!NFind::FindFile(phyPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); UString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParentCur, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &curFolderName, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { const UString name2 = curFolderName + (wchar_t)kDirDelimiter; int parent = dirItems.AddPrefix(phyParent, logParent, name2); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fi.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); for (int ttt = 0; ; ttt++) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); const UString &name = fi.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", options.DefaultItemName); #ifdef _WIN32 outDir.TrimRight(); #endif if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.MTime, options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } res.TrimRight(); return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static const TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fi; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) if (!fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } #ifndef _SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int slashPos2 = arcPath.ReverseFind(L'.'); int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; for (int i = 0; i < Formats.Size(); i++) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) if (Formats[i].Name.CompareNoCase(arcType) == 0) return i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (int pos = 0; pos < arcType.Length();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) pos2 = arcType.Length(); const UString name = arcType.Mid(pos, pos2 - pos); int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = pos2 + 1; } return true; } #endif #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UInt32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) { result = defaultName; NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (arcTypeIndex >= 0) orderIndices.Add(arcTypeIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; Byte hash[1 << 16]; memset(hash, 0xFF, 1 << 16); Byte prevs[256]; if (orderIndices.Size() > 255) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < 2) continue; UInt32 v = sig[0] | ((UInt32)sig[1] << 8); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize--; for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[buf[pos] | ((UInt32)buf[pos + 1] << 8)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = buf[pos] | ((UInt32)buf[pos + 1] << 8); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + 1) if (TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif } for(int i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; RINOK(result); *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { if (formatIndices.Size() >= 3) return E_NOTIMPL; int arcTypeIndex = -1; if (formatIndices.Size() >= 1) arcTypeIndex = formatIndices[formatIndices.Size() - 1]; HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); if (formatIndices.Size() == 1) return S_OK; arcTypeIndex = -1; if (formatIndices.Size() >= 2) arcTypeIndex = formatIndices[formatIndices.Size() - 2]; HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || !getStream) return resSpec; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK || !subSeqStream) return resSpec; CMyComPtr<IInStream> subStream; result = subSeqStream.QueryInterface(IID_IInStream, &subStream); if (result != S_OK || !subStream) return resSpec; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return resSpec; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result != S_OK) return resSpec; return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, NULL, openCallback); int formatInfo; return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, formatIndices, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; SetCallback(fileName, NULL, openCallback, openCallbackNew); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; bool IsOpen; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCTime: case kpidATime: case kpidMTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttrib: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name[name.Length() - 1]; if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name = name.Left(name.Length() - 1); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/StdAfx.h ================================================ // stdafx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Time.h" #include "../../Common/FileStreams.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) { if (formatIndices.Size() > 1) return false; int arcTypeIndex = -1; if (formatIndices.Size() != 0) arcTypeIndex = formatIndices[0]; if (arcTypeIndex >= 0) MethodMode.FormatIndex = arcTypeIndex; else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; if (!arcInfo.UpdateEnabled) return false; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } /* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) { return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); } */ static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArcItem> &arcItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CDirItems &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! // CUpdateProduceCallbackImp upCallback(&arcItems, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); } UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); // check it: defaultItemName !!! if (ai.Name.IsEmpty()) ai.Name = defaultItemName; RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); { CPropVariant prop; RINOK(archive->GetProperty(i, kpidSize, &prop)); ai.SizeDefined = (prop.vt != VT_EMPTY); if (ai.SizeDefined) ai.Size = ConvertPropVariantToUInt64(prop); } { CPropVariant prop; RINOK(archive->GetProperty(i, kpidTimeType, &prop)); if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; switch(ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: break; default: return E_FAIL; } } } ai.IndexInServer = i; arcItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArcItem> &arcItems, CDirItems &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, arcItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) { return Callback->ScanProgress(numFolders, numFiles, path); } }; #ifdef _WIN32 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( ULONG_PTR ulUIParam, LPSTR lpszDelimChar, LPSTR lpszFilePaths, LPSTR lpszFileNames, ULONG ulReserved ); typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; #endif HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CDirItems dirItems; if (options.StdInMode) { CDirItem di; di.Name = options.StdInFileName; di.Size = (UInt64)(Int64)-1; di.Attrib = 0; NTime::GetCurUtcFileTime(di.MTime); di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArcItem> arcItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, arcItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArcItems(0), UpdatePairs(0), NewNames(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); } */ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData != NULL) *newData = BoolToInt(up.NewData); if (newProps != NULL) *newProps = BoolToInt(up.NewProps); if (indexInArchive != NULL) { *indexInArchive = (UInt32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = up.IsAnti; prop.Detach(value); return S_OK; } if (up.IsAnti) { switch(propID) { case kpidIsDir: case kpidPath: break; case kpidSize: prop = (UInt64)0; prop.Detach(value); return S_OK; default: prop.Detach(value); return S_OK; } } if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; } } else { if (propID == kpidPath) { if (up.NewNameIndex >= 0) { prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } if (up.ExistInArchive() && Archive) { UInt32 indexInArchive; if (ArcItems == 0) indexInArchive = up.ArcIndex; else indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if (up.IsAnti) { return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); } const CDirItem &di = DirItems->Items[up.DirIndex]; RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); if (di.IsDir()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; const CDirItems *DirItems; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (ai.SizeDefined) if (di.Size != ai.Size) pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback) { for (int i = 0; i < updatePairs.Size(); i++) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); // cout << "deleting"; */ if (callback) callback->ShowDeleteFile(pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; up2.NewData = up2.NewProps = false; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; break; } operationChain.Add(up2); } operationChain.ReserveDown(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool IsAnti; int DirIndex; int ArcIndex; int NewNameIndex; bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback { virtual HRESULT ShowDeleteFile(int arcIndex) = 0; }; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; #endif UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "Windows/Error.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsDir, L"Folder" }, { kpidSize, L"Size" }, { kpidPackSize, L"Packed Size" }, { kpidAttrib, L"Attributes" }, { kpidCTime, L"Created" }, { kpidATime, L"Accessed" }, { kpidMTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubDirs, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" }, { kpidBit64, L"64-bit" }, { kpidBigEndian, L"Big-endian" }, { kpidCpu, L"CPU" }, { kpidPhySize, L"Physical Size" }, { kpidHeadersSize, L"Headers Size" }, { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, { kpidFreeSpace, L"Free Space" }, { kpidClusterSize, L"Cluster Size" } }; static const char kEmptyAttribChar = '.'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttribString(DWORD wa, bool isDir, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; wchar_t s[32]; ConvertUInt64ToString(propID, s); return s; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&prop.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidPath) { UString s; RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); prop = s; } else { RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (prop.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: prop = defaultItemName; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidMTime) { PrintTime(prop); } else if (fieldInfo.PropID == kpidAttrib) { if (prop.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = prop.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttribString(attributes, isFolder, s); g_StdOut << s; } else if (prop.vt == VT_BSTR) { if (techMode) g_StdOut << prop.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); } else { UString s = ConvertPropertyToString(prop, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant prop; if (archive->GetProperty(index, propID, &prop) != S_OK) throw "GetPropertyValue error"; if (prop.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(prop); return true; } HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) g_StdOut << "is not supported archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" #ifndef _NO_CRYPTO " -p{Password}: set Password\n" #endif " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) throw kUnsupportedArcTypeMessage; if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, formatIndices, options.ArchiveName)) throw kUnsupportedArcTypeMessage; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int MY_CDECL main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::Open_CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(Open_CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: INTERFACE_IOpenCallbackUI(;) CStdOutStream *OutStream; #ifndef _NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; UString Password; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) { return CheckBreak(); } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { #ifdef _NO_CRYPTO *passwordIsDefined = false; return StringToBstr(L"", password); #else if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif } /* HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) { // MT_LOCK if (StdOutMode) return S_OK; RINOK(Finilize()); m_PercentPrinter.PrintString("Deleting "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), #ifndef _NO_CRYPTO PasswordIsDefined(false), AskPassword(false), #endif StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRenameAll = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/7zip/UI/Console/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DWIN_LONG_PATH \ -DEXTERNAL_LZMA \ -DEXTERNAL_CODECS \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Registry.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Threads.obj \ !include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !include "../../Crc.mak" ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Build.mak ================================================ !IFDEF CPU !IFNDEF NO_BUFFEROVERFLOWU LIBS = $(LIBS) bufferoverflowU.lib !ENDIF !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gr -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope !ELSE CFLAGS = $(CFLAGS) -W3 !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF -OPT:ICF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if (_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while (pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for (int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for (int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "MyWindows.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for (int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { public: BSTR m_str; CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memcpy(res, m_str, byteLen); return res; } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifndef _WIN32 #include <ctype.h> #endif #ifndef _UNICODE #include "StringConvert.h" #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while ((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); // int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if (realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if (newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if (_capacity > 0) { for (int i = 0; i < _length; i++) newBuffer[i] = _chars[i]; delete []_chars; } _chars = newBuffer; _chars[_length] = 0; _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if (minBufLength >= _capacity) SetCapacity(minBufLength); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if (newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if (&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for (int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for (int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } void CBaseRecordVector::ClearAndFree() { Clear(); delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta = 1; if (_capacity >= 64) delta = _capacity / 4; else if (_capacity >= 8) delta = 8; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { // if (newCapacity <= _capacity) if (newCapacity == _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = NULL; if (newSize > 0) { p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); memcpy(p, _items, _itemSize * numRecordsToMove); } delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::ReserveDown() { Reserve(_size); } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void ClearAndFree(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); void ReserveDown(); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector(): CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while (--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector() {}; ~CObjectVector() { Clear(); }; CObjectVector(const CObjectVector &v) { *this = v; } CObjectVector& operator=(const CObjectVector &v) { Clear(); return (*this += v); } CObjectVector& operator+=(const CObjectVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for (int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for (int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if (c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while ((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if (c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if (numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { int numRequiredBytes = s.Length() * 2; BOOL defUsed; int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); #ifndef _WIN32_WCE if (numChars == 0) throw 282229; #endif dest.ReleaseBuffer(numChars); } return dest; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { bool defaultCharWasUsed; return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if (!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if (!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; UInt32 v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { if (end != NULL) *end = s; return result; } result <<= 4; result |= v; s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H extern "C" { #include "../../C/Types.h" } typedef int HRes; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; int numAdds; if (srcPos == srcLen) { *destLen = destPos; return True; } c = (Byte)src[srcPos++]; if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xC0) break; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { Byte c2; if (srcPos == srcLen) break; c2 = (Byte)src[srcPos++]; if (c2 < 0x80 || c2 >= 0xC0) break; value <<= 6; value |= (c2 - 0x80); } while (--numAdds != 0); if (value < 0x10000) { if (dest) dest[destPos] = (wchar_t)value; destPos++; } else { value -= 0x10000; if (value >= 0x100000) break; if (dest) { dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); } destPos += 2; } } *destLen = destPos; return False; } static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { unsigned numAdds; UInt32 value; if (srcPos == srcLen) { *destLen = destPos; return True; } value = src[srcPos++]; if (value < 0x80) { if (dest) dest[destPos] = (char)value; destPos++; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00 || srcPos == srcLen) break; c2 = src[srcPos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; if (dest) dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); destPos++; do { numAdds--; if (dest) dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); destPos++; } while (numAdds != 0); } *destLen = destPos; return False; } bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src.Length()); wchar_t *p = dest.GetBuffer((int)destLen); Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; Utf16_To_Utf8(NULL, &destLen, src, src.Length()); char *p = dest.GetBuffer((int)destLen); Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if (CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if (!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for (int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if (string.IsEmpty()) { if (i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if (errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA fd; _handle = ::FindFirstFile(wildcard, &fd); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW fd; _handle = ::FindFirstFileW(wildcard, &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for (UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for (UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } }}} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); }}} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if (hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) { if (c != 0) *s++ = c; char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(0, st.wYear, s, 4); s = UIntToStringSpec('-', st.wMonth, s, 2); s = UIntToStringSpec('-', st.wDay, s, 2); if (includeTime) { s = UIntToStringSpec(' ', st.wHour, s, 2); s = UIntToStringSpec(':', st.wMinute, s, 2); if (includeSeconds) UIntToStringSpec(':', st.wSecond, s, 2); } return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &prop) { switch (prop.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return prop.bstrVal; case VT_UI1: return ConvertUInt64ToString(prop.bVal); case VT_UI2: return ConvertUInt64ToString(prop.uiVal); case VT_UI4: return ConvertUInt64ToString(prop.ulVal); case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); // case VT_I1: return ConvertInt64ToString(prop.cVal); case VT_I2: return ConvertInt64ToString(prop.iVal); case VT_I4: return ConvertInt64ToString(prop.lVal); case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) { switch (prop.vt) { case VT_UI1: return prop.bVal; case VT_UI2: return prop.uiVal; case VT_UI4: return prop.ulVal; case VT_UI8: return (UInt64)prop.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 operator HANDLE() { return thread.handle; } void Attach(HANDLE handle) { thread.handle = handle; } HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Time.cpp ================================================ // Windows/Time.cpp #include "StdAfx.h" #include "Time.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &fileTime)); } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { dosTime = (fileTime.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) { resSeconds = 0; if (year < 1601 || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; UInt32 numYears = year - 1601; UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += day - 1; resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } void GetCurUtcFileTime(FILETIME &ft) { SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); } }} ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); }} #endif ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/Methods.txt ================================================ 7-Zip method IDs (4.65) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - PPC (Big Endian) 03 - Alpha 01 - Alpha 04 - IA64 01 - IA64 05 - ARM 01 - ARM 06 - M68 05 - M68 (Big Endian) 07 - ARM Thumb 01 - ARMT 08 - SPARC 05 - SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/lzma.txt ================================================ LZMA SDK 4.65 ------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK Contents ----------------- LZMA SDK includes: - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory C++/7zip/Compress/LZMA_Alone and call make to recompile it: make -f makefile.gcc clean all In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, you can use LIB = -lm -static Files --------------------- lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C/ - C files 7zCrc*.* - CRC code Alloc.* - Memory allocation functions Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code LzFind.* - Match finder for LZ (LZMA) encoders LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding LzHash.h - Additional file for LZ match finder LzmaDec.* - LZMA decoding LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). Archive - files related to archiving 7z - 7z ANSI-C Decoder CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + Types.h LzmaUtil/LzmaUtil.c is example application that uses these files. Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); For full code example, look at C/LzmaUtil/LzmaUtil.c code. How To compress data -------------------- Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Check C/LzmaUtil/LzmaUtil.c as example, When to use: file->file decompressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) LZMA Defines ------------ _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: operator new(size_t size) { void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } If you use MSCV that throws exception for "new" operator, you can compile without "NewHandler.cpp". So standard exception will be used. Actually some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.4-cisco/lzma/patches/lzma465-squashfs.patch ================================================ diff -rNu lzma/C/LzmaDec.c lzmanew/C/LzmaDec.c --- lzma/C/LzmaDec.c 2008-11-06 02:31:07.000000000 -0500 +++ lzmanew/C/LzmaDec.c 2010-02-25 15:09:16.000000000 -0500 @@ -2,8 +2,10 @@ 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" - + +#ifndef LINKSYSLZMA #include <string.h> +#endif #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) diff -rNu lzma/C/LzmaEnc.c lzmanew/C/LzmaEnc.c --- lzma/C/LzmaEnc.c 2009-02-02 02:34:23.000000000 -0500 +++ lzmanew/C/LzmaEnc.c 2010-02-25 06:05:58.000000000 -0500 @@ -1,7 +1,8 @@ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ - +#ifndef LINKSYSLZMA #include <string.h> +#endif /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ @@ -44,7 +45,10 @@ void LzmaEncProps_Init(CLzmaEncProps *p) { - p->level = 5; +/* The default dictionary size is 16M, The lzma_compression_level is from 1 to 5 + and dictionary size is (1<< (lzma_compression_level*2+14)). */ + + p->level = 1; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; diff -rNu lzma/C/Types.h lzmanew/C/Types.h --- lzma/C/Types.h 2008-11-22 23:45:56.000000000 -0500 +++ lzmanew/C/Types.h 2010-02-25 06:09:40.000000000 -0500 @@ -4,7 +4,9 @@ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H +#ifndef LINKSYSLZMA #include <stddef.h> +#endif #ifdef _WIN32 #include <windows.h> @@ -40,7 +42,10 @@ #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif +#ifndef Byte typedef unsigned char Byte; +#endif + typedef short Int16; typedef unsigned short UInt16; ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/Makefile ================================================ # Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 CC = gcc LZMADIR = ../lzma/C CFLAGS := -I $(LZMADIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 LZMAOBJS = LzmaEnc.o LzFind.o LzmaDec.o MKOBJS = mksquashfs.o read_fs.o sort.o lzmainterface.o all: mksquashfs unsquashfs $(LZMAOBJS): %.o: $(LZMADIR)/%.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $^ -o $@ mksquashfs: $(MKOBJS) $(LZMAOBJS) $(CC) $(MKOBJS) $(LZMAOBJS) -lz -lpthread -lm -lstdc++ -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs: unsquashfs.o $(LZMAOBJS) $(CC) unsquashfs.o lzmainterface.o $(LZMAOBJS) -lz -lpthread -lm -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h clean: -rm -f *.o mksquashfs unsquashfs install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/lzmainterface.c ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * Squashfs -lzma for Linux * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "LzmaDec.h" #include "LzmaEnc.h" #include "lzmainterface.h" static void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } static void SzFree(void *p, void *address) { p = p; free(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out) { CLzmaEncProps encProps; size_t headerSize = LZMA_PROPS_SIZE; int ret; SizeT outProcess; LzmaEncProps_Init(&encProps); encProps.algo = 1; outProcess = out_size - LZMA_PROPS_SIZE; ret = LzmaEncode(out_data+LZMA_PROPS_SIZE, &outProcess, in_data, in_size, &encProps, out_data, &headerSize, 0, NULL, &g_Alloc, &g_Alloc); *total_out = outProcess + LZMA_PROPS_SIZE; return ret; } int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen) { int res; SizeT inSizePure; ELzmaStatus status; if (srclen < LZMA_PROPS_SIZE) { memcpy(dst, src, srclen); return srclen; } inSizePure = srclen - LZMA_PROPS_SIZE; res = LzmaDecode(dst, dstlen, src + LZMA_PROPS_SIZE, &inSizePure, src, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); srclen = inSizePure ; if ((res == SZ_OK) || ((res == SZ_ERROR_INPUT_EOF) && (srclen == inSizePure))) res = 0; if (res != SZ_OK) printf("In LzmaUncompress: return error (%d)\n", res); return res; } ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/lzmainterface.h ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * squashfs with lzma compression * * Copyright (C) 2008, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id: sqlzma.h,v 1.3 2009/03/10 08:42:14 Exp $ */ #ifndef __lzmainterface_h__ #define __lzmainterface_h__ #ifndef __KERNEL__ #include <stdlib.h> #include <string.h> #endif /* detect the compression method automatically by the first byte of compressed data.*/ #define is_lzma(p) (p == 0x5d) int LzmaUncompress(char *dst, unsigned long * dstlen, char *src, int srclen); int LzmaCompress(char *in_data, int in_size, char *out_data, int out_size, unsigned long *total_out); #endif ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/mksquashfs.c ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #include "LzmaEnc.h" #include "Alloc.h" #include "lzmainterface.h" #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif //#include <linux/squashfs_fs.h> #include "squashfs_fs.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; int gLzmaEnable=1; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; int fragment_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } #define GET_FREELIST 1 struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ #ifdef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else #endif if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else #ifndef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } #endif /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found getting a * new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(!gLzmaEnable ){ if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } }else {/*Start:Added @2010-02-25 to suporrt lzma*/ res = LzmaCompress(s, size, d, block_size, &c_byte); if (res) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } }/*End:Added @2010-02-25 to suporrt lzma*/ return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(read(fd, buff, bytes) == -1) BAD_ERROR("Read on destination failed because %s\n", strerror(errno)); pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed because %s\n", strerror(errno)); if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL); #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { squashfs_fragment_entry *disk_fragment; int size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char *data; char cbuffer[block_size]; if(compressed_buffer) data = compressed_buffer->data; else { data = cbuffer; read_bytes(fd, start_block, size, data); } if(!gLzmaEnable){ if((res = uncompress((unsigned char *) buffer->data, &bytes, (const unsigned char *) data, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } }else{/*Start:Added @2010-02-25 to suporrt lzma*/ if((res = LzmaUncompress((unsigned char *) buffer->data, &bytes, (const unsigned char *) data, size)) != SZ_OK) BAD_ERROR("LzmaUncompress: error (%d)\n", res); } /*End:Added @2010-02-25 to suporrt lzma*/ } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else read_bytes(fd, start_block, size, buffer->data); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, entry->buffer); pthread_mutex_lock(&fragment_mutex); TRACE("fragment_locked writing fragment %d, compressed size %d\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } int add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) return FALSE; entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } char buffer2[SQUASHFS_FILE_MAX_SIZE]; struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(b->read_buffer) target_data = b->read_buffer->data; else if(b->size) { target_buffer = cache_lookup(writer_buffer, b->start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(b->start, b->size); } else continue; dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else { read_bytes(fd, dup_start, b->size, buffer2); dup_data = buffer2; } res = memcmp(target_data, dup_data, b->size); if(target_buffer) cache_block_put(target_buffer); if(dup_buffer) cache_block_put(dup_buffer); if(res != 0) break; dup_start += b->size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int index = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; byte = file_buffer->size = read(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read(file, &buffer, 1) == 1) goto restat; } file_buffer->fragment = (file_buffer->block == frag_block); if(file_buffer->fragment) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = cache_get(writer_buffer, 0, 0); if(sparse_files && all_zero(file_buffer)) write_buffer->c_byte = 0; else write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, write_buffer); TRACE("Writing fragment %lld, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(current > max) { printf("%lld %lld\n", current, max); return; } if(columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; int status; *duplicate_file = FALSE; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else cache_block_put(read_buffer); inc_progress_bar(); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; inc_progress_bar(); } else read_buffer = NULL; unlock_fragments(); fragment = get_and_fill_fragment(read_buffer); cache_block_put(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block, thresh; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct buffer_list *buffer_list; int status, num_locked_fragments; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; buffer_list[block].start = bytes; buffer_list[block].size = read_buffer->size; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; } else { buffer_list[block].read_buffer = NULL; cache_block_put(read_buffer); } inc_progress_bar(); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block].read_buffer) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } } unlock_fragments(); cache_block_put(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(!no_fragments && (read_size < block_size)) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, new, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing exclude which subsumes the exclude currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific excludes, delete as they're subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with -wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories in the * filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n"); read_bytes(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) BAD_ERROR("Failed to create recovery file, because %s. Aborting\n", strerror(errno)); if(write(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int readbytes; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n"); if((readbytes = read(recoverfd, metadata, bytes)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(readbytes != bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_bytes(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 3.4 (2008/08/26)\n");\ printf("copyright (C) 2008 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; int s_minor; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else if(strcmp(argv[i], "-nolzma") == 0) { gLzmaEnable= 0; }else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors <number>\tUse <number> processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fagment queue to <size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); fragment_buffer_size = fragmentb_mbytes << (20 - block_log); if(block_size <= 65536 && sparse_files == FALSE) s_minor = 0; else s_minor = SQUASHFS_MINOR; for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } be = orig_be; block_log = slog(block_size = sBlk.block_size); s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = (char *)malloc(scache_bytes); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; // sBlk.s_magic = SQUASHFS_MAGIC; if (gLzmaEnable) sBlk.s_magic = SQUASHFS_MAGIC_LZMA; else sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_uids = uid_count; if(sBlk.no_uids) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; sBlk.no_guids = guid_count; if(sBlk.no_guids) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { int uid = uids[i]; struct passwd *user = getpwuid(uid); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } return 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/read_fs.c ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include "LzmaDec.h" #include "lzmainterface.h" #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif //#include <linux/squashfs_fs.h> #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern int gLzmaEnable; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if(!gLzmaEnable){ if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } }else{ /*Start:Added @2010-02-25 to suporrt lzma*/ if((res = LzmaUncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); } /*End:Added @2010-02-25 to suporrt lzma*/ if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { /*Start:Changed @2010-02-25 to suporrt lzma*/ squashfs_super_block sblk; read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { case SQUASHFS_MAGIC_LZMA: if (!gLzmaEnable) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /*End:Changed @2010-02-25 to suporrt lzma*/ /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/sort.c ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> //#include <linux/squashfs_fs.h> #include "squashfs_fs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/squashfs_fs.h ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.4-cisco/squashfs-tools/unsquashfs.c ================================================ /* Modifications were made by Cisco Systems, Inc. on or before Thu Feb 16 11:28:44 PST 2012 */ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "lzmainterface.h" #include "LzmaDec.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE; char **created_inode; int root_process; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for reading * off disk and decompression. The cache grows until max_blocks is reached, * once this occurs existing discarded blocks on the free list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* not in the cache */ /* first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) goto failed; entry->data = malloc(cache->buffer_size); if(entry->data == NULL) { free(entry); goto failed; } entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* queue to read thread to read and ultimately (via the decompress * threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_block_ready(struct cache_entry *entry, int error) { /* mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* if the wait_pending flag is set, one or more threads may be waiting on * this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* wait for this cache entry to become ready, when reading and (if necessary) * decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains accessible * via the hash table it can be found getting a new lease of life before it * is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* if the wait_free flag is set, one or more threads may be waiting on * this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if (!is_lzma(buffer[0])) { res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } }else{ /*Start:Added @2010-02-25 to suporrt lzma*/ if((res = LzmaUncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); /*End:Added @2010-02-25 to suporrt lzma*/ } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if (!is_lzma(data[0])) { res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } }else{ /*Start:Added @2010-02-25 to suporrt lzma*/ if((res = LzmaUncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); /*End:Added @2010-02-25 to suporrt lzma*/ } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } void read_fragment(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } int lseek_broken = FALSE; char *zero_data; int write_block(int file_fd, char *buffer, int size, int hole) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; }; int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); if((file = malloc(sizeof(struct squashfs_file))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are queued * separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry *)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry *)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(((*i) = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { /*Start:Changed @2010-02-25 to suporrt lzma*/ squashfs_super_block sblk; read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk.s_magic) { case SQUASHFS_MAGIC: case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /*End:Changed @2010-02-25 to suporrt lzma*/ /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_bytes(entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* queue successfully read block to the deflate thread(s) * for further processing */ queue_put(to_deflate, entry); else /* block has either been successfully read and is uncompressed, * or an error has occurred, clear pending flag, set * error appropriately, and wake up any threads waiting on * this buffer */ cache_block_ready(entry, !res); } } /* writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; int hole = 0; int failed = FALSE; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed == FALSE && write_block(file_fd, block->buffer->data + block->offset, block->size, hole) == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* corner case for hole extending to end of file */ if(lseek(file_fd, hole, SEEK_CUR) == -1) { /* for broken lseeks which cannot seek beyond end of * file, write_block will do the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole) == FALSE) { ERROR("writer: failed to write sparse data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; while(1) { struct cache_entry *entry = queue_get(to_deflate); int res; unsigned long bytes = block_size; if(!is_lzma(((unsigned char *)entry->data)[0])){ res = uncompress((unsigned char *) tmp, &bytes, (const unsigned char *) entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); } else memcpy(entry->data, tmp, bytes); }else{ /*Start:Added @2010-02-25 to suporrt lzma*/ if((res = LzmaUncompress((unsigned char *) tmp, &bytes, (const unsigned char *) entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size))) != SZ_OK) ERROR("LzmaUncompress: error (%d)\n", res); else memcpy(entry->data, tmp, bytes); /*End:Added @2010-02-25 to suporrt lzma*/ } /* block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res != Z_OK); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { ERROR("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(current > max) { printf("%lld %lld\n", current, max); return; } if(columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 3.4 (2008/08/26)\n");\ printf("copyright (C) 2008 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; struct winsize winsize; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(lsonly || info) progress = FALSE; if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress bar\n"); ERROR("\t-p[rocessors] <number>\tuse <number> processors. By default will use\n\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; block_log = sBlk.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate data\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/Makefile ================================================ # Copyright (C) 2006-2008 Junjiro Okajima # Copyright (C) 2006-2008 Tomas Matejicek, slax.org # # LICENSE follows the described ones in lzma and squashfs. # $Id: Makefile,v 1.30 2008-03-12 16:24:54 jro Exp $ # paths Sqlzma = ${CURDIR} LzmaVer = lzma465 Lzma = ${Sqlzma}/${LzmaVer} SqVer = squashfs3.4 Squashfs = ${Sqlzma}/${SqVer} KVer = linux-2.6.27.4 SqFs = ${Squashfs}/kernel-patches/${KVer}/fs/squashfs #KDir = /lib/modules/$(shell uname -r)/build #KDir = ${SqFs}/../.. ifeq (${LzmaVer}, lzma443) LzmaC = ${Lzma}/C/7zip/Compress/LZMA_C LzmaAlone = ${Lzma}/C/7zip/Compress/LZMA_Alone endif ifeq (${LzmaVer}, lzma465) LzmaC = ${Lzma}/C LzmaAlone = ${Lzma}/CPP/7zip/Compress/LZMA_Alone else LzmaC = ${Lzma}/C/Compress/Lzma LzmaAlone = ${Lzma}/CPP/7zip/Compress/LZMA_Alone endif SqTools = ${Squashfs}/squashfs-tools # enable it if you want to add -g option when compiling #UseDebugFlags = 1 #MyDebugFlags = -DSQUASHFS_TRACE # disable it if you don't want to compile squashfs kernel module here # BuildSquashfs = 1 export all: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ cp ${SqTools}/mksquashfs ./mksquashfs-lzma cp ${SqTools}/unsquashfs ./unsquashfs clean: ${MAKE} -C ${LzmaC} -f sqlzma.mk $@ ${MAKE} -C ${LzmaAlone} -f sqlzma.mk $@ ${MAKE} -C ${SqTools} $@ ${RM} *~ rm -f ./mksquashfs-lzma ./unsquashfs ######################################## -include priv.mk ifdef BuildSquashfs CONFIG_SQUASHFS = m CONFIG_SQUASHFS_EMBEDDED = CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE = 3 EXTRA_CFLAGS = -I${Sqlzma} -I${SqFs}/../../include -Wall -Werror EXTRA_CFLAGS += -DCONFIG_SQUASHFS_MODULE -UCONFIG_SQUASHFS EXTRA_CFLAGS += -UCONFIG_SQUASHFS_EMBEDDED -DCONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # if you enabled CONFIG_PREEMPT, but want CPU to try concentrating # the uncompression, then define UnsquashNoPreempt. # if you don't define UnsquashNoPreempt, the behaviour follows # the CONFIG_PREEMPT. EXTRA_CFLAGS += -DUnsquashNoPreempt export # the environment variables are not inherited since 2.6.23 MAKE += SQLZMA_EXTRA_CFLAGS="$(shell echo ${EXTRA_CFLAGS} | sed -e 's/\"/\\\\\\"/g')" all: all_sq FORCE: all_sq: ${MAKE} -C ${KDir} M=${SqFs} modules clean: clean_sq clean_sq: ${MAKE} -C ${KDir} M=${SqFs} clean endif ######################################## load: for i in ${LzmaC}/kmod/unlzma.ko ${LzmaC}/kmod/sqlzma.ko \ ${SqFs}/squashfs.ko; \ do sudo insmod $$i; done unload: -sudo rmmod squashfs sqlzma unlzma ================================================ FILE: src/others/squashfs-3.4-nb4/README.txt ================================================ Adaptation squashfs3.4 pour utilisation lzma4.65 Adaptation nécessaire pour les firmware 2.x.x de la neufbox4 Adaptation réalisée d'après la recette de SGDA (http://www.neufbox4.org/forum/viewtopic.php?pid=12691#p12691) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/7zC.txt ================================================ 7z ANSI-C Decoder 4.62 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CFileItem *f = db.db.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zBuf.c ================================================ /* 7zBuf.c -- Byte Buffer 2008-03-28 Igor Pavlov Public domain */ #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)alloc->Alloc(alloc, size); if (p->data != 0) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zBuf.h ================================================ /* 7zBuf.h -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zBuf2.c ================================================ /* 7zBuf2.c -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)alloc->Alloc(alloc, newSize); if (data == 0) return 0; p->size = newSize; memcpy(data, p->data, p->pos); alloc->Free(alloc, p->data); p->data = data; } memcpy(p->data + p->pos, buf, size); p->pos += size; return 1; } void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zCrc.c ================================================ /* 7zCrc.c -- CRC32 calculation 2008-08-05 Igor Pavlov Public domain */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zCrc.h ================================================ /* 7zCrc.h -- CRC32 calculation 2008-03-13 Igor Pavlov Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zFile.c ================================================ /* 7zFile.c -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include <errno.h> #endif #ifdef USE_WINDOWS_FILE /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #define kChunkSizeMax (1 << 22) #endif void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #else p->file = NULL; #endif } static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #else p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #else if (p->file != NULL) { int res = fclose(p->file); if (res != 0) return res; p->file = NULL; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fread(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fwrite(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE LARGE_INTEGER value; DWORD moveMethod; value.LowPart = (DWORD)*pos; value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ switch (origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)value.HighPart << 32) | value.LowPart; return 0; #else int moveMethod; int res; switch (origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return 1; } res = fseek(p->file, (long)*pos, moveMethod); *pos = ftell(p->file); return res; #endif } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #else long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) { CFileSeqInStream *p = (CFileSeqInStream *)pp; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->s.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(void *pp, void *buf, size_t *size) { CFileInStream *p = (CFileInStream *)pp; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) { CFileInStream *p = (CFileInStream *)pp; return File_Seek(&p->file, pos, origin); } void FileInStream_CreateVTable(CFileInStream *p) { p->s.Read = FileInStream_Read; p->s.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(void *pp, const void *data, size_t size) { CFileOutStream *p = (CFileOutStream *)pp; File_Write(&p->file, data, &size); return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->s.Write = FileOutStream_Write; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zFile.h ================================================ /* 7zFile.h -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE #endif #ifdef USE_WINDOWS_FILE #include <windows.h> #else #include <stdio.h> #endif #include "Types.h" /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #else FILE *file; #endif } CSzFile; void File_Construct(CSzFile *p); WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream s; CSzFile file; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream s; CSzFile file; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream s; CSzFile file; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zStream.c ================================================ /* 7zStream.c -- 7z Stream functions 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "Types.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) { Int64 t = offset; return stream->Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); memcpy(buf, lookBuf, *size); return stream->Skip(stream, *size); } SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; size2 = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, &size2); p->size = size2; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; if (*size > LookToRead_BUF_SIZE) *size = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Skip(void *pp, size_t offset) { CLookToRead *p = (CLookToRead *)pp; p->pos += offset; return SZ_OK; } static SRes LookToRead_Read(void *pp, void *buf, size_t *size) { CLookToRead *p = (CLookToRead *)pp; size_t rem = p->size - p->pos; if (rem == 0) return p->realStream->Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) { CLookToRead *p = (CLookToRead *)pp; p->pos = p->size = 0; return p->realStream->Seek(p->realStream, pos, origin); } void LookToRead_CreateVTable(CLookToRead *p, int lookahead) { p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact; p->s.Skip = LookToRead_Skip; p->s.Read = LookToRead_Read; p->s.Seek = LookToRead_Seek; } void LookToRead_Init(CLookToRead *p) { p->pos = p->size = 0; } static SRes SecToLook_Read(void *pp, void *buf, size_t *size) { CSecToLook *p = (CSecToLook *)pp; return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->s.Read = SecToLook_Read; } static SRes SecToRead_Read(void *pp, void *buf, size_t *size) { CSecToRead *p = (CSecToRead *)pp; return p->realStream->Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->s.Read = SecToRead_Read; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/7zVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Alloc.c ================================================ /* Alloc.c -- Memory allocation functions 2008-09-24 Igor Pavlov Public domain */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG { void *p = malloc(size); fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); return p; } #else return malloc(size); #endif } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" #include "7zDecode.h" #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_Construct(&state); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) { if (state.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(inStream->Skip((void *)inStream, curSize)); } return SZ_OK; } #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } UInt64 GetSum(const UInt64 *values, UInt32 index) { UInt64 sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CSzCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; UInt64 unpackSize = folder->UnpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); if (temp == 0 && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = GetSum(packSizes, si); inSize = packSizes[si]; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } else { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZ_ERROR_UNSUPPORTED; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); UInt64 s3Size = packSizes[1]; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZ_ERROR_MEM; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) res = Bcj2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], tempBuf[2], tempSizes[2], outBuffer, outSize); RINOK(res) } else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SRes res = SzDecode2(packSizes, folder, inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) IAlloc_Free(allocMain, tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "7zDecode.h" #include "7zExtract.h" SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzAr_Extract( const CSzArEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c -- 7z Input functions 2008-12-31 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "../../CpuArch.h" #include "7zDecode.h" #include "7zIn.h" #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->FolderStartPackStreamIndex = 0; p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } /* UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CSzFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) { UInt32 startPos = 0; UInt64 startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); for (i = 0; i < p->db.NumFolders; i++) { p->FolderStartPackStreamIndex[i] = startPos; startPos += p->db.Folders[i].NumPackStreams; } MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); for (i = 0; i < p->db.NumPackStreams; i++) { p->PackStreamStartPositions[i] = startPosSize; startPosSize += p->db.PackSizes[i]; } MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); for (i = 0; i < p->db.NumFiles; i++) { CSzFileItem *file = p->db.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { p->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderStartFileIndex[folderIndex] = i; if (p->db.Folders[folderIndex].NumUnpackStreams != 0) break; folderIndex++; } } p->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) { return p->dataPos + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) { UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; CSzFolder *folder = p->db.Folders + folderIndex; UInt64 size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; if (t < size) /* check it */ return SZ_ERROR_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SRes SzReadTime(const CObjectVector<CBuf> &dataVector, CObjectVector<CSzFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for (int i = 0; i < files.Size(); i++) { CSzFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; } } return SZ_OK; } */ static int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; static SRes SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZ_ERROR_ARCHIVE; sd->Size--; *b = *sd->Data++; return SZ_OK; } static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } static SRes SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } static SRes SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static SRes SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } static SRes SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZ_ERROR_ARCHIVE; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } static SRes SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SzSkeepData(sd)); } } static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, alloc); MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } static SRes SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, ISzAlloc *alloc) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); MY_ALLOC(UInt32, *digests, numItems, alloc); for (i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } static SRes SzReadPackInfo( CSzData *sd, UInt64 *dataOffset, UInt32 *numPackStreams, UInt64 **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, ISzAlloc *alloc) { UInt32 i; RINOK(SzReadNumber(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { RINOK(SzReadNumber(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } static SRes SzReadStreamsInfo( CSzData *sd, UInt64 *dataOffset, CSzAr *p, UInt32 *numUnpackStreams, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ ISzAlloc *alloc, ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZ_ERROR_UNSUPPORTED; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); break; } case k7zIdUnpackInfo: { RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZ_ERROR_UNSUPPORTED; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) { UInt32 i; for (i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CSzFileItem *file = files + i; while (pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZ_ERROR_ARCHIVE; if (pos + 2 > sd->Size) return SZ_ERROR_ARCHIVE; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZ_ERROR_ARCHIVE; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, alloc); len = 0; while (2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += numAdds; } } return SZ_OK; } static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->FileCRCDefined = 0; } } } return SzArEx_Fill(p, allocMain); } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; } static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzDecode(p->PackSizes, folder, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; } static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h -- 7z Input functions 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 *FolderStartPackStreamIndex; UInt64 *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; } CSzArEx; void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #include "7zItem.h" void SzCoderInfo_Init(CSzCoderInfo *p) { Buf_Init(&p->Props); } void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) { Buf_Free(&p->Props, alloc); SzCoderInfo_Init(p); } void SzFolder_Init(CSzFolder *p) { p->Coders = 0; p->BindPairs = 0; p->PackStreams = 0; p->UnpackSizes = 0; p->NumCoders = 0; p->NumBindPairs = 0; p->NumPackStreams = 0; p->UnpackCRCDefined = 0; p->UnpackCRC = 0; p->NumUnpackStreams = 0; } void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { UInt32 i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); } UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) { UInt32 result = 0; UInt32 i; for (i = 0; i < p->NumCoders; i++) result += p->Coders[i].NumOutStreams; return result; } int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } UInt64 SzFolder_GetUnpackSize(CSzFolder *p) { int i = (int)SzFolder_GetNumOutStreams(p); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolder_FindBindPairForOutStream(p, i) < 0) return p->UnpackSizes[i]; /* throw 1; */ return 0; } void SzFile_Init(CSzFileItem *p) { p->HasStream = 1; p->IsDir = 0; p->IsAnti = 0; p->FileCRCDefined = 0; p->MTimeDefined = 0; p->Name = 0; } static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Name); SzFile_Init(p); } void SzAr_Init(CSzAr *p) { p->PackSizes = 0; p->PackCRCsDefined = 0; p->PackCRCs = 0; p->Folders = 0; p->Files = 0; p->NumPackStreams = 0; p->NumFolders = 0; p->NumFiles = 0; } void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { UInt32 i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); if (p->Files) for (i = 0; i < p->NumFiles; i++) SzFile_Free(&p->Files[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" typedef struct { UInt32 NumInStreams; UInt32 NumOutStreams; UInt64 MethodID; CBuf Props; } CSzCoderInfo; void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); typedef struct { UInt32 InIndex; UInt32 OutIndex; } CBindPair; typedef struct { CSzCoderInfo *Coders; CBindPair *BindPairs; UInt32 *PackStreams; UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; int UnpackCRCDefined; UInt32 UnpackCRC; UInt32 NumUnpackStreams; } CSzFolder; void SzFolder_Init(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { CNtfsFileTime MTime; UInt64 Size; char *Name; UInt32 FileCRC; Byte HasStream; Byte IsDir; Byte IsAnti; Byte FileCRCDefined; Byte MTimeDefined; } CSzFileItem; void SzFile_Init(CSzFileItem *p); typedef struct { UInt64 *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; CSzFolder *Folders; CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; UInt32 NumFiles; } CSzAr; void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c - Test application for 7z Decoder 2008-11-23 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "7zAlloc.h" #include "7zExtract.h" #include "7zIn.h" static void ConvertNumberToString(UInt64 value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } if (InFile_Open(&archiveStream.file, args[2])) { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *f = db.db.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) ConvertFileTimeToString(&f->MTime, t); else strcpy(t, " "); printf("%s %10s %s\n", t, s, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (f->IsDir) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) { printf("\n"); continue; } res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { CSzFile outFile; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } if (OutFile_Open(&outFile, fileName)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/makefile ================================================ MY_STATIC_LINK=1 PROG = 7zDec.exe C_OBJS = \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ $O\7zStream.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c 7zBuf2.o: ../../7zBuf2.c $(CXX) $(CFLAGS) ../../7zBuf2.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c Bcj2.o: ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c 7zFile.o: ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c 7zStream.o: ../../7zStream.c $(CXX) $(CFLAGS) ../../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Bcj2.c ================================================ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bcj2.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *buffer, *bufferLim; UInt32 range, code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; buffer = buf3; bufferLim = buffer + size3; RC_INIT2 if (outSize == 0) return SZ_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; UInt32 ttt; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IF_BIT_0(prob) { UPDATE_0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UPDATE_1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return SZ_ERROR_DATA; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return SZ_ERROR_DATA; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Bcj2.h ================================================ /* Bcj2.h -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). Returns: SZ_OK SZ_ERROR_DATA - Data error */ int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Bra.c ================================================ /* Bra.c -- Converters for RISC code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 8; for (i = 0; i <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 4; for (i = 0; i <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) { UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Bra.h ================================================ /* Bra.h -- Branch converters for executables 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. Type Endian Alignment LookAhead x86 little 1 4 ARMT little 2 2 ARM little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 size must be >= Alignment + LookAhead, if it's not last block. If (size < Alignment + LookAhead), converter returns 0. Example: UInt32 ip = 0; for () { ; size must be >= Alignment + LookAhead, if it's not last block SizeT processed = Convert(data, size, ip, 1); data += processed; size -= processed; ip += processed; } */ #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Bra86.c ================================================ /* Bra86.c -- Converter for x86 code (BCJ) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *state & 0x7; if (size < 5) return 0; ip += 5; prevPosT = (SizeT)0 - 1; for (;;) { Byte *p = data + bufferPos; Byte *limit = data + size - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - data); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (ip + (UInt32)bufferPos) + src; else dest = src - (ip + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/BraIA64.c ================================================ /* BraIA64.c -- Converter for IA-64 code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" static const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 16) return 0; size -= 16; for (i = 0; i <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)data[i + j + bytePos] << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/CpuArch.h ================================================ /* CpuArch.h 2008-08-05 Igor Pavlov Public domain */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #ifdef LITTLE_ENDIAN_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #endif #if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzFindMt.c ================================================ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include "LzHash.h" #include "LzFindMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads2(name, v, action) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ { action; for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #define NO_INLINE MY_FAST_CALL Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->crc = mf->crc; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzFindMt.h ================================================ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFINDMT_H #define __LZFINDMT_H #include "Threads.h" #include "LzFind.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #include <string.h> #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ #include <string.h> /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include <stdio.h> #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifdef COMPRESS_MF_MT ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/LzmaLib.def ================================================ EXPORTS LzmaCompress LzmaUncompress ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/LzmaLib.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # End Group # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\IStream.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\LzmaLib.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/LzmaLib.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/LzmaLibExports.c ================================================ /* LzmaLibExports.c -- LZMA library DLL Entry point 2008-10-04 : Igor Pavlov : Public domain */ #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance = hInstance; dwReason = dwReason; lpReserved = lpReserved; return TRUE; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/makefile ================================================ MY_STATIC_LINK=1 SLIB = sLZMA.lib PROG = LZMA.dll SLIBPATH = $O\$(SLIB) DEF_FILE = LzmaLib.def CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIBS = $(LIBS) oleaut32.lib LIB_OBJS = \ $O\LzmaLibExports.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzmaLib.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../CPP/Build.mak" $(SLIBPATH): $O $(OBJS) lib -out:$(SLIBPATH) $(OBJS) $(LIBS) $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib/resource.rc ================================================ #include "../../CPP/7zip/MyVersionInfo.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib.c ================================================ /* LzmaLib.c -- LZMA library wrapper 2008-08-05 Igor Pavlov Public domain */ #include "LzmaEnc.h" #include "LzmaDec.h" #include "Alloc.h" #include "LzmaLib.h" static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaLib.h ================================================ /* LzmaLib.h -- LZMA library interface 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMALIB_H #define __LZMALIB_H #include "Types.h" #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 16 KB 0 32 1: 64 KB 0 32 2: 256 KB 0 32 3: 1 MB 0 32 4: 4 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7+: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/Lzma86Dec.c ================================================ /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2008-04-07 Igor Pavlov Public domain */ #include "Lzma86Dec.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaDec.h" #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(dest, *destLen, 0, &x86State, 0); } return SZ_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/Lzma86Dec.h ================================================ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86DEC_H #define __LZMA86DEC_H #include "../Types.h" /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/Lzma86Enc.c ================================================ /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #include <string.h> #include "Lzma86Enc.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaEnc.h" #define SZE_OUT_OVERFLOW SZE_DATA_ERROR static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; Bool useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, srcLen, 0, &x86State, 1); } } { size_t minSize = 0; Bool bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/Lzma86Enc.h ================================================ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86ENC_H #define __LZMA86ENC_H #include "../Types.h" /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, = 1 - x86 filter 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/LzmaUtil.c ================================================ /* LzmaUtil.c -- Test application for LZMA compression 2008-11-23 : Igor Pavlov : Public domain */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../Alloc.h" #include "../7zFile.h" #include "../7zVersion.h" #include "../LzmaDec.h" #include "../LzmaEnc.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; const char *kDataErrorMessage = "Data error"; static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; void PrintHelp(char *buffer) { strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" "\nUsage: lzma <e|d> inputFile outputFile\n" " e: encode file\n" " d: decode file\n"); } int PrintError(char *buffer, const char *message) { strcat(buffer, "\nError: "); strcat(buffer, message); strcat(buffer, "\n"); return 1; } int PrintErrorNumber(char *buffer, SRes val) { sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); return 1; } int PrintUserError(char *buffer) { return PrintError(buffer, "Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) { int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)); inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || thereIsSize && unpackSize == 0) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ RINOK(SeqInStream_Read(inStream, header, sizeof(header))); unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_Construct(&state); RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; rs = rs; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int main2(int numArgs, const char *args[], char *rs) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; Bool useOutFile = False; FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); if (numArgs == 1) { PrintHelp(rs); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(rs); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(rs); { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError(rs, "Incorrect UInt32 or UInt64"); } if (InFile_Open(&inStream.file, args[2]) != 0) return PrintError(rs, "Can not open input file"); if (numArgs > 3) { useOutFile = True; if (OutFile_Open(&outStream.file, args[3]) != 0) return PrintError(rs, "Can not open output file"); } else if (encodeMode) PrintUserError(rs); if (encodeMode) { UInt64 fileSize; File_GetLength(&inStream.file, &fileSize); res = Encode(&outStream.s, &inStream.s, fileSize, rs); } else { res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(rs, kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(rs, kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError(rs, kCantWriteMessage); else if (res == SZ_ERROR_READ) return PrintError(rs, kCantReadMessage); return PrintErrorNumber(rs, res); } return 0; } int MY_CDECL main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/LzmaUtil.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\7zFile.c # End Source File # Begin Source File SOURCE=..\7zFile.h # End Source File # Begin Source File SOURCE=..\7zStream.c # End Source File # Begin Source File SOURCE=..\7zVersion.h # End Source File # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\CpuArch.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/LzmaUtil.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/makefile ================================================ MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/LzmaUtil/makefile.gcc ================================================ PROG = lzma CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = \ LzmaUtil.o \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ 7zFile.o \ 7zStream.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaUtil.o: LzmaUtil.c $(CXX) $(CFLAGS) LzmaUtil.c Alloc.o: ../Alloc.c $(CXX) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CXX) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CXX) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CXX) $(CFLAGS) ../LzmaEnc.c 7zFile.o: ../7zFile.c $(CXX) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CXX) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Threads.c ================================================ /* Threads.c -- multithreading library 2008-08-05 Igor Pavlov Public domain */ #include "Threads.h" #include <process.h> static WRes GetError() { DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return 0; } WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(thread->handle); } WRes WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } WRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } WRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return HandleToWRes(p->handle); } WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return HandleToWRes(p->handle); } WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Threads.h ================================================ /* Threads.h -- multithreading library 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); WRes Thread_Wait(CThread *thread); WRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); WRes Event_Set(CEvent *event); WRes Event_Reset(CEvent *event); WRes Event_Wait(CEvent *event); WRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include <stddef.h> #ifdef _WIN32 #include <windows.h> #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif #include makefile.gcc CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 -D _SZ_NO_INT_64 ifdef KDir include kmod.mk endif ifdef UseDebugFlags DebugFlags = -O0 -g -UNDEBUG endif CFLAGS += -DNDEBUG ${DebugFlags} Tgt = libunlzma.a libunlzma_r.a all: ${Tgt} %_r.c: %.c ln $< $@ # -pthread %_r.o: CFLAGS += -D_REENTRANT -include pthread.h uncomp.o uncomp_r.o: CFLAGS += -I${Sqlzma} uncomp.o: uncomp.c ${Sqlzma}/sqlzma.h libunlzma.a: uncomp.o LzmaDec.o Alloc.o ${AR} cr $@ $^ libunlzma_r.a: uncomp_r.o LzmaDec_r.o Alloc_r.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) ${Tgt} uncomp.o uncomp_r.o LzmaDec_r.o LzmaDec.o \ Alloc.o Alloc_r.o *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/C/uncomp.c ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $ */ /* extract some parts from lzma443/C/7zip/Compress/LZMA_C/LzmaTest.c */ #ifndef __KERNEL__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h> #include <pthread.h> #define unlikely(x) __builtin_expect(!!(x), 0) #define BUG_ON(x) assert(!(x)) /* sqlzma buffers are always larger than a page. true? */ #define kmalloc(sz,gfp) malloc(sz) #define kfree(p) free(p) #define zlib_inflate(s, f) inflate(s, f) #define zlib_inflateInit(s) inflateInit(s) #define zlib_inflateReset(s) inflateReset(s) #define zlib_inflateEnd(s) inflateEnd(s) #else #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/vmalloc.h> #ifndef WARN_ON_ONCE #define WARN_ON_ONCE(b) WARN_ON(b) #endif #endif /* __KERNEL__ */ #include "sqlzma.h" #include "LzmaDec.h" #include "Alloc.h" #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; static int LzmaUncompress(struct sqlzma_un *un) { int err, i; SizeT outSize, srclen; /* it's about 24-80 bytes structure, if int is 32-bit */ CLzmaDec state; CLzmaProps props; unsigned char *dst, *src, a[8]; struct sized_buf *sbuf; ELzmaStatus status; /* Decode LZMA properties and allocate memory */ err = -EINVAL; src = (void *)un->un_cmbuf; src += LZMA_PROPS_SIZE; i = LzmaProps_GetNumProbs(&props); if (unlikely(i <= 0)) i = 1; i *= sizeof(CLzmaProb); sbuf = un->un_a + SQUN_PROB; if (unlikely(sbuf->sz < i)) { if (sbuf->buf && sbuf->buf != un->un_prob) kfree(sbuf->buf); #ifdef __KERNEL__ printk("%s:%d: %d --> %d\n", __func__, __LINE__, sbuf->sz, i); #else printf("%d --> %d\n", sbuf->sz, i); #endif err = -ENOMEM; sbuf->sz = 0; sbuf->buf = kmalloc(i, GFP_ATOMIC); if (unlikely(!sbuf->buf)) goto out; sbuf->sz = i; } state.probs = (void *)sbuf->buf; /* Read uncompressed size */ memcpy(a, src, sizeof(a)); src += sizeof(a); outSize = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24); err = -EINVAL; dst = un->un_resbuf; if (unlikely(!dst || outSize > un->un_reslen)) goto out; un->un_reslen = outSize; srclen = un->un_cmlen - (src - un->un_cmbuf); /* Decompress */ /* SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) */ err = LzmaDecode(dst, &outSize, src, &srclen, (void *)un->un_cmbuf, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc); if (unlikely(err!=SZ_OK)) err = -EINVAL; out: #ifndef __KERNEL__ if (err) fprintf(stderr, "err %d\n", err); #endif return err; } int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst) { int err, by_lzma = 1; if (un->un_lzma && is_lzma(*src->buf)) { un->un_cmbuf = src->buf; un->un_cmlen = src->sz; un->un_resbuf = dst->buf; un->un_reslen = dst->sz; /* this library is thread-safe */ err = LzmaUncompress(un); goto out; } by_lzma = 0; err = zlib_inflateReset(&un->un_stream); if (unlikely(err != Z_OK)) goto out; un->un_stream.next_in = src->buf; un->un_stream.avail_in = src->sz; un->un_stream.next_out = dst->buf; un->un_stream.avail_out = dst->sz; err = zlib_inflate(&un->un_stream, Z_FINISH); if (err == Z_STREAM_END) err = 0; out: if (unlikely(err)) { #ifdef __KERNEL__ WARN_ON_ONCE(1); #else char a[64] = "ZLIB "; if (by_lzma) { strcpy(a, "LZMA "); #ifdef _REENTRANT strerror_r(err, a + 5, sizeof(a) - 5); #else strncat(a, strerror(err), sizeof(a) - 5); #endif } else strncat(a, zError(err), sizeof(a) - 5); fprintf(stderr, "%s: %.*s\n", __func__, sizeof(a), a); #endif } return err; } int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz) { int err; err = -ENOMEM; un->un_lzma = do_lzma; memset(un->un_a, 0, sizeof(un->un_a)); un->un_a[SQUN_PROB].buf = un->un_prob; un->un_a[SQUN_PROB].sz = sizeof(un->un_prob); if (res_sz) { un->un_a[SQUN_RESULT].buf = kmalloc(res_sz, GFP_KERNEL); if (unlikely(!un->un_a[SQUN_RESULT].buf)) return err; un->un_a[SQUN_RESULT].sz = res_sz; } un->un_stream.next_in = NULL; un->un_stream.avail_in = 0; #ifdef __KERNEL__ un->un_stream.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); if (unlikely(!un->un_stream.workspace)) return err; #else un->un_stream.opaque = NULL; un->un_stream.zalloc = Z_NULL; un->un_stream.zfree = Z_NULL; #endif err = zlib_inflateInit(&un->un_stream); if (unlikely(err == Z_MEM_ERROR)) return -ENOMEM; BUG_ON(err); return err; } void sqlzma_fin(struct sqlzma_un *un) { int i; for (i = 0; i < SQUN_LAST; i++) if (un->un_a[i].buf && un->un_a[i].buf != un->un_prob) kfree(un->un_a[i].buf); BUG_ON(zlib_inflateEnd(&un->un_stream) != Z_OK); } #ifdef __KERNEL__ EXPORT_SYMBOL(sqlzma_un); EXPORT_SYMBOL(sqlzma_init); EXPORT_SYMBOL(sqlzma_fin); #if 0 static int __init sqlzma_init(void) { return 0; } static void __exit sqlzma_exit(void) { } module_init(sqlzma_init); module_exit(sqlzma_exit); #endif MODULE_LICENSE("GPL"); MODULE_AUTHOR("Junjiro Okajima <sfjro at users dot sf dot net>"); MODULE_VERSION("$Id: uncomp.c,v 1.7 2008-03-12 16:58:34 jro Exp $"); MODULE_DESCRIPTION("LZMA uncompress for squashfs. " "Some functions for squashfs to support LZMA and " "a tiny wrapper for LzmaDecode.c in LZMA SDK from www.7-zip.org."); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zDecode.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnpackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnpackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _db.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &db = _db; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = db.Folders[folderIndex]; UInt64 unpackSize = folderInfo.GetUnpackSize(); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; // Count partial_folder_size // efi.UnpackSize += unpackSize; // importantTotalUnpacked += unpackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnpacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnpacked = 0; UInt64 totalFolderUnpacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnpacked += totalFolderUnpacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnpacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnpacked = efi.UnpackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &db = volume.Database; #else const CArchiveDatabaseEx &db = _db; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = db.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&db, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = db.Folders[folderIndex]; totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef _NO_CRYPTO bool passwordIsDefined; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &db.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; UInt64 fileSize = fi.Size; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fi.CrcDefined && _checkCrc) digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/CpuArch.h" } #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _db.Files.Size(); return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidPhySize, VT_UI8}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidOffset, VT_UI8} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _db.Folders.Size(); i++) { const CFolder &f = _db.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) { UInt64 value; if (v.GetItem(index, value)) { FILETIME ft; ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); prop = ft; } } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { case kpidPath: if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; case kpidIsDir: prop = item.IsDir; break; case kpidSize: { prop = item.Size; // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _db.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; case kpidEncrypted: prop = IsEncrypted(index2); break; case kpidIsAnti: prop = _db.IsItemAnti(index2); break; #ifndef _SFX case kpidMethod: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Props.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Props.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Props; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Props.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Props; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Props.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Props.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Props[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); #ifndef _NO_CRYPTO _passwordIsDefined = false; UString password; #endif HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO , getTextPassword, _passwordIsDefined #endif ); RINOK(result); _db.Fill(); _inStream = stream; } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); return S_OK; COM_TRY_END } #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _db; #ifndef _NO_CRYPTO bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif DECL_EXTERNAL_CODECS_VARS }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = (UInt32)kNumFastBytesForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = (UInt32)kDictionaryForHeaders; oneMethodInfo.Props.Add(prop); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Props = oneMethodInfo.Props; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Props.Size(); j++) { const CProp &prop = methodFull.Props[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) { ft = 0; ftDefined = false; if (!writeTime) return S_OK; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream != 0) db = &_db; #endif CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem ui; ui.NewProperties = IntToBool(newProperties); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; if (ui.IndexInArchive != -1) { const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; ui.Size = fi.Size; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } if (ui.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) nameIsDefined = false; else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { ui.Name = NItemName::MakeLegalName(prop.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } if (ui.NewData) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } updateItems.Add(ui); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef _NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if(encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; options.HeaderOptions.WriteATime = WriteATime; options.HeaderOptions.WriteMTime = WriteMTime; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; COutArchive archive; CArchiveDatabase newDatabase; HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, archive, newDatabase, outStream, updateCallback, options); RINOK(res); updateItems.ClearAndFree(); return archive.WriteDatabase(EXTERNAL_CODECS_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttributes, kComment, kEncodedHeader, kStartPos, kDummy }; } }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" } #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { static void BoolVector_Fill_False(CBoolVector &v, int size) { v.Clear(); v.Reserve(size); for (int i = 0; i < size; i++) v.Add(false); } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) { if (index >= (UInt32)v.Size()) return true; bool res = v[index]; v[index] = true; return res; } bool CFolder::CheckStructure() const { const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax const int kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); int i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; BoolVector_Fill_False(v, UnpackSizes.Size()); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; int i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { CIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; const CCoderInfo &coder = Coders[i]; for (j = 0; j < coder.NumInStreams; j++) inStreamToCoder.Add(i); for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } for (i = 0; i < kMaskSize; i++) for (int j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; for (i = 0; i < kMaskSize; i++) if (((1 << i) & mask[i]) != 0) return false; return true; } class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); coder.Props.SetCapacity((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bp; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { folder.PackStreams.Add(i); break; } if (folder.PackStreams.Size() != 1) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { BoolVector_Fill_False(packCRCsDefined, numPackStreams); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for (CNum i = 0; i < numPackStreams; i++) packCRCs.Add(0); } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnpackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CBoolVector crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnpackCRCDefined = crcsDefined[i]; folder.UnpackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { numUnpackStreamsInFolders.Clear(); numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnpackStreamsInFolders.IsEmpty()) for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(1); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CBoolVector digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { BoolVector_Fill_False(digestsDefined, numDigestsTotal); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) digests.Add(0); } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnpackInfo: { ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for (int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles) { ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Values.Reserve(numFiles); for (int i = 0; i < numFiles; i++) { UInt64 t = 0; if (v.Defined[i]) t = ReadUInt64(); v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArchiveInfo.DataStartPosition, db.PackSizes, db.PackCRCsDefined, db.PackCRCs, db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for (int i = 0; i < db.Folders.Size(); i++) { db.NumUnpackStreamsVector.Add(1); CFolder &folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digestsDefined.Add(folder.UnpackCRCDefined); digests.Add(folder.UnpackCRC); } } db.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!db.PackSizes.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; BoolVector_Fill_False(emptyStreamVector, (int)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); size_t ppp = _inByteBack->_pos; bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (int i = 0; i < db.Files.Size(); i++) _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; file.AttribDefined = boolVector[i]; if (file.AttribDefined) file.Attrib = ReadUInt32(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; BoolVector_Fill_False(emptyFileVector, numEmptyStreams); BoolVector_Fill_False(antiFileVector, numEmptyStreams); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThrowIncorrect(); addPropIdToList = false; break; } default: addPropIdToList = isKnownType = false; } if (isKnownType) { if(addPropIdToList) db.ArchiveInfo.FileInfoPopIDs.Add(type); } else SkeepData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; CNum numAntiItems = 0; for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti.Add(isAnti); } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; public: size_t _pos; void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnpackSizes; UInt32 UnpackCRC; bool UnpackCRCDefined; CFolder(): UnpackCRCDefined(false) {} UInt64 GetUnpackSize() const // test it { if (UnpackSizes.IsEmpty()) return 0; for (int i = UnpackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnpackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } bool CheckStructure() const; }; struct CUInt64DefVector { CRecordVector<UInt64> Values; CRecordVector<bool> Defined; void Clear() { Values.Clear(); Defined.Clear(); } void ReserveDown() { Values.ReserveDown(); Values.ReserveDown(); } bool GetItem(int index, UInt64 &value) const { if (index < Defined.Size() && Defined[index]) { value = Values[index]; return true; } value = 0; return false; } void SetItem(int index, bool defined, UInt64 value) { while (index >= Defined.Size()) Defined.Add(false); Defined[index] = defined; if (!defined) return; while (index >= Values.Size()) Values.Add(0); Values[index] = value; } bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } }; struct CFileItem { UInt64 Size; UInt32 Attrib; UInt32 Crc; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; bool AttribDefined; CFileItem(): HasStream(true), IsDir(false), CrcDefined(false), AttribDefined(false) {} void SetAttrib(UInt32 attrib) { AttribDefined = true; Attrib = attrib; } }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnpackStreamsVector; CObjectVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnpackStreamsVector.Clear(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); } void ReserveDown() { PackSizes.ReserveDown(); PackCRCsDefined.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); Files.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { int size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsSolid() const { for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } void SetItemAnti(int index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; void AddFile(const CFileItem &file, const CFileItem2 &file2); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if (processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 3; return WriteDirect(buf, 8); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[24]; SetUInt64(buf + 4, h.NextHeaderOffset); SetUInt64(buf + 12, h.NextHeaderSize); SetUInt32(buf + 20, h.NextHeaderCRC); SetUInt32(buf, CrcCalc(buf + 4, 20)); return WriteDirect(buf, 24); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) { _outByte.WriteByte(b); _crc = CRC_UPDATE_BYTE(_crc, b); } else _outByte2.WriteByte(b); } void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } WriteByte(firstByte); for (;i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef _7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propsSize = coder.Props.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propsSize != 0) ? 0x20 : 0 ); WriteByte(b); WriteBytes(longID, idSize); if (isComplex) { WriteNumber(coder.NumInStreams); WriteNumber(coder.NumOutStreams); } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; WriteNumber(bindPair.InIndex); WriteNumber(bindPair.OutIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { WriteNumber(folder.PackStreams[i]); } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for (int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } void COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for (i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); if (numDefined == digestsDefined.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(digestsDefined); } for (i = 0; i < digests.Size(); i++) if (digestsDefined[i]) WriteUInt32(digests[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); for (int i = 0; i < packSizes.Size(); i++) WriteNumber(packSizes[i]); WriteHashDigests(packCRCsDefined, packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); for (int i = 0; i < folders.Size(); i++) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); int i; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnpackSizes.Size(); j++) WriteNumber(folder.UnpackSizes[j]); } CRecordVector<bool> unpackCRCsDefined; CRecordVector<UInt32> unpackCRCs; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unpackCRCsDefined.Add(folder.UnpackCRCDefined); unpackCRCs.Add(folder.UnpackCRC); } WriteHashDigests(unpackCRCsDefined, unpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { WriteByte(NID::kSubStreamsInfo); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } } bool needFlag = true; CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) { if (j + 1 != numUnpackStreamsInFolders[i]) { if (needFlag) WriteByte(NID::kSize); needFlag = false; WriteNumber(unpackSizes[index]); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnpackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } WriteHashDigests(digestsDefined2, digests2); WriteByte(NID::kEnd); } void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) { return; } /* 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } */ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) { const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8; const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); WriteByte(type); WriteNumber(dataSize); if (numDefined == v.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(v); } WriteByte(0); } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { int numDefined = 0; int i; for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) numDefined++; if (numDefined == 0) return; WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) WriteUInt64(v.Values[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnpackCRCDefined = true; folderItem.UnpackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } void COutArchive::WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; headerOffset = packedSize; WriteByte(NID::kHeader); // Archive Properties if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCsDefined, db.PackCRCs); WriteUnpackInfo(db.Folders); CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digestsDefined.Add(file.CrcDefined); digests.Add(file.Crc); } WriteSubStreamsInfo( db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.Reserve(db.Files.Size()); int numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) if (db.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { WriteByte(NID::kEmptyStream); WriteNumber((emptyStreamVector.Size() + 7) / 8); WriteBoolVector(emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDir); if (!file.IsDir) numEmptyFiles++; bool isAnti = db.IsItemAnti(i); antiVector.Add(isAnti); if (isAnti) numAntiItems++; } } if (numEmptyFiles > 0) { WriteByte(NID::kEmptyFile); WriteNumber((emptyFileVector.Size() + 7) / 8); WriteBoolVector(emptyFileVector); } if (numAntiItems > 0) { WriteByte(NID::kAnti); WriteNumber((antiVector.Size() + 7) / 8); WriteBoolVector(antiVector); } } } { /* ---------- Names ---------- */ int numDefined = 0; size_t namesDataSize = 0; for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; if (!name.IsEmpty()) numDefined++; namesDataSize += (name.Length() + 1) * 2; } if (numDefined > 0) { namesDataSize++; SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; for (int t = 0; t <= name.Length(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } } } } if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); int numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; boolVector.Add(defined); if (defined) numDefined++; } if (numDefined > 0) { WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (file.AttribDefined) WriteUInt32(file.Attrib); } } } WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (db.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { bool encodeHeaders = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, headerOptions, headerOffset); if (encodeHeaders) { CByteBuffer buf; buf.SetCapacity(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, headerOptions, headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, (const Byte *)buf, _countSize, packSizes, folders)); _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>()); WriteUnpackInfo(folders); WriteByte(NID::kEnd); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const { file = Files[index]; file2.CTimeDefined = CTime.GetItem(index, file2.CTime); file2.ATimeDefined = ATime.GetItem(index, file2.ATime); file2.MTimeDefined = MTime.GetItem(index, file2.MTime); file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); file2.IsAnti = IsItemAnti(index); } void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) { int index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); SetItemAnti(index, file2.IsAnti); Files.Add(file); } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; bool WriteCTime; bool WriteATime; bool WriteMTime; CHeaderOptions(): CompressMainHeader(true), WriteCTime(false), WriteATime(false), WriteMTime(true) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); void WriteUnpackInfo(const CObjectVector<CFolder> &folders); void WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); void WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCTime, NULL, kpidCTime, VT_FILETIME}, { NID::kMTime, NULL, kpidMTime, VT_FILETIME}, { NID::kATime, NULL, kpidATime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttrib, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, #ifndef _SFX { 97, NULL, kpidEncrypted, VT_BOOL}, { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if ((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // 7zUpdate.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnpackStreamsVector[i1], db.NumUnpackStreamsVector[i2])); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = ui.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = ui.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kMatchFinderForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = kDictionaryForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Props.Add(prop); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData) continue; if (!ui.HasStream()) continue; if (useFilters) { const UString name = ui.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); for (int i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (db != 0) { for(i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; for (CNum fileIndex = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fileIndex++) { if (db->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnpackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)db); } //////////////////////////// RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; if (numSolidFiles == 1) { if (ui.Size > inSizeForReduce) inSizeForReduce = ui.Size; } else inSizeForReduce += ui.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = db->Folders[folderIndex]; CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; db->GetFile(fi, file, file2); if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewProperties) { CFileItem uf; FromUpdateItemToFileItem(ui, uf, file2); uf.Size = file.Size; uf.Crc = file.Crc; uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; } } newDatabase.AddFile(file, file2); } } } folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = ui.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; if (file.Size != 0) { file.CrcDefined = true; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } newDatabase.AddFile(file, file2); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; } } groups.ClearAndFree(); { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1) if (db->Files[ui.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); newDatabase.AddFile(file, file2); } } newDatabase.ReserveDown(); return S_OK; } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { return Update2( EXTERNAL_CODECS_LOC_VARS inStream, db, updateItems, archive, newDatabase, seqOutStream, updateCallback, options); } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { int IndexInArchive; int IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; UInt32 Attrib; bool NewData; bool NewProperties; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL && result != S_FALSE) return result; } RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../../ICoder.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Props.Size(); j++) if (oneMethodInfo.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; oneMethodInfo.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); prop.Id = (name.CompareNoCase(L"D") == 0) ? NCoderPropID::kDictionarySize : NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { bool isSolid; switch(value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; WriteCTime = false; WriteATime = false; WriteMTime = true; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) { RINOK(SetBoolProperty(_encryptHeaders, value)); _encryptHeadersSpecified = true; return S_OK; } if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp prop; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); prop.Id = NCoderPropID::kDictionarySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(1).CompareNoCase(L"C") == 0) { UInt32 blockSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); prop.Id = NCoderPropID::kBlockSize; prop.Value = blockSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); prop.Id = NCoderPropID::kUsedMemorySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); } return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (value.boolVal != VARIANT_FALSE); return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } #define INTERFACE_IArchiveOpenCallback(x) \ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { INTERFACE_IArchiveOpenCallback(PURE); }; #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { INTERFACE_IArchiveExtractCallback(PURE) }; #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { INTERFACE_IArchiveOpenVolumeCallback(PURE); }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ Int32 *newData, /*1 - new data, 0 - old data */ \ Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ ) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { INTERFACE_IArchiveUpdateCallback(PURE); }; #define INTERFACE_IArchiveUpdateCallback2(x) \ INTERFACE_IArchiveUpdateCallback(x) \ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { INTERFACE_IArchiveUpdateCallback2(PURE); }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp ================================================ // LzmaArcRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "LzmaHandler.h" static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } static CArcInfo g_ArcInfo = { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; REGISTER_ARC(Lzma) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp ================================================ // LzmaFiltersDecode.cpp #include "StdAfx.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; HRESULT CDecoder::Code( DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress) { *inProcessedSize = (UInt64)(Int64)-1; if (block.FilterMethod > 1) return E_NOTIMPL; if (!_lzmaDecoder) { RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); if (_lzmaDecoder == 0) return E_NOTIMPL; } { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); } bool filteredMode = (block.FilterMethod == 1); CMyComPtr<ICompressSetOutStream> setOutStream; if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { RINOK(flush->Flush()); } RINOK(setOutStream->ReleaseOutStream()); } CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); if (getInStreamProcessedSize) { RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); } return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h ================================================ // LzmaFiltersDecode.h #ifndef __LZMA_FILTERS_DECODE_H #define __LZMA_FILTERS_DECODE_H #include "../../Common/CreateCoder.h" #include "LzmaItem.h" namespace NArchive { namespace NLzma { class CDecoder { CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; public: HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaHandler.cpp ================================================ // LzmaHandler.cpp #include "StdAfx.h" #include "LzmaHandler.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/DummyOutStream.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { STATPROPSTG kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_UI1} }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = 1; return S_OK; } static void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s + MyStringLen(s)); } static void DictSizeToString(UInt32 value, wchar_t *s) { for (int i = 0; i <= 31; i++) if ((UInt32(1) << i) == value) { ConvertUInt32ToString(i, s); return; } wchar_t c = L'b'; if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = L'm'; } else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = L'k'; } ConvertUInt32ToString(value, s); int p = MyStringLen(s); s[p++] = c; s[p++] = L'\0'; } static void MyStrCat(wchar_t *d, const wchar_t *s) { MyStringCopy(d + MyStringLen(d), s); } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { if (index != 0) return E_INVALIDARG; NWindows::NCOM::CPropVariant propVariant; switch(propID) { case kpidSize: if (m_StreamInfo.HasUnpackSize()) propVariant = (UInt64)m_StreamInfo.UnpackSize; break; case kpidPackSize: propVariant = (UInt64)m_PackSize; break; case kpidMethod: { wchar_t s[64]; s[0] = '\0'; if (m_StreamInfo.IsThereFilter) { const wchar_t *f; if (m_StreamInfo.FilterMethod == 0) f = L"Copy"; else if (m_StreamInfo.FilterMethod == 1) f = L"BCJ"; else f = L"Unknown"; MyStrCat(s, f); MyStrCat(s, L" "); } MyStrCat(s, L"LZMA:"); DictSizeToString(m_StreamInfo.GetDicSize(), s); propVariant = s; break; } } propVariant.Detach(value); return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* openArchiveCallback */) { { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); if (res != S_OK) return S_FALSE; Byte b; RINOK(ReadStream_FALSE(inStream, &b, 1)); if (b != 0) return S_FALSE; UInt64 endPos; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); m_Stream = inStream; } return S_OK; } STDMETHODIMP CHandler::Close() { m_Stream.Release(); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN bool allFilesMode = (numItems == UInt32(-1)); if (!allFilesMode) { if (numItems == 0) return S_OK; if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); RINOK(extractCallback->SetTotal(m_PackSize)); UInt64 currentTotalPacked = 0; CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); { CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(); if(!testMode && !realOutStream) return S_OK; extractCallback->PrepareOperation(askMode); } CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); CDecoder decoder; RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); UInt64 streamPos = m_StreamStartPosition; Int32 opRes = NArchive::NExtract::NOperationResult::kOK; bool firstItem = true; for (;;) { CHeader st; HRESULT result = ReadStreamHeader(m_Stream, st); if (result != S_OK) { if (firstItem) return E_FAIL; break; } firstItem = false; lps->OutSize = outStreamSpec->GetSize(); lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); streamPos += st.GetHeaderSize(); UInt64 packProcessed; { result = decoder.Code( EXTERNAL_CODECS_VARS st, m_Stream, outStream, &packProcessed, progress); if (result == E_NOTIMPL) { opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; } if (result == S_FALSE) { opRes = NArchive::NExtract::NOperationResult::kDataError; break; } RINOK(result); } if (packProcessed == (UInt64)(Int64)-1) break; RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); currentTotalPacked += packProcessed; streamPos += packProcessed; } outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaHandler.h ================================================ // Lzma/Handler.h #ifndef __GZIP_HANDLER_H #define __GZIP_HANDLER_H #include "Common/MyCom.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #include "LzmaIn.h" namespace NArchive { namespace NLzma { // const UInt64 k_LZMA = 0x030101; class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(IInArchive) QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Open)(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); STDMETHOD(Close)(); STDMETHOD(GetNumberOfItems)(UInt32 *numItems); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); UString GetMethodString(); public: CHandler() { } private: CHeader m_StreamInfo; UInt64 m_StreamStartPosition; UInt64 m_PackSize; CMyComPtr<IInStream> m_Stream; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaIn.cpp ================================================ // Archive/LzmaIn.cpp #include "StdAfx.h" #include "LzmaIn.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace NLzma { static bool CheckDictSize(const Byte *p) { UInt32 dicSize = GetUi32(p); int i; for (i = 1; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return false; } HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) { Byte sig[5 + 9]; RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); const Byte kMaxProp0Val = 5 * 5 * 9 - 1; if (sig[0] > kMaxProp0Val) return S_FALSE; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i]; block.IsThereFilter = false; block.FilterMethod = 0; if (!CheckDictSize(sig + 1)) { if (sig[0] > 1 || sig[1] > kMaxProp0Val) return S_FALSE; block.IsThereFilter = true; block.FilterMethod = sig[0]; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i + 1]; if (!CheckDictSize(block.LzmaProps + 1)) return S_FALSE; RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); } UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); block.UnpackSize = GetUi64(sig + unpOffset); if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) return S_FALSE; return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaIn.h ================================================ // Archive/LzmaIn.h #ifndef __ARCHIVE_LZMA_IN_H #define __ARCHIVE_LZMA_IN_H #include "LzmaItem.h" #include "../../IStream.h" namespace NArchive { namespace NLzma { HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/LzmaItem.h ================================================ // Archive/LzmaItem.h #ifndef __ARCHIVE_LZMA_ITEM_H #define __ARCHIVE_LZMA_ITEM_H #include "Common/Types.h" #include "../../../../C/CpuArch.h" namespace NArchive { namespace NLzma { struct CHeader { UInt64 UnpackSize; bool IsThereFilter; Byte FilterMethod; Byte LzmaProps[5]; UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Lzma/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Split/SplitHandler.cpp ================================================ // SplitHandler.cpp #include "StdAfx.h" #include "Common/ComTry.h" #include "Common/Defs.h" #include "Common/NewHandler.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/MultiStream.h" #include "SplitHandler.h" using namespace NWindows; using namespace NTime; namespace NArchive { namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO class CSeqName { public: UString _unchangedPart; UString _changedPart; bool _splitStyle; UString GetNextName() { UString newName; if (_splitStyle) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { c = 'a'; newName = c + newName; continue; } else if (c == 'Z') { c = 'A'; newName = c + newName; continue; } c++; if ((c == 'z' || c == 'Z') && i == 0) { _unchangedPart += c; wchar_t newChar = (c == 'z') ? L'a' : L'A'; newName.Empty(); numLetters++; for (int k = 0; k < numLetters; k++) newName += newChar; break; } newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } else { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } _changedPart = newName; return _unchangedPart + _changedPart; } }; STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); if (openArchiveCallback == 0) return S_FALSE; // try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback) != S_OK) return S_FALSE; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; _name = prop.bstrVal; } int dotPos = _name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { prefix = _name.Left(dotPos + 1); ext = _name.Mid(dotPos + 1); } else ext = _name; UString extBig = ext; extBig.MakeUpper(); CSeqName seqName; int numLetters = 2; bool splitStyle = false; if (extBig.Right(2) == L"AA") { splitStyle = true; while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != 'A') break; numLetters++; } } else if (ext.Right(2) == L"01") { while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Length()) return S_FALSE; } else return S_FALSE; _streams.Add(stream); seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); seqName._changedPart = ext.Right(numLetters); seqName._splitStyle = splitStyle; if (prefix.Length() < 1) _subName = L"file"; else _subName = prefix.Left(prefix.Length() - 1); _totalSize = 0; UInt64 size; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName = seqName.GetNextName(); CMyComPtr<IInStream> nextStream; HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } } /* catch(...) { return S_FALSE; } */ return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { _sizes.Clear(); _streams.Clear(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; } prop.Detach(value); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) { COM_TRY_BEGIN if (numItems != UInt32(-1)) { if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; extractCallback->SetTotal(_totalSize); /* CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) return E_FAIL; */ UInt64 currentTotalSize = 0; UInt64 currentItemSize; RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = 0; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->PrepareOperation(askMode)); if (testMode) { RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); return S_OK; } if (!testMode && (!realOutStream)) return S_OK; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); currentItemSize = copyCoderSpec->TotalSize; } realOutStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; for (int i = 0; i < _streams.Size(); i++) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Split/SplitHandler.h ================================================ // Split/Handler.h #ifndef __SPLIT_HANDLER_H #define __SPLIT_HANDLER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../IArchive.h" namespace NArchive { namespace NSplit { class CHandler: public IInArchive, public IInArchiveGetStream, // public IOutArchive, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); private: UString _subName; UString _name; CObjectVector<CMyComPtr<IInStream> > _streams; CRecordVector<UInt64> _sizes; UInt64 _totalSize; }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Split/SplitHandlerOut.cpp ================================================ // Split/OutHandler.cpp #include "StdAfx.h" #include "SplitHandler.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" using namespace NWindows; namespace NArchive { namespace NSplit { /* STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN if (numItems != 1) return E_INVALIDARG; UInt64 volumeSize = 0; CMyComPtr<IArchiveUpdateCallback2> callback2; updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&callback2); RINOK(callback2->GetVolumeSize(0, &volumeSize)); Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; UInt32 fileIndex = 0; RINOK(updateCallback->GetUpdateItemInfo(fileIndex, &newData, &newProperties, &indexInArchive)); if (newProperties != 0) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } } UInt64 newSize; bool thereIsCopyData = false; if (newData != 0) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; newSize = prop.uhVal.QuadPart; } else thereIsCopyData = true; UInt64 pos = 0; while(pos < newSize) { } return S_OK; COM_TRY_END } */ }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Split/SplitRegister.cpp ================================================ // SplitRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "SplitHandler.h" static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } /* #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } #else #define CreateArcOut 0 #endif */ static CArcInfo g_ArcInfo = { L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; REGISTER_ARC(Split) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/Split/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Archive/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwapRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderOpt.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # Begin Group "LZM" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaItem.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ LZM_OBJS = \ $O\LzmaArcRegister.obj \ $O\LzmaFiltersDecode.obj \ $O\LzmaHandler.obj \ $O\LzmaIn.obj \ SPLIT_OBJS = \ $O\SplitHandler.obj \ $O\SplitHandlerOut.obj \ $O\SplitRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(LZM_OBJS) \ $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp $(COMPL) $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } RINOK(WriteStream(outStream, _buffer, size)); _nowPos64 += size; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { size_t processedSize = kBufferSize - bufferPos; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } RINOK(WriteStream(_outStream, _buffer, _bufferPos)); _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; size_t processedSizeTemp = kBufferSize - _bufferPos; RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); _bufferPos = _bufferPos + (UInt32)processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if (_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } UInt32 ReadBytes(Byte *buf, UInt32 size) { if ((UInt32)(_bufferLimit - _buffer) >= size) { for (UInt32 i = 0; i < size; i++) buf[i] = _buffer[i]; _buffer += size; return size; } for (UInt32 i = 0; i < size; i++) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return i; buf[i] = *_buffer++; } return size; } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; if (processedSize != NULL) *processedSize = 0; if (size > _size) { size = (UInt32)_size; if (size == 0) { _overflow = true; return E_FAIL; } } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize != NULL) *processedSize = size; return result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size) { _size = size; _overflow = false; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "MethodProps.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProps = method.Props.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProps != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; HRESULT res = S_OK; try { for (int i = 0; i < numProps; i++) { const CProp &prop = method.Props[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "../../Common/MyVector.h" #include "../../Windows/PropVariant.h" #include "MethodId.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Props; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { memcpy(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(data, _dataPointer + _pos, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memcpy(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, (size_t)size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return (rem == size ? S_OK : E_FAIL); } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); WRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/Bcj2Coder.cpp ================================================ // Bcj2Coder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/Bcj2Coder.h ================================================ // Bcj2Coder.h #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "RangeCoderBit.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/Bcj2Register.cpp ================================================ // Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BcjCoder.cpp ================================================ // BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BcjCoder.h ================================================ // BcjCoder.h #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H extern "C" { #include "../../../C/Bra.h" } #include "BranchCoder.h" struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BcjRegister.cpp ================================================ // BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BranchCoder.h ================================================ // BranchCoder.h #ifndef __COMPRESS_BRANCH_CODER_H #define __COMPRESS_BRANCH_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BranchMisc.cpp ================================================ // BranchMisc.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Bra.h" } #include "BranchMisc.h" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BranchMisc.h ================================================ // BranchMisc.h #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) MyClassA(BC_ARMT, 0x07, 1) MyClassA(BC_PPC, 0x02, 5) MyClassA(BC_SPARC, 0x08, 5) MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMT) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/ByteSwap.h ================================================ // ByteSwap.h #ifndef __COMPRESS_BYTE_SWAP_H #define __COMPRESS_BYTE_SWAP_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPY_CODER_H #define __COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/CopyRegister.cpp ================================================ // CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaEncoder.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "LzmaUtil" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #include "LzmaBenchCon.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif extern "C" { #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/LzmaUtil/Lzma86Dec.h" #include "../../../../C/LzmaUtil/Lzma86Enc.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } static void ParseUInt32(const CParser &parser, int index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) IncorrectCommand(); } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictDefined = false; UInt32 dict = (UInt32)-1; if(parser[NKey::kDict].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dict); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; size_t inSize = (size_t)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; Byte *outBuffer = 0; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictDefined) dict = 1 << 23; int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictDefined) dict = 1 << 23; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = (BSTR)(const wchar_t *)mf; props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; int numProps = kNumPropsMax; if (!mcDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; decoderSpec->FinishStream = true; const UInt32 kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int MY_CDECL main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" } #include "../../../Common/MyCom.h" #ifdef BENCH_MT #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #else #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLzma::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLzma::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/comp.cc ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma.txt. */ /* $Id: comp.cc,v 1.29 2006/11/27 03:54:58 jro Exp $ */ // extract some parts from lzma443/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <errno.h> #include "StdAfx.h" #include "../../../Common/MyInitGuid.h" #include "../../../Common/MyWindows.h" #include "../../../Common/StringConvert.h" #include "../LzmaEncoder.h" #include <pthread.h> #include <zlib.h> #include "sqlzma.h" ////////////////////////////////////////////////////////////////////// class CMemoryStream { protected: Bytef *m_data; UInt64 m_limit; UInt64 m_pos; public: CMemoryStream(Bytef *data, UInt64 size) : m_data(data), m_limit(size), m_pos(0) {} virtual ~CMemoryStream() {} }; class CInMemoryStream : public CMemoryStream, public IInStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialInStream> m_stream; public: MY_UNKNOWN_IMP1(IInStream); CInMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~CInMemoryStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { UInt64 room = m_limit - m_pos; if (size > room) size = room; if (size) { memcpy(data, m_data + m_pos, size); m_pos += size; } if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } }; class COutMemoryStream : public CMemoryStream, public IOutStream, public CMyUnknownImp { //protected: CMyComPtr<ISequentialOutStream> m_stream; public: MY_UNKNOWN_IMP1(IOutStream); COutMemoryStream(Bytef *data, UInt64 size) : CMemoryStream(data, size), m_stream(this) {} virtual ~COutMemoryStream() {} UInt32 GetSize() {return m_pos;} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (m_pos + size > m_limit) return -ENOSPC; memcpy(m_data + m_pos, data, size); m_pos += size; if (processedSize) *processedSize = size; return S_OK; } // disabled all STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { assert(0); return E_NOTIMPL; } STDMETHOD(SetSize)(Int64 newSize) { assert(0); return E_NOTIMPL; } }; ////////////////////////////////////////////////////////////////////// static int LzmaCompress(Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out, struct sqlzma_opts *opts, uLong *total_out) { int err; HRESULT res; const Byte a[] = { avail_in, avail_in >> 8, avail_in >> 16, avail_in >> 24, 0, 0, 0, 0 }; NCompress::NLzma::CEncoder encoderSpec; CMyComPtr<ICompressCoder> encoder = &encoderSpec; encoder->AddRef(); CInMemoryStream inStreamSpec(next_in, avail_in); CMyComPtr<ISequentialInStream> inStream = &inStreamSpec; inStream->AddRef(); COutMemoryStream outStreamSpec(next_out, avail_out); CMyComPtr<ISequentialOutStream> outStream = &outStreamSpec; outStream->AddRef(); // these values are dpending upon is_lzma() macro in sqlzma.h const UInt32 dictionary = opts->dicsize; const UString mf = L"BT4"; const UInt32 posStateBits = 2; const UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data const UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data const UInt32 algorithm = 2; const UInt32 numFastBytes = 128; const UInt32 matchFinderCycles = 16 + numFastBytes / 2; //const bool matchFinderCyclesDefined = false; const PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kMatchFinderCycles }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumPropsMax]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_FALSE; // EOS properties[8].vt = VT_UI4; properties[8].ulVal = UInt32(matchFinderCycles); err = -EINVAL; res = encoderSpec.SetCoderProperties(propIDs, properties, kNumPropsMax - 1); if (res) goto out; res = encoderSpec.WriteCoderProperties(outStream); if (res) goto out; UInt32 r; res = outStream->Write(a, sizeof(a), &r); if (res || r != sizeof(a)) goto out; err = encoder->Code(inStream, outStream, 0, /*broken*/0, 0); if (err) goto out; *total_out = outStreamSpec.GetSize(); out: return err; } ////////////////////////////////////////////////////////////////////// #define Failure(p) do { \ fprintf(stderr, "%s:%d: please report to jro " \ "{%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x}\n", \ __func__, __LINE__, \ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ abort(); \ }while(0) extern "C" int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out) { int err; Bytef *p = next_out; uInt l = avail_out; stream->next_in = next_in; stream->avail_in = avail_in; stream->next_out = p; stream->avail_out = l; err = deflate(stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) goto out_err; if (avail_in < stream->total_out) return err; if (is_lzma(*p)) Failure(p); if (opts->try_lzma) { unsigned char a[stream->total_out]; uLong processed; memcpy(a, p, stream->total_out); // malloc family in glibc and stdc++ seems to be thread-safe err = LzmaCompress(next_in, avail_in, p, l, opts, &processed); if (!err && processed <= stream->total_out) { if (!is_lzma(*next_out)) Failure(next_out); stream->total_out = processed; err = Z_STREAM_END; } else { //puts("by zlib"); memcpy(p, a, stream->total_out); err = Z_STREAM_END; } } return err; out_err: fprintf(stderr, "%s: ZLIB err %s\n", __func__, zError(err)); return err; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe LIBS = $(LIBS) user32.lib CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ LZMA_OPT_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra86.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ C_LZMAUTIL_OBJS = \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ OBJS = \ $O\StdAfx.obj \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(C_OBJS) \ $(C_LZMAUTIL_OBJS) \ $O\FileStreams.obj \ $O\FileIO.obj \ !include "../../../Build.mak" $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZMAUTIL_OBJS): ../../../../C/LzmaUtil/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaDecoder.o \ LzmaEncoder.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ Bra86.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ Lzma86Dec.o \ Lzma86Enc.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaDecoder.o: ../LzmaDecoder.cpp $(CXX) $(CFLAGS) ../LzmaDecoder.cpp LzmaEncoder.o: ../LzmaEncoder.cpp $(CXX) $(CFLAGS) ../LzmaEncoder.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c Bra86.o: ../../../../C/Bra86.c $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c LzFind.o: ../../../../C/LzFind.c $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c LzmaDec.o: ../../../../C/LzmaDec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c LzmaEnc.o: ../../../../C/LzmaEnc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c Lzma86Dec.o: ../../../../C/LzmaUtil/Lzma86Dec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Dec.c Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma86Enc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LZMA_Alone/sqlzma.mk ================================================ # Copyright (C) 2006-2007 Junjiro Okajima # Copyright (C) 2006-2007 Tomas Matejicek, slax.org # # LICENSE follows the described one in lzma.txt. # $Id: sqlzma.mk,v 1.1 2007-11-05 05:43:36 jro Exp $ ifndef Sqlzma $(error Sqlzma is not defined) endif include makefile.gcc ifdef UseDebugFlags DebugFlags = -Wall -O0 -g -UNDEBUG endif # -pthread CXXFLAGS = ${CFLAGS} -D_REENTRANT -include pthread.h -DNDEBUG ${DebugFlags} Tgt = liblzma_r.a all: ${Tgt} RObjs = LzmaEncoder_r.o LzmaEnc_r.o Alloc_r.o StreamUtils_r.o \ LzFind_r.o Bcj2Coder_r.o OutBuffer_r.o 7zCrc_r.o %_r.cc: ../%.cpp ln $< $@ %_r.c: ../../../../C/%.c ln $< $@ %_r.c: ../../../../C/Compress/Lz/%.c ln $< $@ %_r.cc: ../../Common/%.cpp ln $< $@ %_r.cc: ../RangeCoder/%.cpp ln $< $@ LzmaEncoder_r.o: CXXFLAGS += -I../ LzmaEnc_r.o: CFLAGS += -I../../../../C LzFind_r.o: CFLAGS += -I../../../../C Alloc_r.o: CFLAGS += -I../../../../C StreamUtils_r.o: CXXFLAGS += -I../../Common # MatchFinder_r.o: CFLAGS += -I../../../../C/Compress/Lz LzFindMt_r.o: CFLAGS += -I../../../../C RangeCoderBit_r.o: CXXFLAGS += -I../RangeCoder Bcj2Coder_r.o: CXXFLAGS += -I../ OutBuffer_r.o: CXXFLAGS += -I../../Common 7zCrc_r.o: CFLAGS += -I../../../../C comp.o: CXXFLAGS += -I${Sqlzma} comp.o: comp.cc ${Sqlzma}/sqlzma.h liblzma_r.a: ${RObjs} comp.o ${AR} cr $@ $^ clean: clean_sqlzma clean_sqlzma: $(RM) comp.o *_r.o ${Tgt} *~ # Local variables: ; # compile-command: (concat "make Sqlzma=../../../../.. -f " (file-name-nondirectory (buffer-file-name))); # End: ; ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LzmaDecoder.cpp ================================================ // LzmaDecoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) { LzmaDec_Construct(&_state); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); MyFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; LzmaDec_Init(&_state); _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.dicPos; SizeT curSize = _state.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; } #endif }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LzmaDecoder.h ================================================ // LzmaDecoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H extern "C" { #include "../../../C/LzmaDec.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif bool FinishStream; CDecoder(); virtual ~CDecoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LzmaEncoder.cpp ================================================ // LzmaEncoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; // case SZ_ERROR_THREAD: return E_FAIL; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(void *object, void *data, size_t *size) { UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); *size = curSize; return (SRes)res; } static size_t MyWrite(void *object, const void *data, size_t size) { CSeqOutStream *p = (CSeqOutStream *)object; p->Res = WriteStream(p->RealStream, data, size); if (p->Res != 0) return 0; return size; } static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } static void SzFree(void *, void *address) { MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { _seqInStream.SeqInStream.Read = MyRead; _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) throw 1; } CEncoder::~CEncoder() { if (_encoder != 0) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; switch (propIDs[i]) { case NCoderPropID::kNumFastBytes: if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; case NCoderPropID::kMatchFinderCycles: if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; case NCoderPropID::kAlgorithm: if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; case NCoderPropID::kDictionarySize: if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; case NCoderPropID::kPosStateBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; case NCoderPropID::kLitPosBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; case NCoderPropID::kLitContextBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; case NCoderPropID::kMultiThread: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; case NCoderPropID::kMatchFinder: if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; default: return E_INVALIDARG; } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte props[LZMA_PROPS_SIZE]; size_t size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); return WriteStream(outStream, props, size); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _seqOutStream.RealStream = outStream; _seqOutStream.Res = S_OK; return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _seqOutStream.RealStream.Release(); return S_OK; } typedef struct _CCompressProgressImp { ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; } CCompressProgressImp; #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) { CCompressProgressImp *p = (CCompressProgressImp *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { CCompressProgressImp progressImp; progressImp.p.Progress = CompressProgress; progressImp.Progress = progress; progressImp.Res = SZ_OK; _seqInStream.RealStream = inStream; SetOutStream(outStream); SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); ReleaseOutStream(); if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) return _seqOutStream.Res; if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) return progressImp.Res; return SResToHRESULT(res); } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LzmaEncoder.h ================================================ // LzmaEncoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H extern "C" { #include "../../../C/LzmaEnc.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { struct CSeqInStream { ISeqInStream SeqInStream; ISequentialInStream *RealStream; }; struct CSeqOutStream { ISeqOutStream SeqOutStream; CMyComPtr<ISequentialOutStream> RealStream; HRESULT Res; }; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; CSeqInStream _seqInStream; CSeqOutStream _seqOutStream; public: CEncoder(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/LzmaRegister.cpp ================================================ // LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/RangeCoder.h ================================================ // Compress/RangeCoder.h #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) { Range >>= 1; Low += Range & (0 - ((value >> numBits) & 1)); if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/RangeCoderBit.h ================================================ // Compress/RangeCoderBit.h #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 4; const int kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/Compress/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kBlockSize, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define INTERFACE_IProgress(x) \ STDMETHOD(SetTotal)(UInt64 total) x; \ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ DECL_INTERFACE(IProgress, 0, 5) { INTERFACE_IProgress(PURE) }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_7ZIP_VERSION "7-Zip 4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/PropID.h ================================================ // PropID.h #ifndef __7ZIP_PROPID_H #define __7ZIP_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; UInt32 Attrib; bool isDir; bool AttribDefined; bool MTimeDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (NFile::NFind::FindFile(fullProcessedPath, fi)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.MTimeDefined) _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if (newData != NULL) *newData = BoolToInt(true); if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) *indexInArchive = (UInt32)-1; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: prop = dirItem.Name; break; case kpidIsDir: prop = dirItem.isDir(); break; case kpidSize: prop = dirItem.Size; break; case kpidAttrib: prop = dirItem.Attrib; break; case kpidCTime: prop = dirItem.CTime; break; case kpidATime: prop = dirItem.ATime; break; case kpidMTime: prop = dirItem.MTime; break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if (dirItem.isDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////////////////// // Main function int MY_CDECL main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; command.MakeLower(); UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.Compare("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem di; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(name, fi)) { PrintString(UString(L"Can't find file") + name); return 1; } di.Attrib = fi.Attrib; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Name = name; di.FullPath = name; dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.Compare("l") == 0) listCommand = true; else if (command.Compare("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, #ifndef _NO_CRYPTO kPassword, #endif kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, #ifndef _NO_CRYPTO { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, #endif { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for (int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for (int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for (int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); UStringVector archivePaths; { CDirItems dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } for (int i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) archivePaths.Add(dirItems.GetPhyPath(i)); } } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; int i; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if (parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if (options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if (options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO bool PasswordEnabled; UString Password; #endif bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcMTimeDefault = utcMTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDir) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) INTERFACE_IArchiveExtractCallback(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _encrypted; struct CProcessedFileInfo { FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attributes; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool IsDir; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcMTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), WriteMTime(true), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch(propID) { case kpidName: prop = _subArchiveName; break; } else switch(propID) { case kpidName: prop = _fileInfo.Name; break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; case kpidCTime: prop = _fileInfo.CTime; break; case kpidATime: prop = _fileInfo.ATime; break; case kpidMTime: prop = _fileInfo.MTime; break; } prop.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (ReOpenCallback) { CMyComPtr<ICryptoGetTextPassword> getTextPassword; ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" #ifdef _NO_CRYPTO #define INTERFACE_IOpenCallbackUI_Crypto(x) #else #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ #endif #define INTERFACE_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI { INTERFACE_IOpenCallbackUI(=0) }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L"~"; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" #include "../../Archive/IArchive.h" struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UInt32 Attrib; int PhyParent; int LogParent; CDirItem(): PhyParent(-1), LogParent(-1) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; public: CObjectVector<CDirItem> Items; int GetNumFolders() const { return Prefixes.Size(); } UString GetPhyPath(int index) const; UString GetLogPath(int index) const; int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; struct CArcItem { UInt64 Size; FILETIME MTime; UString Name; bool IsDir; bool SizeDefined; bool Censored; UInt32 IndexInServer; int TimeType; CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include <stdio.h> #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; di.Name = fi.Name; dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; int len = name.Length(); int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Length(); int totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; len -= name.Length(); memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; len -= s.Length(); memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } UString CDirItems::GetPhyPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } UString CDirItems::GetLogPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); for (;;) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParent, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; if (!NFind::FindFile(phyPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); UString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParentCur, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &curFolderName, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { const UString name2 = curFolderName + (wchar_t)kDirDelimiter; int parent = dirItems.AddPrefix(phyParent, logParent, name2); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fi.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); for (int ttt = 0; ; ttt++) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); const UString &name = fi.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", options.DefaultItemName); #ifdef _WIN32 outDir.TrimRight(); #endif if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.MTime, options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } res.TrimRight(); return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static const TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fi; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) if (!fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } #ifndef _SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int slashPos2 = arcPath.ReverseFind(L'.'); int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; for (int i = 0; i < Formats.Size(); i++) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) if (Formats[i].Name.CompareNoCase(arcType) == 0) return i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (int pos = 0; pos < arcType.Length();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) pos2 = arcType.Length(); const UString name = arcType.Mid(pos, pos2 - pos); int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = pos2 + 1; } return true; } #endif #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UInt32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) { result = defaultName; NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (arcTypeIndex >= 0) orderIndices.Add(arcTypeIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; Byte hash[1 << 16]; memset(hash, 0xFF, 1 << 16); Byte prevs[256]; if (orderIndices.Size() > 255) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < 2) continue; UInt32 v = sig[0] | ((UInt32)sig[1] << 8); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize--; for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[buf[pos] | ((UInt32)buf[pos + 1] << 8)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = buf[pos] | ((UInt32)buf[pos + 1] << 8); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + 1) if (TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif } for(int i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; RINOK(result); *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { if (formatIndices.Size() >= 3) return E_NOTIMPL; int arcTypeIndex = -1; if (formatIndices.Size() >= 1) arcTypeIndex = formatIndices[formatIndices.Size() - 1]; HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); if (formatIndices.Size() == 1) return S_OK; arcTypeIndex = -1; if (formatIndices.Size() >= 2) arcTypeIndex = formatIndices[formatIndices.Size() - 2]; HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || !getStream) return resSpec; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK || !subSeqStream) return resSpec; CMyComPtr<IInStream> subStream; result = subSeqStream.QueryInterface(IID_IInStream, &subStream); if (result != S_OK || !subStream) return resSpec; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return resSpec; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result != S_OK) return resSpec; return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, NULL, openCallback); int formatInfo; return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, formatIndices, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; SetCallback(fileName, NULL, openCallback, openCallbackNew); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; bool IsOpen; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCTime: case kpidATime: case kpidMTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttrib: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name[name.Length() - 1]; if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name = name.Left(name.Length() - 1); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/StdAfx.h ================================================ // stdafx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Time.h" #include "../../Common/FileStreams.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) { if (formatIndices.Size() > 1) return false; int arcTypeIndex = -1; if (formatIndices.Size() != 0) arcTypeIndex = formatIndices[0]; if (arcTypeIndex >= 0) MethodMode.FormatIndex = arcTypeIndex; else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; if (!arcInfo.UpdateEnabled) return false; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } /* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) { return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); } */ static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArcItem> &arcItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CDirItems &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! // CUpdateProduceCallbackImp upCallback(&arcItems, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); } UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); // check it: defaultItemName !!! if (ai.Name.IsEmpty()) ai.Name = defaultItemName; RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); { CPropVariant prop; RINOK(archive->GetProperty(i, kpidSize, &prop)); ai.SizeDefined = (prop.vt != VT_EMPTY); if (ai.SizeDefined) ai.Size = ConvertPropVariantToUInt64(prop); } { CPropVariant prop; RINOK(archive->GetProperty(i, kpidTimeType, &prop)); if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; switch(ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: break; default: return E_FAIL; } } } ai.IndexInServer = i; arcItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArcItem> &arcItems, CDirItems &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, arcItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) { return Callback->ScanProgress(numFolders, numFiles, path); } }; #ifdef _WIN32 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( ULONG_PTR ulUIParam, LPSTR lpszDelimChar, LPSTR lpszFilePaths, LPSTR lpszFileNames, ULONG ulReserved ); typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; #endif HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CDirItems dirItems; if (options.StdInMode) { CDirItem di; di.Name = options.StdInFileName; di.Size = (UInt64)(Int64)-1; di.Attrib = 0; NTime::GetCurUtcFileTime(di.MTime); di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArcItem> arcItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, arcItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArcItems(0), UpdatePairs(0), NewNames(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); } */ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData != NULL) *newData = BoolToInt(up.NewData); if (newProps != NULL) *newProps = BoolToInt(up.NewProps); if (indexInArchive != NULL) { *indexInArchive = (UInt32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = up.IsAnti; prop.Detach(value); return S_OK; } if (up.IsAnti) { switch(propID) { case kpidIsDir: case kpidPath: break; case kpidSize: prop = (UInt64)0; prop.Detach(value); return S_OK; default: prop.Detach(value); return S_OK; } } if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; } } else { if (propID == kpidPath) { if (up.NewNameIndex >= 0) { prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } if (up.ExistInArchive() && Archive) { UInt32 indexInArchive; if (ArcItems == 0) indexInArchive = up.ArcIndex; else indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if (up.IsAnti) { return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); } const CDirItem &di = DirItems->Items[up.DirIndex]; RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); if (di.IsDir()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; const CDirItems *DirItems; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (ai.SizeDefined) if (di.Size != ai.Size) pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback) { for (int i = 0; i < updatePairs.Size(); i++) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); // cout << "deleting"; */ if (callback) callback->ShowDeleteFile(pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; up2.NewData = up2.NewProps = false; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; break; } operationChain.Add(up2); } operationChain.ReserveDown(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool IsAnti; int DirIndex; int ArcIndex; int NewNameIndex; bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback { virtual HRESULT ShowDeleteFile(int arcIndex) = 0; }; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; #endif UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "Windows/Error.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsDir, L"Folder" }, { kpidSize, L"Size" }, { kpidPackSize, L"Packed Size" }, { kpidAttrib, L"Attributes" }, { kpidCTime, L"Created" }, { kpidATime, L"Accessed" }, { kpidMTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubDirs, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" }, { kpidBit64, L"64-bit" }, { kpidBigEndian, L"Big-endian" }, { kpidCpu, L"CPU" }, { kpidPhySize, L"Physical Size" }, { kpidHeadersSize, L"Headers Size" }, { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, { kpidFreeSpace, L"Free Space" }, { kpidClusterSize, L"Cluster Size" } }; static const char kEmptyAttribChar = '.'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttribString(DWORD wa, bool isDir, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; wchar_t s[32]; ConvertUInt64ToString(propID, s); return s; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&prop.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidPath) { UString s; RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); prop = s; } else { RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (prop.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: prop = defaultItemName; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidMTime) { PrintTime(prop); } else if (fieldInfo.PropID == kpidAttrib) { if (prop.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = prop.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttribString(attributes, isFolder, s); g_StdOut << s; } else if (prop.vt == VT_BSTR) { if (techMode) g_StdOut << prop.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); } else { UString s = ConvertPropertyToString(prop, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant prop; if (archive->GetProperty(index, propID, &prop) != S_OK) throw "GetPropertyValue error"; if (prop.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(prop); return true; } HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) g_StdOut << "is not supported archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" #ifndef _NO_CRYPTO " -p{Password}: set Password\n" #endif " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) throw kUnsupportedArcTypeMessage; if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, formatIndices, options.ArchiveName)) throw kUnsupportedArcTypeMessage; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int MY_CDECL main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::Open_CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(Open_CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: INTERFACE_IOpenCallbackUI(;) CStdOutStream *OutStream; #ifndef _NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; UString Password; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) { return CheckBreak(); } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { #ifdef _NO_CRYPTO *passwordIsDefined = false; return StringToBstr(L"", password); #else if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif } /* HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) { // MT_LOCK if (StdOutMode) return S_OK; RINOK(Finilize()); m_PercentPrinter.PrintString("Deleting "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } */ ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), #ifndef _NO_CRYPTO PasswordIsDefined(false), AskPassword(false), #endif StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRenameAll = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/7zip/UI/Console/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DWIN_LONG_PATH \ -DEXTERNAL_LZMA \ -DEXTERNAL_CODECS \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Registry.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Threads.obj \ !include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !include "../../Crc.mak" ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Build.mak ================================================ !IFDEF CPU !IFNDEF NO_BUFFEROVERFLOWU LIBS = $(LIBS) bufferoverflowU.lib !ENDIF !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gr -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope !ELSE CFLAGS = $(CFLAGS) -W3 !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF -OPT:ICF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if (_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while (pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for (int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for (int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "MyWindows.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for (int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { public: BSTR m_str; CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memcpy(res, m_str, byteLen); return res; } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifndef _WIN32 #include <ctype.h> #endif #ifndef _UNICODE #include "StringConvert.h" #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while ((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); // int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if (realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if (newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if (_capacity > 0) { for (int i = 0; i < _length; i++) newBuffer[i] = _chars[i]; delete []_chars; } _chars = newBuffer; _chars[_length] = 0; _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if (minBufLength >= _capacity) SetCapacity(minBufLength); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if (newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if (&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for (int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for (int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } void CBaseRecordVector::ClearAndFree() { Clear(); delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta = 1; if (_capacity >= 64) delta = _capacity / 4; else if (_capacity >= 8) delta = 8; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { // if (newCapacity <= _capacity) if (newCapacity == _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = NULL; if (newSize > 0) { p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); memcpy(p, _items, _itemSize * numRecordsToMove); } delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::ReserveDown() { Reserve(_size); } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void ClearAndFree(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); void ReserveDown(); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector(): CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while (--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector() {}; ~CObjectVector() { Clear(); }; CObjectVector(const CObjectVector &v) { *this = v; } CObjectVector& operator=(const CObjectVector &v) { Clear(); return (*this += v); } CObjectVector& operator+=(const CObjectVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for (int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for (int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if (c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while ((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if (c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if (numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { int numRequiredBytes = s.Length() * 2; BOOL defUsed; int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); #ifndef _WIN32_WCE if (numChars == 0) throw 282229; #endif dest.ReleaseBuffer(numChars); } return dest; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { bool defaultCharWasUsed; return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if (!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if (!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; UInt32 v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { if (end != NULL) *end = s; return result; } result <<= 4; result |= v; s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H extern "C" { #include "../../C/Types.h" } typedef int HRes; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; int numAdds; if (srcPos == srcLen) { *destLen = destPos; return True; } c = (Byte)src[srcPos++]; if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xC0) break; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { Byte c2; if (srcPos == srcLen) break; c2 = (Byte)src[srcPos++]; if (c2 < 0x80 || c2 >= 0xC0) break; value <<= 6; value |= (c2 - 0x80); } while (--numAdds != 0); if (value < 0x10000) { if (dest) dest[destPos] = (wchar_t)value; destPos++; } else { value -= 0x10000; if (value >= 0x100000) break; if (dest) { dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); } destPos += 2; } } *destLen = destPos; return False; } static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { unsigned numAdds; UInt32 value; if (srcPos == srcLen) { *destLen = destPos; return True; } value = src[srcPos++]; if (value < 0x80) { if (dest) dest[destPos] = (char)value; destPos++; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00 || srcPos == srcLen) break; c2 = src[srcPos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; if (dest) dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); destPos++; do { numAdds--; if (dest) dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); destPos++; } while (numAdds != 0); } *destLen = destPos; return False; } bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src.Length()); wchar_t *p = dest.GetBuffer((int)destLen); Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; Utf16_To_Utf8(NULL, &destLen, src, src.Length()); char *p = dest.GetBuffer((int)destLen); Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if (CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if (!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for (int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if (string.IsEmpty()) { if (i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if (errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA fd; _handle = ::FindFirstFile(wildcard, &fd); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW fd; _handle = ::FindFirstFileW(wildcard, &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for (UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for (UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } }}} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); }}} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if (hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) { if (c != 0) *s++ = c; char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(0, st.wYear, s, 4); s = UIntToStringSpec('-', st.wMonth, s, 2); s = UIntToStringSpec('-', st.wDay, s, 2); if (includeTime) { s = UIntToStringSpec(' ', st.wHour, s, 2); s = UIntToStringSpec(':', st.wMinute, s, 2); if (includeSeconds) UIntToStringSpec(':', st.wSecond, s, 2); } return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &prop) { switch (prop.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return prop.bstrVal; case VT_UI1: return ConvertUInt64ToString(prop.bVal); case VT_UI2: return ConvertUInt64ToString(prop.uiVal); case VT_UI4: return ConvertUInt64ToString(prop.ulVal); case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); // case VT_I1: return ConvertInt64ToString(prop.cVal); case VT_I2: return ConvertInt64ToString(prop.iVal); case VT_I4: return ConvertInt64ToString(prop.lVal); case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) { switch (prop.vt) { case VT_UI1: return prop.bVal; case VT_UI2: return prop.uiVal; case VT_UI4: return prop.ulVal; case VT_UI8: return (UInt64)prop.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 operator HANDLE() { return thread.handle; } void Attach(HANDLE handle) { thread.handle = handle; } HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Time.cpp ================================================ // Windows/Time.cpp #include "StdAfx.h" #include "Time.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &fileTime)); } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { dosTime = (fileTime.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) { resSeconds = 0; if (year < 1601 || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; UInt32 numYears = year - 1601; UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += day - 1; resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } void GetCurUtcFileTime(FILETIME &ft) { SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); } }} ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); }} #endif ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/Methods.txt ================================================ 7-Zip method IDs (4.65) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - PPC (Big Endian) 03 - Alpha 01 - Alpha 04 - IA64 01 - IA64 05 - ARM 01 - ARM 06 - M68 05 - M68 (Big Endian) 07 - ARM Thumb 01 - ARMT 08 - SPARC 05 - SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-3.4-nb4/lzma465/lzma.txt ================================================ LZMA SDK 4.65 ------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK Contents ----------------- LZMA SDK includes: - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory C++/7zip/Compress/LZMA_Alone and call make to recompile it: make -f makefile.gcc clean all In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, you can use LIB = -lm -static Files --------------------- lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C/ - C files 7zCrc*.* - CRC code Alloc.* - Memory allocation functions Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code LzFind.* - Match finder for LZ (LZMA) encoders LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding LzHash.h - Additional file for LZ match finder LzmaDec.* - LZMA decoding LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). Archive - files related to archiving 7z - 7z ANSI-C Decoder CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + Types.h LzmaUtil/LzmaUtil.c is example application that uses these files. Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); For full code example, look at C/LzmaUtil/LzmaUtil.c code. How To compress data -------------------- Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Check C/LzmaUtil/LzmaUtil.c as example, When to use: file->file decompressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) LZMA Defines ------------ _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: operator new(size_t size) { void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } If you use MSCV that throws exception for "new" operator, you can compile without "NewHandler.cpp". So standard exception will be used. Actually some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-3.4-nb4/mksquashfs ================================================ #!/bin/bash ./mksquashfs-lzma -nolzma $@ ================================================ FILE: src/others/squashfs-3.4-nb4/sqlzma.h ================================================ /* * Copyright (C) 2006-2008 Junjiro Okajima * Copyright (C) 2006-2008 Tomas Matejicek, slax.org * * LICENSE follows the described one in lzma. */ /* $Id: sqlzma.h,v 1.20 2008-03-12 16:58:34 jro Exp $ */ #ifndef __sqlzma_h__ #define __sqlzma_h__ #ifndef __KERNEL__ #include <stdlib.h> #include <string.h> #include <zlib.h> #ifdef _REENTRANT #include <pthread.h> #endif #else #include <linux/zlib.h> #endif #define _7ZIP_BYTE_DEFINED #define LZMA_VERSION "4.65" /* * detect the compression method automatically by the first byte of compressed * data. * according to rfc1950, the first byte of zlib compression must be 0x?8. */ #define is_lzma(c) (c == 0x5d) /* ---------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif #ifndef __KERNEL__ /* for mksquashfs only */ struct sqlzma_opts { unsigned int try_lzma; unsigned int dicsize; }; int sqlzma_cm(struct sqlzma_opts *opts, z_stream *stream, Bytef *next_in, uInt avail_in, Bytef *next_out, uInt avail_out); #endif /* ---------------------------------------------------------------------- */ /* * Three patterns for sqlzma uncompression. very dirty code. * - kernel space (squashfs kernel module) * - user space with pthread (mksquashfs) * - user space without pthread (unsquashfs) */ struct sized_buf { unsigned int sz; unsigned char *buf; }; enum {SQUN_PROB, SQUN_RESULT, SQUN_LAST}; struct sqlzma_un { int un_lzma; struct sized_buf un_a[SQUN_LAST]; unsigned char un_prob[31960]; /* unlzma 64KB - 1MB */ z_stream un_stream; #define un_cmbuf un_stream.next_in #define un_cmlen un_stream.avail_in #define un_resbuf un_stream.next_out #define un_resroom un_stream.avail_out #define un_reslen un_stream.total_out }; int sqlzma_init(struct sqlzma_un *un, int do_lzma, unsigned int res_sz); int sqlzma_un(struct sqlzma_un *un, struct sized_buf *src, struct sized_buf *dst); void sqlzma_fin(struct sqlzma_un *un); /* ---------------------------------------------------------------------- */ #ifdef __cplusplus }; #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/sqmagic.h ================================================ /* * Copyright (C) 2006 Junjiro Okajima * Copyright (C) 2006 Tomas Matejicek, slax.org * * LICENSE must follow the one in squashfs. */ /* $Id: sqmagic.h,v 1.2 2006-11-27 03:54:58 jro Exp $ */ #ifndef __sqmagic_h__ #define __sqmagic_h__ /* see SQUASHFS_MAGIC in squashfs_fs.h */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 #endif ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/ACKNOWLEDGEMENTS ================================================ ACKNOWLEDGEMENTS Thanks to everyone who have download squashfs. I appreciate people using it, and any feedback you have. The following have provided useful feedback, which has guided some of the extra features in squashfs. This is a randomly ordered (roughly in chronological order) list, which is updated when I remember... Acknowledgements for Squashfs-3.3 ------------------------------------ Peter Korsgaard and others sent patches updating Squashfs to changes in the VFS interface for 2.6.22/2.6.23/2.6.24-rc1. Peter also sent some small patches for the Squashfs kernel code. Vito Di Leo sent a patch extending Mksquashfs to support regex filters. While his patched worked, it unfortunately made it easy to make Mksquashfs perform unpredictably with poorly choosen regex expressions. It, however, encouraged myself to add support for wildcard pattern matching and regex filters in a different way. Acknowledgements for Squashfs-3.2-r2 ------------------------------------ Junjiro Okajima discovered a couple of SMP issues, thanks. Junjiro Okajima and Tomas Matejicek have produced some good LZMA patches for Squashfs. Acknowledgements for Squashfs-3.2 --------------------------------- Peter Korsgaard sent a patch updating Squashfs to changes in the VFS interface in Linux 2.6.20. Acknowledgements for Squashfs-3.1 --------------------------------- Kenneth Duda and Ed Swierk of Arastra Inc. identified numerous bugs with Squashfs, and provided patches which were the basis for some of the fixes. In particular they identified the fragment rounding bug, the NFS bug, the initrd bug, and helped identify the 4K stack overflow bug. Scott James Remnant (Ubuntu) also identified the fragment rounding bug, and he also provided a patch. Ming Zhang identified the Lseek bug in Mksquashfs. His tests on the performance of Mksquashfs on SMP systems encouraged the rewrite of Mksquashfs. Peter Korsgaard, Daniel Olivera and Zilvinas Valinskas noticed Squashfs 3.0 didn't compile on Linux-2.6.18-rc[1-4] due to changes in the Linux VFS interfaces, and provided patches. Tomas Matejicek (SLAX) suggested the -force option on Unsquashfs, and noticed Unsquashfs didn't return the correct exit status. Yann Le Doare reported a kernel oops and provided a Qemu image that led to the identification of the simultaneously accessing multiply mounted Squashfs filesystems bug. Older acknowledgements ---------------------- Mark Robson - pointed out early on that initrds didn't work Adam Warner - pointed out that greater than 2GB filesystems didn't work. John Sutton - raised the problem when archiving the entire filesystem (/) there was no way to prevent /proc being archived. This prompted exclude files. Martin Mueller (LinuxTV) - noticed that the filesystem length in the superblock doesn't match the output filesystem length. This is due to padding to a 4K boundary. This prompted the addition of the -nopad option. He also reported a problem where 32K block filesystems hung when used as initrds. Arkadiusz Patyk (Polish Linux Distribution - PLD) reported a problem where 32K block filesystems hung when used as a root filesystem mounted as a loopback device. Joe Blow emailed me that I'd forgotten to put anything in the README about mounting the squashfs filesystem. David Fox (Lindows) noticed that the exit codes returned by Mksquashfs were wrong. He also noticed that a lot of time was spent in the duplicate scan routine. Cameron Rich complained that Squashfs did not support FIFOs or sockets. Steve Chadsey and Thomas Weissmuller noticed that files larger than the available memory could not be compressed by Mksquashfs. "Ptwahyu" and "Hoan" (I have no full names and I don't like giving people's email addresses), noticed that Mksquashfs 1.3 SEGV'd occasionally. Even though I had already noticed this bug, it is useful to be informed by other people. Don Elwell, Murray Jensen and Cameron Rich, have all sent in patches. Thanks, I have not had time to do anything about them yet... Drew Scott Daniels has been a good advocate for Squashfs. Erik Andersen has made some nice suggestions, unfortunately, I have not had time to implement anything. Artemiy I. Pavlov has written a useful LDP mini-howto for Squashfs (http://linuxdoc.artemio.net/squashfs). Yves Combe reported the Apple G5 bug, when using Squashfs for his PPC Knoppix-mib livecd project. Jaco Greeff (mklivecd project, and maintainer of the Mandrake squashfs-tools package) suggested the new mksquashfs -ef option, and the standalone build for mksquashfs. Mike Schaudies made a donation. Arkadiusz Patyk from the Polish Linux Distribution reported that Squashfs didn't work on amd64 machines. He gave me an account on a PLD amd64 machine which allowed myself to track down these bugs. Miles Roper, Peter Kjellerstedt and Willy Tarreau reported that release 2.1 did not compile with gcc < 3.x. Marcel J.E. Mol reported lack of kernel memory issues when using Squashfs on small memory embedded systems. This prompted the addition of the embedded system kernel configuration options. Era Scarecrow noticed that Mksquashfs had not been updated to reflect that smaller than 4K blocks are no longer supported. Kenichi Shima reported the Kconfig file had not been updated to 2.2. Aaron Ten Clay made a donation! Tomas Matejicek (SLAX) made a donation! ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/CHANGES ================================================ SQUASHFS CHANGE LOG 3.4 26 AUG 2008 Performance improvements to Unsquashfs, Mksquashfs and the kernel code. Plus many small bug fixes. 1. Kernel code improvements: 1.1 Internal Squashfs kernel metadata and fragment cache implementations have been merged and optimised. Spinlocks are now used, locks are held for smaller periods and wakeups have been minimised. Small race condition fixed where if two or more processes tried to read the same cache block simultaneously they would both read and decompress it. 10-20%+ speed improvement has been seen on tests. 1.2 NFS export code rewritten following VFS changes in linux-2.6.24. 1.3 New patches for linux-2.6.25, linux-2.6.26, and linux-2.6.27. Fixed patch for linux-2.6.24. 1.4 Fixed small buffer_head leak in squashfs_read_data when handling badly corrupted filesystems. 1.5 Fixed bug in get_dir_index_using_offset. 2. Unsquashfs improvements: 2.1 Unsquashfs has been parallelised. Filesystem reading, writing and decompression is now multi-threaded. Up to 40% speed improvement seen on tests. 2.2 Unsquashfs now has a progress bar. Use -no-progress to disable it. 2.3 Fixed small bug where unistd.h wasn't being included on some distributions, leading to lseek being used rather than lseek64 - which meant on these distributions Unsquashfs couldn't unsquash filesystems larger than 4GB. 3. Mksquashfs improvements: 3.1 Removed some small remaining parallelisation bottlenecks. Depending on source filesystem, up to 10%+ speed improvement. 3.2 Progress bar improved, and moved to separate thread. 3.3 Sparse file handling bug in Mksquashfs 3.3 fixed. 3.4 Two rare appending restore bugs fixed (when ^C hit twice). 3.3 1 NOV 2007 Increase in block size, sparse file support, Mksquashfs and Unsquashfs extended to use pattern matching in exclude/extract files, plus many more improvements and bug fixes. 1. Filesystem improvements: 1.1. Maximum block size has been increased to 1Mbyte, and the default block size has been increased to 128 Kbytes. This improves compression. 1.2. Sparse files are now supported. Sparse files are files which have large areas of unallocated data commonly called holes. These files are now detected by Squashfs and stored more efficiently. This improves compression and read performance for sparse files. 2. Mksquashfs improvements: 2.1. Exclude files have been extended to use wildcard pattern matching and regular expressions. Support has also been added for non-anchored excludes, which means it is now possible to specify excludes which match anywhere in the filesystem (i.e. leaf files), rather than always having to specify exclude files starting from the root directory (anchored excludes). 2.2. Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). 3. Unsquashfs improvements: 3.1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. 3.2. Extract files have been extended to use wildcard pattern matching and regular expressions. 3.3. Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). 3.4. A -stat option has been added which displays the filesystem superblock information. 3.5. Unsquashfs now supports 1.x filesystems. 4. Miscellaneous improvements/bug fixes: 4.1. Squashfs kernel code improved to use SetPageError in squashfs_readpage() if I/O error occurs. 4.2. Fixed Squashfs kernel code bug preventing file seeking beyond 2GB. 4.3. Mksquashfs now detects file size changes between first phase directory scan and second phase filesystem create. It also deals better with file I/O errors. 3.2-r2 15 JAN 2007 Kernel patch update and progress bar bug fix 1. Kernel patches 2.6.19/2.6.20 have been updated to use const structures and mutexes rather than older semaphores. 2. Minor SMP bug fixes. 3. Progress bar broken on x86-64. Fixed. 3.2 2 JAN 2007 NFS support, improvements to the Squashfs-tools, major bug fixes, lots of small improvements/bug fixes, and new kernel patches. Improvements: 1. Squashfs filesystems can now be exported via NFS. 2. Unsquashfs now supports 2.x filesystems. 3. Mksquashfs now displays a progress bar. 4. Squashfs kernel code has been hardened against accidently or maliciously corrupted Squashfs filesystems. Bug fixes: 5. Race condition occurring on S390 in readpage() fixed. 6. Odd behaviour of MIPS memcpy in read_data() routine worked-around. 7. Missing cache_flush in Squashfs symlink_readpage() added. 3.1-r2 30 AUG 2006 Mksquashfs -sort bug fix A code optimisation after testing unfortunately broke sorting in Mksquashfs. This has been fixed. 3.1 19 AUG 2006 This release has some major improvements to the squashfs-tools, a couple of major bug fixes, lots of small improvements/bug fixes, and new kernel patches. 1. Mksquashfs has been rewritten to be multi-threaded. It has the following improvements 1.1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 1.2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 1.3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 1.4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 1.5 The use of swap memory was found to significantly impact performance. The amount of memory used to cache files is now a command line option, by default this is 512 Mbytes. 2. Unsquashfs has the following improvements 2.1 Unsquashfs now allows you to specify the filename or the directory within the Squashfs filesystem that is to be extracted, rather than always extracting the entire filesystem. 2.2 A new -force option has been added which forces Unsquashfs to output to the destination directory even if files and directories already exist in the destination directory. This allows you to update an already existing directory tree, or to Unsquashfs to a partially filled directory tree. Without the -force option Unsquashfs will refuse to output. 3. The following major bug fixes have been made 3.1 A fragment table rounding bug has been fixed in Mksquashfs. Previously if the number of fragments in the filesystem were a multiple of 512, Mksquashfs would generate an incorrect filesystem. 3.2 A rare SMP bug which occurred when simultaneously acccessing multiply mounted Squashfs filesystems has been fixed. 4. Miscellaneous improvements/bug fixes 4.1 Kernel code stack usage has been reduced. This is to ensure Squashfs works with 4K stacks. 4.2 Readdir (Squashfs kernel code) has been fixed to always return 0, rather than the number of directories read. Squashfs should now interact better with NFS. 4.3 Lseek bug in Mksquashfs when appending to larger than 4GB filesystems fixed. 4.4 Squashfs 2.x initrds can now been mounted. 4.5 Unsquashfs exit status fixed. 4.6 New patches for linux-2.6.18 and linux-2.4.33. 3.0 15 MAR 2006 Major filesystem improvements 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). 2.2-r2 8 SEPT 2005 Second release of 2.2, this release fixes a couple of small bugs, a couple of small documentation mistakes, and adds a patch for kernel 2.6.13. 1. Mksquashfs now deletes the output filesystem image file if an error occurs whilst generating the filesystem. Previously on error the image file was left empty or partially written. 2. Updated mksquashfs so that it doesn't allow you to generate filesystems with block sizes smaller than 4K. Squashfs hasn't supported block sizes less than 4K since 2.0-alpha. 3. Mksquashfs now ignores missing files/directories in sort files. This was the original behaviour before 2.2. 4. Fixed small mistake in fs/Kconfig where the version was still listed as 2.0. 5. Updated ACKNOWLEDGEMENTS file. 2.2 3 JUL 2005 This release has some small improvements, bug fixes and patches for new kernels. 1. Sort routine re-worked and debugged from release 2.1. It now allows you to give Mkisofs style sort files and checks for filenames that don't match anything. Sort priority has also been changed to conform to Mkisofs usage, highest priority files are now placed at the start of the filesystem (this means they will be on the inside of a CD or DVD). 2. New Configure options for embedded systems (memory constrained systems). See INSTALL file for further details. 3. Directory index bug fixed where chars were treated as signed on some architectures. A file would not be found in the rare case that the filename started with a chracter greater than 127. 4. Bug introduced into the read_data() routine when sped up to use data block queueing fixed. If the second or later block resulted in an I/O error this was not checked. 5. Append bug introduced in 2.1 fixed. The code to compute the new compressed and uncompressed directory parts after appending was wrong. 6. Metadata block length read routine altered to not perform a misaligned short read. This was to fix reading on an ARM7 running uCLinux without a misaligned read interrupt handler. 7. Checkdata bug introduced in 2.1 fixed. 2.1-r2 15 DEC 2004 Code changed so it can be compiled with gcc 2.x 1. In some of the code added for release 2.1 I unknowingly used some gcc extensions only supported by 3.x compilers. I have received a couple of reports that the 2.1 release doesn't build on 2.x and so people are clearly still using gcc 2.x. The code has been rewritten to remove these extensions. 2.1 10 DEC 2004 Significantly improved directory handling plus numerous other smaller improvements 1. Fast indexed directories implemented. These speed up directory operations (ls, file lookup etc.) significantly for directories larger than 8 KB. 2. All directories are now sorted in alphabetical order. This again speeds up directory operations, and in some cases it also results in a small compression improvement (greater data similarity between files with alphabetically similar names). 3. Maximum directory size increased from 512 KB to 128 MB. 4. Duplicate fragment checking and appending optimised in mksquashfs, depending on filesystem, this is now up to 25% faster. 5. Mksquashfs help information reformatted and reorganised. 6. The Squashfs version and release date is now printed at kernel boot-time or module insertion. This addition will hopefully help to reduce the growing problem where the Squashfs version supported by a kernel is unknown and the kernel source is unavailable. 7. New PERFORMANCE.README file. 8. New -2.0 mksquashfs option. 9. CHANGES file reorganised. 10. README file reorganised, clarified and updated to include the 2.0 mksquashfs options. 11. New patch for Linux 2.6.9. 12. New patch for Linux 2.4.28. 2.0r2 29 AUG 2004 Workaround for kernel bug in kernels 2.6.8 and newer added 1. New patch for kernel 2.6.8.1. This includes a workaround for a kernel bug introduced in 2.6.7bk14, which is present in all later versions of the kernel. If you're using a 2.6.8 kernel or later then you must use this 2.6.8.1 patch. If you've experienced hangs or oopses using Squashfs with a 2.6.8 or later kernel then you've hit this bug, and this patch will fix it. It is worth mentioning that this kernel bug potentially affects other filesystems. If you receive odd results with other filesystems you may be experiencing this bug with that filesystem. I submitted a patch but this has not yet gone into the kernel, hopefully the bug will be fixed in later kernels. 2.0 13 JULY 2004 A couple of new options, and some bug fixes 1. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 2. Initrds are now supported for kernels 2.6.x. 3. amd64 bug fixes. If you use an amd64, please read the README-AMD64 file. 4. Check-data and gid bug fixes. With 2.0-alpha when mounting 1.x filesystems in certain cases file gids were corrupted. 5. New patch for Linux 2.6.7. 2.0-ALPHA 21 MAY 2004 Filesystem changes and compression improvements 1. Squashfs 2.0 has added the concept of fragment blocks. Files smaller than the file block size and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K (in the ALPHA version of Squashfs 2.0). 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 6. Numerous small bug fixes have been made. 1.3r3 18 JAN 2004 Third release of 1.3, this adds a new mksquashfs option, some bug fixes, and extra patches for new kernels 1. New mksquashfs -ef exclude option. This option reads the exclude dirs/files from an exclude file, one exclude dir/file per line. This avoids the command line size limit when using the -e exclude option, 2. When appending to existing filesystems, if mksquashfs experiences a fatal error (e.g. out of space when adding to the destination), the original filesystem is restored, 3. Mksquashfs now builds standalone, without the kernel needing to be patched. 4. Bug fix in the kernel squashfs filesystem, where the pages being filled were not kmapped. This seems to only have caused problems on an Apple G5, 5. New patch for Linux 2.4.24, 6. New patch for Linux 2.6.1, this replaces the patch for 2.6.0-test7. 1.3r2 14 OCT 2003 Second release of 1.3, bug fixes and extra patches for new kernels 1. Bug fix in routine that adds files to the filesystem being generated in mksquashfs. This bug was introduced in 1.3 (not enough testing...) when I rewrote it to handle files larger than available memory. This bug caused a SEGV, so if you've ever got that, it is now fixed, 2. Long running bug where ls -s and du reported wrong block size fixed. I'm pretty sure this used to work many kernel versions ago (2.4.7) but it broke somewhere along the line since then, 3. New patch for Linux 2.4.22, 4. New patch for 2.6.0-test7, this replaces the patch for 2.6.0-test1. 1.3 29 JUL 2003 FIFO/Socket support added plus optimisations and improvements 1. FIFOs and Socket inodes are now supported, 2. Mksquashfs can now compress files larger than available memory, 3. File duplicate check routine optimised, 4. Exit codes fixed in Mksquashfs, 5. Patch for Linux 2.4.21, 6. Patch for Linux 2.6.0-test1. Hopefully, this will work for the next few releases of 2.6.0-testx, otherwise, I'll be releasing a lot of updates to the 2.6.0 patch... 1.2 13 MAR 2003 Append feature and new mksquashfs options added Mksquashfs can now add to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. See the README file for usage changes. 1.1b 16 JAN 2003 Bug fix release Fixed readpage deadlock bug. This was a rare deadlock bug that happened when pushing pages into the page cache when using greater than 4K blocks. I never got this bug when I tested the filesystem, but two people emailed me on the same day about the problem! I fixed it by using a page cache function that wasn't there when I originally did the work, which was nice :-) 1.1 8 JAN 2003 Added features 1. Kernel squashfs can now mount different byte order filesystems. 2. Additional features added to mksquashfs. Mksquashfs now supports exclude files and multiple source files/directories can be specified. A nopad option has also been added, which informs mksquashfs not to pad filesystems to a multiple of 4K. See README for mksquashfs usage changes. 3. Greater than 2GB filesystems bug fix. Filesystems greater than 2GB can now be created. 1.0c 14 NOV 2002 Bug fix release Fixed bugs with initrds and device nodes 1.0 23 OCT 2002 Initial release ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) 19yy <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/INSTALL ================================================ INSTALLING SQUASHFS The squashfs3.4.tar.gz file contains the kernel-patches directory containing the squashfs patches, and the squashfs-tools directory containing mksquashfs and unsquashfs. 1. Patching the kernel ---------------------- There are twelve kernel patch directories depending on your linux kernel version. If your kernel version isn't there then try the patch for the nearest kernel. To patch your kernel, cd into the top level directory, and run the "patch" command, e.g. assuming linux-2.6.22 %cd /usr/src/linux-2.6.22 %patch -p1 < location-of-squashfs/kernel-patches/linux-2.6.22/squashfs3.4-patch Where "location-of-squashfs" is the path to the squashfs3.4 source directory. The squashfs patches patch the relevant kernel files to add configure support, initrd support, include files, and the squashfs directory under linux/fs/. Once patched, the kernel must be reconfigured, with squashfs support turned on (either Y/M) to ensure that inflate support is built into the kernel. The squashfs kernel option can be found in the miscellaneous filesystems submenu near the bottom of the filesystems submenu. There are a set of options which are intended for use by embedded systems with low memory. At the "Additional option for memory-constrained systems" prompt, please say NO unless you're using an embedded system! Saying Y here allows you to specify cache sizes. The "Number of fragments cached" prompt allows the number of fragments cached to be controlled. By default SquashFS caches the last 3 fragments read from the filesystem. Increasing this amount may mean SquashFS has to re-read fragments less often from disk, at the expense of extra system memory. Decreasing this amount will mean SquashFS uses less memory at the expense of extra reads from disk. Note there must be at least one cached fragment. Anything much more than three will probably not make much difference. 2. Building squashfs tools -------------------------- The squashfs-tools directory contains the mksquashfs and unsquashfs programs. These can be made by typing make. The source files use a local copy of squashfs_fs.h (included in the kernel patches) allowing the tools to be made without needing to patch the kernel. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-2.0 ================================================ NOTE: This the original README for version 2.0. It is retained as it contains information about the fragment design. A description of the new 2.0 mksquashfs options has been added to the main README file, and that file should now be consulted for these. SQUASHFS 2.0 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to the final release of Squashfs version 2.0! A lot of changes to the filesystem have been made under the bonnet (hood). Squashfs 2.0 uses fragment blocks and larger blocks (64K) to improve compression ratio by about 5 - 20% over Squashfs 1.0 depending on the files being compressed. Using fragment blocks allows Squashfs 2.0 to achieve better compression than cloop and similar compression to tgz files while retaining the I/O efficiency of a compressed filesystem. Detailed changes: 1. Squashfs 2.0 has added the concept of fragment blocks (see later discussion). Files smaller than the file block size (64K in Squashfs 2.0) and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K. 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 6. Initrds are now supported for kernels 2.6.x. 7. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 8. AMD64, check-data and gid bug fixes. 9. Numerous small bug fixes have been made. 10. New patch for Linux 2.6.7. New Squashfs 2.0 options ------------------------ -noF or -noFragmentCompression Do not compress the fragments. Added for compatibility with noI and noD, probably not that useful. -no-fragments Do not use fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. -always-use-fragments By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. -no-duplicates Do not detect duplicate files. -all-root -root-owned These options (both do exactly the same thing), force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. -force-uid uid This option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. -force-gid gid This option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. Compression improvements example -------------------------------- The following is the compression results obtained compressing the 2.6.6 linux kernel source using CRAMFS, Cloop (with iso filesystem), Squashfs 1.3 and Squashfs 2.0 (results generated using big-endian filesystems). In decreasing order of size: CRAMFS 62791680 bytes (59.9M) Squashfs 1.x 51351552 bytes (48.9M) Cloop 46118681 bytes (44.0M) Squashfs 2.0 45604854 bytes (43.5M) The Squashfs 1.x filesystem is 12.6% larger than the new 2.0 filesystem. The cloop filesystem is 1.1% larger than the Squashfs 2.0 filesystem. Fragment blocks in Squashfs 2.0 ------------------------------- Squashfs like all other compressed filesystems compresses files individually on a block by block basis. This is performed to allow mounting and de-compression of files on a block by block basis without requiring the entire filesystem to be decompressed. This is in contrast to data-based compression schemes which compress without understanding the underlying filesystem (i.e. cloop and tgz files) and which, therefore, do not compress files individually. Each approach has advantages and disadvantages, data-based systems have better compression because compression is always performed at the maximum block size (64K in cloop) irrespective of the size of each file (which could be less than the block size). Compressed filesystems tend to be faster at I/O because they understand the filesystem and therefore employ better caching stategies and read less un-needed data from the filesystem. Fragment blocks in Squashfs 2.0 solves this problem by packing files (and optionally the ends of files) which are smaller than the block size into shared blocks, which are compressed together. For example five files each of 10K will be packed into one shared fragment of 50K and compressed together, rather than being compressed in five 10K blocks. This scheme produces a hybrid filesystem, retaining the I/O efficiency of a compressed filesystem, while obtaining the compression efficiency of data-based schemes by compressing small files together. Squashfs 1.x and Squashfs 2.0 compatibility ------------------------------------------- Appending to Squashfs 1.x filesystems is not supported. If you wish to append to 1.x filesystems, then either use the original mksquashfs, or convert them to Squashfs 2.0 by mounting the filesystem and running the 2.0 mksquashfs on the mounted filesystem. Mounting Squashfs 1.x filesystems IS supported by the 2.0 kernel patch. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-2.1 ================================================ SQUASHFS 2.1 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to Squashfs version 2.1-r2. Squashfs 2.1 introduces indexed directories which considerably speed up directory lookup (ls, find etc.) for directories which are greater than 8K in size. All directories are now also sorted alphabetically which further speeds up directory lookup. Many smaller improvements have also been made to this release, please see the CHANGES file entry for detailed changes. 1. DIRECTORY SPEED IMPROVEMENT EXAMPLES --------------------------------------- To give an indication of the directory speed improvements a number of test results are shown here. There is in addition a new PERFORMANCE.README file which gives details of I/O and lookup performance for Squashfs 2.1 against the Zisofs, Cloop and CRAMFS filesystems. example 1: Filesystems generated from a single directory of 72,784 files (2.6 MB directory size). Each file is 10 bytes in size (the test is directory lookup and so the file size isn't an issue). The ext3 uncompressed directory size is 288 MB (presumably because of one file per block). Zisofs compressed size 153.50 MB Cloop (isofs) compressed size 1.74 MB Squashfs2.1 compressed size 612 KB (0.60 MB) Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 35 minutes 7.895 seconds (User 7.868 secs, Sys 34 mins 5.621 secs) Cloop 35 minutes 12.765 seconds (User 7.771 secs, Sys 34 mins 3.869 secs) Squashfs2.1 19 seconds (User 5.119 secs, Sys 14.547 secs) example 2: Filesystems were generated from the Ubuntu Warty livecd (original uncompressed size on ext3 is 1.4 GB). Zisofs compressed size 589.81 MB Cloop (isofs) compressed size 471.19 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 49.875 seconds (User time 2.589 secs, Sys 11.194 secs) Cloop 20.797 seconds (User time 2.706 secs, Sys 13.496 secs) Squashfs2.0 16.556 seconds (User time 2.424 secs, Sys 10.371 secs) Squashfs2.1 10.143 seconds (User time 2.475 secs, Sys 4.440 secs) NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 2. NEW MKSQUASHFS OPTIONS ------------------------- There is only one extra option "-2.0". This tells mksquashfs to generate a filesystem which is mountable with Squashfs version 2.0. 3. APPENDING AND MOUNTING SQUASHFS 2.0 FILESYSTEMS -------------------------------------------------- Mounting 2.0 filesystems is supported by Squashfs 2.1. In addition mksquashfs v2.1 can append to 2.0 filesystems, although the generated filesystem will still be a 2.0 filesystem. 4. DONATIONS ------------ If you find Squashfs useful then please consider making a donation, particularly if you use Squashfs in a commercial product. Please consider giving something back especially if you're making money from it. Off the Squashfs subject somewhat I'm currently looking for another job doing Linux kernel or filesystems work. If you know of any such work that can be performed from the UK then please get in touch. Thanks. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-3.0 ================================================ SQUASHFS 3.0 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to the first release of Squashfs version 3.0. Squashfs 3.0 has the the following improvements to 2.x. 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). There is a new Unsquashfs utility (in squashfs-tools) than can be used to decompress a filesystem without mounting it. Squashfs 3.0 supports 2.x filesystems. Support for 1.x filesystems will be added in the future. 1. UNSQUASHFS ------------- Unsquashfs has the following options: SYNTAX: unsquashfs [-ls | -dest] filesystem -version print version, licence and copyright information -info print files as they are unsquashed -ls list filesystem only -dest <pathname> unsquash to <pathname>, default "squashfs-root" The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. Unsquashfs can decompress 3.0 filesystems. Support for 2.x and 1.x filesystems will be added in the future. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-3.1 ================================================ SQUASHFS 3.1 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.1-r2. Squashfs 3.1 has major improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- Mksquashfs has been rewritten and it is now multi-threaded. It offers the following improvements: 1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 5. The use of swap memory was found to significantly impact performance. The amount of memory used to cache the file is now a command line option, by default this is 512 Mbytes. 1.1 NEW COMMAND LINE OPTIONS ---------------------------- The new Mksquashfs program has a couple of extra command line options which can be used to control the new features: -processors <processors> This specifies the number of processors used by Mksquashfs. By default this is the number of available processors. -read_queue <size in Mbytes> This specifies the size of the file input queue used by the reader thread. This defaults to 64 Mbytes. -write_queue <size in Mbytes> This specifies the size of the filesystem output queue used by the writer thread. It also specifies the maximum cache used in file duplicate detection (the output queue is shared between these tasks). This defaults to 512 Mbytes. 1.2 PERFORMANCE RESULTS ----------------------- The following results give an indication of the speed improvements. Two example filesystems were tested, a liveCD filesystem (about 1.8 Gbytes uncompressed), and my home directory consisting largely of text files (about 1.3 Gbytes uncompressed). Tests were run on a single core and a dual core system. Dual Core (AMDx2 3800+) system: Source directories on ext3. LiveCD, old mksquashfs: real 11m48.401s user 9m27.056s sys 0m15.281s LiveCD, new par_mksquashfs: real 4m8.736s user 7m11.771s sys 0m27.749s "Home", old mksquashfs: real 4m34.360s user 3m54.007s sys 0m32.155s "Home", new par_mksquashfs: real 1m27.381s user 2m7.304s sys 0m17.234s Single Core PowerBook (PowerPC G4 1.5 GHz Ubuntu Linux) Source directories on ext3. LiveCD, old mksquashs: real 11m38.472s user 9m6.137s sys 0m23.799s LiveCD, par_mksquashfs: real 10m5.572s user 8m59.921s sys 0m16.145s "Home", old mksquashfs: real 3m42.298s user 2m49.478s sys 0m13.675s "Home", new par_mksquashfs: real 3m9.178s user 2m50.699s sys 0m9.069s I'll be interested in any performance results obtained, especially from SMP machines larger than my dual-core AMD box, as this will give an indication of the scalability of the code. Obviously, I'm also interested in any problems, deadlocks, low performance etc. 2. UNSQUASHFS ------------- Unsquashfs now allows you to specify the filename or directory that is to be extracted from the Squashfs filesystem, rather than always extracting the entire filesystem. It also has a new "-force" option, and all options can be specified in a short form (-i rather than -info). The Unsquashfs usage info is now: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The new "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-3.2 ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Squashfs 3.2 has support for NFS exporting, some improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- New command line options: -no-exports Squashfs now supports NFS exports. By default the additional information necessary is added to the filesystem by Mksquashfs. If you do not wish this extra information, then this option can be specified. This will save a couple of bytes per file, and the filesystem will be identical to Squashfs 3.1. -no-progress Mksquashfs by default now displays a progress bar. This option disables it. 2. UNSQUASHFS ------------- Unsquashfs now supports Squashfs 2.x filesystems. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-3.3 ================================================ SQUASHFS 3.3 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to another release of Squashfs. This is the 22nd release in just over five years of work. Squashfs 3.3 has lots of nice improvements, both to the filesystem itself (bigger blocks, and sparse files), but also to the Squashfs-tools Mksquashfs and Unsquashfs. As usual the CHANGES file has a detailed list of all the improvements. Following is a description of the changes to the Squashfs tools, usage guides to the new options, and a summary of the new options. 1. MKSQUASHFS - EXTENDED EXCLUDE FILE HANDLING ---------------------------------------------- 1. Extended wildcard pattern matching now supported in exclude files Enabled by specifying -wildcards option Supports both anchored and non-anchored exclude files. 1.1 Anchored excludes Similar to existing exclude files except with wildcards. Exclude file matches from root of source directories. Examples: 1. mksquashfs example image.sqsh -wildcards -e 'test/*.gz' Exclude all files matching "*.gz" in the top level directory "test". 2. mksquashfs example image.sqsh -wildcards -e '*/[Tt]est/example*' Exclude all files beginning with "example" inside directories called "Test" or "test", that occur inside any top level directory. Using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e 'test/!(*data*).gz' Exclude all files matching "*.gz" in top level directory "test", except those with "data" in the name. 1.2 Non-anchored excludes By default excludes match from the top level directory, but it is often useful to exclude a file matching anywhere in the source directories. For this non-anchored excludes can be used, specified by pre-fixing the exclude with "...". Examples: 1. mksquashfs example image.sqsh -wildcards -e '... *.gz' Exclude files matching "*.gz" anywhere in the source directories. For example this will match "example.gz", "test/example.gz", and "test/test/example.gz". 2. mksquashfs example image.sqsh -wildcards -e '... [Tt]est/*.gz' Exclude files matching "*.gz" inside directories called "Test" or "test" that occur anywhere in the source directories. Again, using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e '... !(*data*).gz' Exclude all files matching "*.gz" anywhere in the source directories, except those with "data" in the name. 2. Regular expression pattern matching now supported in exclude files Enabled by specifying -regex option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. Supports both anchored and non-anchored exclude files. 2. MKSQUASHFS - NEW RECOVERY FILE FEATURE ----------------------------------------- Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). The recovery files are called squashfs_recovery_xxx_yyy, where "xxx" is the name of the filesystem being appended to, and "yyy" is a number to guarantee filename uniqueness (the PID of the parent Mksquashfs process). Normally if Mksquashfs exits correctly the recovery file is deleted to avoid cluttering the filesystem. If Mksquashfs aborts, the "-recover" option can be used to recover the filesystem, giving the previously created recovery file as a parameter, i.e. mksquashfs dummy image.sqsh -recover squashfs_recovery_image.sqsh_1234 The writing of the recovery file can be disabled by specifying the "-no-recovery" option. 3. UNSQUASHFS - EXTENDED EXTRACT FILE HANDLING ---------------------------------------------- 1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. To specify a file containing the extract files use the "-e[f]" option. 2. Extended wildcard pattern matching now supported in extract files Enabled by default. Similar to existing extract files except with wildcards. Examples: 1. unsquashfs image.sqsh 'test/*.gz' Extract all files matching "*.gz" in the top level directory "test". 2. unsquashfs image.sqsh '[Tt]est/example*' Extract all files beginning with "example" inside top level directories called "Test" or "test". Using extended wildcards, negative matching is also possible. 3. unsquashfs image.sqsh 'test/!(*data*).gz' Extract all files matching "*.gz" in top level directory "test", except those with "data" in the name. 3. Regular expression pattern matching now supported in extract files Enabled by specifying -r[egex] option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. 4. UNSQUASHFS - EXTENDED FILENAME PRINTING ------------------------------------------ Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). New options: -ll[s] list filesystem with file attributes, but don't unsquash -li[nfo] print files as they are unsquashed with file attributes 5. UNSQUASHFS - MISCELLANEOUS OPTIONS ------------------------------------- -s[tat] Display the filesystem superblock information. This is useful to discover the filesystem version, byte ordering, whether it has an NFS export table, and what options were used to compress the filesystem. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/OLD-READMEs/README-AMD64 ================================================ Information for amd64 users --------------------------- All releases of Squashfs prior to 2.0 generate incorrect filesystems on amd64 machines. Filesystems created on amd64 machines work correctly on amd64 machines, but cannot be mounted on non-amd64 machines. Likewise, filesystems created on non-amd64 machines cannot be mounted on amd64 machines. This bug is caused by the different size of the "time_t" definition used in SquashFS filesystem structures. This bug is fixed in releases 2.0 and newer. However, all amd64 filesystems generated by previous releases will not be mountable on amd64 machines with newer releases. If you have amd64 filesystems generated with mksquashfs version 2.0-alpha or older, it is important that you recreate the filesystem. This can be performed by mounting the filesystem using a kernel with the original patch (i.e. a 2.0-alpha or older patch) and running the NEW (i.e. this release) mksquashfs tool to create a new SquashFS filesystem. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/PERFORMANCE.README ================================================ GENERAL INFORMATION ON PERFORMANCE TESTS ---------------------------------------- The following performance tests were based on two file sets: the liveCD filesystem from the Ubuntu liveCD (Warty release), and the liveCD filesystem from the Damn Small Linux liveCD (release 0.8.4). The Ubuntu liveCD filesystem was used to test filesystem performance from CDROM and hard disk for Zisofs, Cloop, Squashfs 2.0 and Squashfs2.1. CRAMFS filesystem performance could not be tested for this filesystem bacause it exceeds the maximum supported size of CRAMFS. To test CRAMFS performance against Squashfs, the liveCD filesystem from Damn Small Linux was used. NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 1. Ubuntu liveCD performance tests ext3 uncompressed size 1.4 GB Zisofs compressed size 589.81 MB Cloop compressed size 471.89 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB 1.1 Performance tests from CDROM 1.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM Zisofs 49.88 seconds (User 2.60 secs, Sys 11.19 secs) Cloop 20.80 seconds (User 2.71 secs, Sys 13.50 secs) Squashfs2.0 16.56 seconds (User 2.42 secs, Sys 10.37 secs) Squashfs2.1 10.14 seconds (User 2.48 secs, Sys 4.44 secs) 1.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM Zisofs 27 minutes 28.54 seconds (User 3.00 secs, Sys 1 min 4.80 secs) Cloop 5 minutes 55.72 seconds (User 2.90 secs, Sys 3 min 37.90 secs) Squashfs2.0 5 minutes 20.87 seconds (User 2.33 secs, Sys 56.98 secs) Squashfs2.1 5 minutes 15.46 seconds (user 2.28 secs, Sys 51.12 secs) 1.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM Zisofs 101 minutes 29.65 seconds (User 5.33 secs, Sys 1 min 17.20 secs) Cloop 35 minutes 27.51 seconds (user 5.93 secs, Sys 4 mins 30.23 secs) Squashfs2.0 21 minutes 53.05 seconds (user 5.71 secs, Sys 2 mins 36.59 secs) Squashfs2.1 21 minutes 46.99 seconds (User 5.80 secs, Sys 2 mins 31.88 secs) 1.2 Performance tests from Hard disk 1.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 17.29 seconds (User 2.62 secs, Sys 11.08 secs) Cloop 16.46 seconds (User 2.63 secs, Sys 13.41 secs) Squashfs2.0 13.75 seconds (User 2.44 secs, Sys 11.00 secs) Squashfs2.1 6.94 seconds (User 2.44 secs, Sys 4.48 secs) 1.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 1 minute 21.47 seconds (User 2.73 secs, Sys 54.44 secs) Cloop 1 minute 34.06 seconds (user 2.85 secs, Sys 1 min 12.13 secs) Squashfs2.0 1 minute 21.22 seconds (User 2.42 secs, Sys 56.21 secs) Squashfs2.1 1 minute 15.46 seconds (User 2.36 secs, Sys 49.78 secs) 1.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk Zisofs 11 minutes 13.64 seconds (User 5.08 secs, Sys 52.62 secs) Cloop 5 minutes 37.93 seconds (user 6 secs, Sys 2 mins 22.38 secs) Squashfs2.0 5 minutes 7.11 seconds (user 5.63 secs, Sys 2 mins 35.23 secs) Squashfs2.1 5 minutes 1.87 seconds (User 5.71 secs, Sys 2 mins 29.98 secs) 2. Damn Small Linux liveCD performance tests ext3 uncompressed size 126 MB CRAMFS compressed size 52.19 MB Squashfs2.0 compressed size 46.52 MB Squashfs2.1 compressed size 46.52 MB 2.1 Performance tests from CDROM 2.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 10.85 seconds (User 0.39 secs, Sys 0.98 secs) Squashfs2.0 2.97 seconds (User 0.36 secs, Sys 2.15 secs) Squashfs2.1 2.43 seconds (User 0.40 secs, Sys 1.42 secs) 2.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 55.38 seconds (User 0.34 secs, Sys 6.98 secs) Squashfs2.0 35.99 seconds (User 0.30 secs, Sys 6.35 secs) Squashfs2.1 33.83 seconds (User 0.26 secs, Sys 5.56 secs) 2.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM CRAMFS 3 minutes 1.68 seconds (User 0.54 secs, Sys 9.51 secs) Squashfs2.0 1 minute 39.45 seconds (User 0.57 secs, Sys 13.14 secs) Squashfs2.1 1 minute 38.41 seconds (User 0.58 secs, Sys 13.08 secs) 2.2 Performance tests from Hard disk 2.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 1.77 seconds (User 0.53 secs, Sys 1.21 secs) Squashfs2.0 2.67 seconds (User 0.41 secs, Sys 2.25 secs) Squashfs2.1 1.87 seconds (User 0.41 secs, Sys 1.46 secs) 2.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 6.80 seconds (User 0.36 secs, Sys 6.02 secs) Squashfs2.0 7.23 seconds (User 0.29 secs, Sys 6.62 secs) Squashfs2.1 6.53 seconds (User 0.31 secs, Sys 5.82 secs) 2.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk CRAMFS 28.55 seconds (User 0.49 secs, Sys 6.49 secs) Squashfs2.0 25.44 seconds (User 0.58 secs, Sys 13.17 secs) Squashfs2.1 24.72 seconds (User 0.56 secs, Sys 13.15 secs) ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/README ================================================ SQUASHFS 3.4 - A squashed read-only filesystem for Linux Copyright 2002-2008 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.4. Please read the CHANGES file for details of changes. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 1Mbytes (default block size 128K). Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. 1. SQUASHFS OVERVIEW -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. In theory files up to 2^64 bytes are supported. In theory filesystems can be up to 2^64 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 1Mbyte (the default size is 128K). Using 128K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 7. Both big and little endian architectures are supported. Squashfs can mount filesystems created on different byte order machines. 2. USING SQUASHFS ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 3. MKSQUASHFS ------------- 3.1 Mksquashfs options and overview. ------------------------------------ As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. SYNTAX:mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Options are -version print version, licence and copyright message -recover <name> recover filesystem data using recovery file <name> -no-recovery don't generate a recovery file -info print files written to filesystem -no-exports don't make the filesystem exportable via NFS -no-progress don't display the progress bar -no-sparse don't detect sparse files -b <block_size> set data block to <block_size>. Default 131072 bytes -processors <number> Use <number> processors. By default will use number of processors available -read-queue <size> Set input queue to <size> Mbytes. Default 64 Mbytes -write-queue <size> Set output queue to <size> Mbytes. Default 512 Mbytes -fragment-queue <size> Set fagment queue to <size> Mbytes. Default 64 Mbytes -noI do not compress inode table -noD do not compress data blocks -noF do not compress fragment blocks -no-fragments do not use fragments -always-use-fragments use fragment blocks for files larger than block size -no-duplicates do not perform duplicate checking -noappend do not append to existing filesystem -keep-as-directory if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory -root-becomes <name> when appending source files/directories, make the original root become a subdirectory in the new root called <name>, rather than adding the new source items to the original root -all-root make all files owned by root -force-uid uid set all file uids to uid -force-gid gid set all file gids to gid -le create a little endian filesystem -be create a big endian filesystem -nopad do not pad filesystem to a multiple of 4K -check_data add checkdata for greater filesystem checks -root-owned alternative name for -all-root -noInodeCompression alternative name for -noI -noDataCompression alternative name for -noD -noFragmentCompression alternative name for -noF -sort <sort_file> sort files according to priorities in <sort_file>. One file or dir with priority per line. Priority -32768 to 32767, default priority 0 -ef <exclude_file> list of exclude dirs/files. One per line -wildcards Allow extended shell wildcards (globbing) to be used in exclude dirs/files -regex Allow POSIX regular expressions to be used in exclude dirs/files Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. 3.2 Changing compression defaults used in mksquashfs ---------------------------------------------------- There are a large number of options that can be used to control the compression in mksquashfs. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances! The -noI, -noD and -noF options (also -noInodeCompression, -noDataCompression and -noFragmentCompression) can be used to force mksquashfs to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. The -no-fragments tells mksquashfs to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 3.1 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. The -always-use-fragments option tells mksquashfs to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. The -no-duplicates option tells mksquashfs to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. The -b option allows the block size to be selected, both "K" and "M" postfixes are supported, this can be either 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K or 1M bytes. 3.3 Specifying the UIDs/GIDs used in the filesystem --------------------------------------------------- By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, mksquashfs provides a number of options which can be used to override the ownership. The options -all-root and -root-owned (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The "-force-uid uid" option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. The "-force-gid gid" option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. 3.4 Excluding files from the filesystem --------------------------------------- The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. Two styles of exclude file matching are supported: basic exclude matching, and extended wildcard matching. Basic exclude matching is a legacy feature retained for backwards compatibility with earlier versions of Mksquashfs. Extended wildcard matching should be used in preference. 3.4.1 Basic exclude matching Each exclude file is treated as an exact match of a file/directory in the source directories. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. 3.4.2 Extended exclude file handling Extended exclude file matching treats each exclude file as a wildcard or regex expression. To enable wildcard matching specify the -wildcards option, and to enable regex matching specify the -regex option. In most cases the -wildcards option should be used rather than -regex because wildcard matching behaviour is significantly easier to understand! In addition to wildcards/regex expressions, exclude files can be "anchored" or "non-anchored". An anchored exclude is one which matches from the root of the directory and nowhere else, a non-anchored exclude matches anywhere. For example given the directory hierarchy "a/b/c/a/b", the anchored exclude "a/b" will match "a/b" at the root of the directory hierarchy, but it will not match the "/a/b" sub-directory within directory "c", whereas a non-anchored exclude would. A couple of examples should make this clearer. Anchored excludes 1. mksquashfs example image.sqsh -wildcards -e 'test/*.gz' Exclude all files matching "*.gz" in the top level directory "test". 2. mksquashfs example image.sqsh -wildcards -e '*/[Tt]est/example*' Exclude all files beginning with "example" inside directories called "Test" or "test", that occur inside any top level directory. Using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e 'test/!(*data*).gz' Exclude all files matching "*.gz" in top level directory "test", except those with "data" in the name. Non-anchored excludes By default excludes match from the top level directory, but it is often useful to exclude a file matching anywhere in the source directories. For this non-anchored excludes can be used, specified by pre-fixing the exclude with "...". Examples: 1. mksquashfs example image.sqsh -wildcards -e '... *.gz' Exclude files matching "*.gz" anywhere in the source directories. For example this will match "example.gz", "test/example.gz", and "test/test/example.gz". 2. mksquashfs example image.sqsh -wildcards -e '... [Tt]est/*.gz' Exclude files matching "*.gz" inside directories called "Test" or "test" that occur anywhere in the source directories. Again, using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e '... !(*data*).gz' Exclude all files matching "*.gz" anywhere in the source directories, except those with "data" in the name. 3.4.3 Exclude files summary The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. 3.5 Appending to squashfs filesystems ------------------------------------- Running squashfs with the destination directory containing an existing filesystem will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3.6 Appending recovery file feature ----------------------------------- Recovery files are created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). The recovery files are called squashfs_recovery_xxx_yyy, where "xxx" is the name of the filesystem being appended to, and "yyy" is a number to guarantee filename uniqueness (the PID of the parent Mksquashfs process). Normally if Mksquashfs exits correctly the recovery file is deleted to avoid cluttering the filesystem. If Mksquashfs aborts, the "-recover" option can be used to recover the filesystem, giving the previously created recovery file as a parameter, i.e. mksquashfs dummy image.sqsh -recover squashfs_recovery_image.sqsh_1234 The writing of the recovery file can be disabled by specifying the "-no-recovery" option. 3.7 Miscellaneous options ------------------------- The -info option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The -le and -be options can be used to force mksquashfs to generate a little endian or big endian filesystem. Normally mksquashfs will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 4. UNSQUASHFS ------------- Unsquashfs allows you to decompress and extract a Squashfs filesystem without mounting it. It can extract the entire filesystem, or a specific file or directory. The Unsquashfs usage info is: SYNTAX: unsquashfs [options] filesystem [directories or files to extract] -v[ersion] print version, licence and copyright information -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -n[o-progress] don't display the progress bar -p[rocessors] <number> use <number> processors. By default will use number of processors available -i[nfo] print files as they are unsquashed -li[nfo] print files as they are unsquashed with file attributes (like ls -l output) -l[s] list filesystem, but don't unsquash -ll[s] list filesystem with file attributes (like ls -l output), but don't unsquash -f[orce] if file already exists then overwrite -s[tat] display filesystem superblock information -e[f] <extract file> list of directories or files to extract. One per line -da[ta-queue] <size> Set data queue to <size> Mbytes. Default 256 Mbytes -fr[ag-queue] <size> Set fagment queue to <size> Mbytes. Default 256 Mbytes -r[egex] treat extract names as POSIX regular expressions rather than use the default shell wildcard expansion (globbing) To extract a subset of the filesystem, the filenames or directory trees that are to be extracted can be specified on the command line. The files/directories should be specified using the full path to the files/directories as they appear within the Squashfs filesystem. The files/directories will also be extracted to those positions within the specified destination directory. The extract files can also be given in a file using the "-e[f]" option. Similarly to Mksquashfs, wildcard matching is performed on the extract files. Wildcard matching is enabled by default. Examples: 1. unsquashfs image.sqsh 'test/*.gz' Extract all files matching "*.gz" in the top level directory "test". 2. unsquashfs image.sqsh '[Tt]est/example*' Extract all files beginning with "example" inside top level directories called "Test" or "test". Using extended wildcards, negative matching is also possible. 3. unsquashfs image.sqsh 'test/!(*data*).gz' Extract all files matching "*.gz" in top level directory "test", except those with "data" in the name. 4.1 Unsquashfs options ---------------------- The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-lls" option is similar but it also displays file attributes (ls -l style output). The "-info" option forces Unsquashfs to print each file as it is decompressed. The -"linfo" is similar but it also displays file attributes. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. The "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. The "-stat" option displays filesystem superblock information. This is useful to discover the filesystem version, byte ordering, whether it has a NFS export table, and what options were used to compress the filesystem, etc. Unsquashfs can decompress all Squashfs filesystem versions, 1.x, 2.x and 3.x filesystems. 5. FILESYSTEM LAYOUT -------------------- Brief filesystem design notes follow for the original 1.x filesystem layout. A description of the 2.x and 3.x filesystem layouts will be written sometime! A squashfs filesystem consists of five parts, packed together on a byte alignment: --------------- | superblock | |---------------| | data | | blocks | |---------------| | inodes | |---------------| | directories | |---------------| | uid/gid | | lookup table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory and uid/gid lookup tables are written. 5.1 Metadata ------------ Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. An inode is identified by a two field tuple <start address of compressed block : offset into de-compressed block>. Inode contents vary depending on the file type. The base inode consists of: base inode: Inode type Mode uid index gid index The inode type is 4 bits in size, and the mode is 12 bits. The uid and gid indexes are 4 bits in length. Ordinarily, this will allow 16 unique indexes into the uid table. To minimise overhead, the uid index is used in conjunction with the spare bit in the file type to form a 48 entry index as follows: inode type 1 - 5: uid index = uid inode type 5 -10: uid index = 16 + uid inode type 11 - 15: uid index = 32 + uid In this way 48 unique uids are supported using 4 bits, minimising data inode overhead. The 4 bit gid index is used to index into a 15 entry gid table. Gid index 15 is used to indicate that the gid is the same as the uid. This prevents the 15 entry gid table filling up with the common case where the uid/gid is the same. The data contents of symbolic links are stored immediately after the symbolic link inode, inside the inode table. This allows the normally small symbolic link to be compressed as part of the inode table, achieving much greater compression than if the symbolic link was compressed individually. Similarly, the block index for regular files is stored immediately after the regular file inode. The block index is a list of block lengths (two bytes each), rather than block addresses, saving two bytes per block. The block address for a given block is computed by the summation of the previous block lengths. This takes advantage of the fact that the blocks making up a file are stored contiguously in the filesystem. The top bit of each block length is set if the block is uncompressed, either because the -noD option is set, or if the compressed block was larger than the uncompressed block. 5.2 Directories --------------- Like inodes, directories are packed into the metadata blocks, and are not aligned on block boundaries, therefore directories can overlap compressed blocks. A directory is, again, identified by a two field tuple <start address of compressed block containing directory start : offset into de-compressed block>. Directories are organised in a slightly complex way, and are not simply a list of file names and inode tuples. The organisation takes advantage of the observation that in most cases, the inodes of the files in the directory will be in the same compressed metadata block, and therefore, the inode tuples will have the same start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. The organisation is as follows: directory_header: count (8 bits) inode start block (24 bits) directory entry: * count inode offset (13 bits) inode type (3 bits) filename size (8 bits) filename This organisation saves on average 3 bytes per filename. 5.3 File data ------------- File data is compressed on a block by block basis and written to the filesystem. The filesystem supports up to 32K blocks, which achieves greater compression ratios than the Linux 4K page size. The disadvantage with using greater than 4K blocks (and the reason why most filesystems do not), is that the VFS reads data in 4K pages. The filesystem reads and decompresses a larger block containing that page (e.g. 32K). However, only 4K can be returned to the VFS, resulting in a very inefficient filesystem, as 28K must be thrown away. Squashfs, solves this problem by explicitly pushing the extra pages into the page cache. 6. AUTHOR INFO -------------- Squashfs was written by Phillip Lougher, email phillip@lougher.demon.co.uk, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback! ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/README ================================================ Readme for Linux-2.6.27 users. The VFS interface in the rc candidates has not stabilised sufficiently to produce one patch that is guaranteed to work once Linux-2.6.27 is released. Linux-2.6.27-rc4 has some minor VFS changes, but there are further up and coming changes in the linux-next tree (linux-2.6.27-rc4-next) that probably will make it into the final Linux 2.6.27 release. If you're using Linux-2.6.27-rc4 use the linux-2.6.27-rc4 patch. If you're using a later rc candidate or the final release, first try the linux-2.6.27-rc4-next patch. ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.12/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.12/fs/Kconfig linux-2.6.12-squashfs3.4/fs/Kconfig --- linux-2.6.12/fs/Kconfig 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/Kconfig 2008-08-19 05:12:27.000000000 +0100 @@ -1171,6 +1171,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.12/fs/Makefile linux-2.6.12-squashfs3.4/fs/Makefile --- linux-2.6.12/fs/Makefile 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -52,6 +52,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/inode.c linux-2.6.12-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.12/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:23:00.000000000 +0100 @@ -0,0 +1,2170 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static void *kzalloc(int size, int flags) +{ + void *buff = kmalloc(size, flags); + + if(buff != NULL) + memset(buff, 0, size); + + return buff; +} + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/Makefile linux-2.6.12-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.12/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/squashfs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/squashfs2_0.c linux-2.6.12-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.12/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-19 04:57:36.000000000 +0100 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.12/fs/squashfs/squashfs.h linux-2.6.12-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.12/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/fs/squashfs/squashfs.h 2008-08-19 04:57:36.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs.h linux-2.6.12-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.12/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/include/linux/squashfs_fs.h 2008-08-19 04:57:36.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs_i.h linux-2.6.12-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.12/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-19 04:57:36.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.12/include/linux/squashfs_fs_sb.h linux-2.6.12-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.12/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.12-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-19 04:57:36.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.12/init/do_mounts_rd.c linux-2.6.12-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.12/init/do_mounts_rd.c 2005-06-17 20:48:29.000000000 +0100 +++ linux-2.6.12-squashfs3.4/init/do_mounts_rd.c 2008-08-18 02:48:54.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.14/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.14/fs/Kconfig linux-2.6.14-squashfs3.4/fs/Kconfig --- linux-2.6.14/fs/Kconfig 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/Kconfig 2008-08-19 05:12:43.000000000 +0100 @@ -1137,6 +1137,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.14/fs/Makefile linux-2.6.14-squashfs3.4/fs/Makefile --- linux-2.6.14/fs/Makefile 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/inode.c linux-2.6.14-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.14/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:23:14.000000000 +0100 @@ -0,0 +1,2159 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + down(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + up(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + up(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + init_MUTEX(&msblk->read_data_mutex); + init_MUTEX(&msblk->read_page_mutex); + init_MUTEX(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + up(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + down(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + up(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + down(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + up(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + up(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/Makefile linux-2.6.14-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.14/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/squashfs/Makefile 2008-08-19 04:48:39.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/squashfs2_0.c linux-2.6.14-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.14/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-19 04:48:39.000000000 +0100 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.14/fs/squashfs/squashfs.h linux-2.6.14-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.14/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/fs/squashfs/squashfs.h 2008-08-19 04:48:39.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs.h linux-2.6.14-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.14/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/include/linux/squashfs_fs.h 2008-08-19 04:49:11.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs_i.h linux-2.6.14-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.14/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-19 04:49:11.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.14/include/linux/squashfs_fs_sb.h linux-2.6.14-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.14/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.14-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-19 04:51:22.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct semaphore read_data_mutex; + struct semaphore read_page_mutex; + struct semaphore meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.14/init/do_mounts_rd.c linux-2.6.14-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.14/init/do_mounts_rd.c 2005-10-28 01:02:08.000000000 +0100 +++ linux-2.6.14-squashfs3.4/init/do_mounts_rd.c 2008-08-18 02:48:54.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.16/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.16/fs/Kconfig linux-2.6.16-squashfs3.4/fs/Kconfig --- linux-2.6.16/fs/Kconfig 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.4/fs/Kconfig 2008-08-18 17:12:49.000000000 +0100 @@ -1193,6 +1193,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.16/fs/Makefile linux-2.6.16-squashfs3.4/fs/Makefile --- linux-2.6.16/fs/Makefile 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.4/fs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -55,6 +55,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/inode.c linux-2.6.16-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.16/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:23:31.000000000 +0100 @@ -0,0 +1,2159 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct super_block *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static struct super_block *squashfs_get_sb(struct file_system_type *,int, const char *, void *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct super_block *s, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/Makefile linux-2.6.16-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.16/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/fs/squashfs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/squashfs2_0.c linux-2.6.16-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.16/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.16/fs/squashfs/squashfs.h linux-2.6.16-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.16/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs.h linux-2.6.16-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.16/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs_i.h linux-2.6.16-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.16/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.16/include/linux/squashfs_fs_sb.h linux-2.6.16-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.16/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.16/init/do_mounts_rd.c linux-2.6.16-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.16/init/do_mounts_rd.c 2006-03-20 05:53:29.000000000 +0000 +++ linux-2.6.16-squashfs3.4/init/do_mounts_rd.c 2008-08-18 02:48:54.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.18/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.18/fs/Kconfig linux-2.6.18-squashfs3.4/fs/Kconfig --- linux-2.6.18/fs/Kconfig 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/Kconfig 2008-08-18 17:12:49.000000000 +0100 @@ -1249,6 +1249,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" help diff -x .gitignore -Nurp linux-2.6.18/fs/Makefile linux-2.6.18-squashfs3.4/fs/Makefile --- linux-2.6.18/fs/Makefile 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -57,6 +57,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/inode.c linux-2.6.18-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.18/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:23:44.000000000 +0100 @@ -0,0 +1,2161 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static kmem_cache_t * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + if (kmem_cache_destroy(squashfs_inode_cachep)) + printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n"); + +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/Makefile linux-2.6.18-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.18/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/squashfs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/squashfs2_0.c linux-2.6.18-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.18/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,755 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + i->i_blksize = PAGE_CACHE_SIZE; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.18/fs/squashfs/squashfs.h linux-2.6.18-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.18/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs.h linux-2.6.18-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.18/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs_i.h linux-2.6.18-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.18/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.18/include/linux/squashfs_fs_sb.h linux-2.6.18-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.18/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.18/init/do_mounts_rd.c linux-2.6.18-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.18/init/do_mounts_rd.c 2006-09-20 04:42:06.000000000 +0100 +++ linux-2.6.18-squashfs3.4/init/do_mounts_rd.c 2008-08-18 02:48:54.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.20/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.20/fs/Kconfig linux-2.6.20-squashfs3.4/fs/Kconfig --- linux-2.6.20/fs/Kconfig 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.4/fs/Kconfig 2008-08-18 17:12:49.000000000 +0100 @@ -1404,6 +1404,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.20/fs/Makefile linux-2.6.20-squashfs3.4/fs/Makefile --- linux-2.6.20/fs/Makefile 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.4/fs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -68,6 +68,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/inode.c linux-2.6.20-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.20/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:23:57.000000000 +0100 @@ -0,0 +1,2147 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/Makefile linux-2.6.20-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.20/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/fs/squashfs/Makefile 2008-08-18 02:48:54.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/squashfs2_0.c linux-2.6.20-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.20/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.20/fs/squashfs/squashfs.h linux-2.6.20-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.20/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs.h linux-2.6.20-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.20/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs_i.h linux-2.6.20-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.20/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.20/include/linux/squashfs_fs_sb.h linux-2.6.20-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.20/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.20-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 17:12:49.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.20/init/do_mounts_rd.c linux-2.6.20-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.20/init/do_mounts_rd.c 2007-02-04 18:44:54.000000000 +0000 +++ linux-2.6.20-squashfs3.4/init/do_mounts_rd.c 2008-08-18 02:48:54.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.22/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.22/fs/Kconfig linux-2.6.22-squashfs3.4/fs/Kconfig --- linux-2.6.22/fs/Kconfig 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/Kconfig 2008-08-18 17:01:29.000000000 +0100 @@ -1367,6 +1367,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.22/fs/Makefile linux-2.6.22-squashfs3.4/fs/Makefile --- linux-2.6.22/fs/Makefile 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/Makefile 2008-08-18 17:02:26.000000000 +0100 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/inode.c linux-2.6.22-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.22/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:24:09.000000000 +0100 @@ -0,0 +1,2146 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/Makefile linux-2.6.22-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.22/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/squashfs/Makefile 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/squashfs2_0.c linux-2.6.22-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.22/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.22/fs/squashfs/squashfs.h linux-2.6.22-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.22/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs.h linux-2.6.22-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.22/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs_i.h linux-2.6.22-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.22/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.22/include/linux/squashfs_fs_sb.h linux-2.6.22-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.22/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 17:01:29.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.22/init/do_mounts_rd.c linux-2.6.22-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.22/init/do_mounts_rd.c 2007-07-09 00:32:17.000000000 +0100 +++ linux-2.6.22-squashfs3.4/init/do_mounts_rd.c 2008-08-18 17:01:29.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.23/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.23/fs/Kconfig linux-2.6.23-squashfs3.4/fs/Kconfig --- linux-2.6.23/fs/Kconfig 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/Kconfig 2008-08-18 16:47:40.000000000 +0100 @@ -1364,6 +1364,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.23/fs/Makefile linux-2.6.23-squashfs3.4/fs/Makefile --- linux-2.6.23/fs/Makefile 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/Makefile 2008-08-18 16:49:22.000000000 +0100 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-$(CONFIG_RAMFS) += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/inode.c linux-2.6.23-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.23/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:24:19.000000000 +0100 @@ -0,0 +1,2147 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/exportfs.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> + +#include "squashfs.h" + +static void vfs_read_inode(struct inode *i); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct super_operations squashfs_export_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .read_inode = vfs_read_inode +}; + +static struct export_operations squashfs_export_ops = { + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + +static void vfs_read_inode(struct inode *i) +{ + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino); + + TRACE("Entered vfs_read_inode\n"); + + if(inode != SQUASHFS_INVALID_BLK) + (msblk->read_inode)(i, inode); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); + struct dentry *rv; + + TRACE("Entered squashfs_get_parent\n"); + + if(parent == NULL) { + rv = ERR_PTR(-EACCES); + goto out; + } + + rv = d_alloc_anon(parent); + if(rv == NULL) + rv = ERR_PTR(-ENOMEM); + +out: + return rv; +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_op = &squashfs_export_super_ops; + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/Makefile linux-2.6.23-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.23/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/squashfs/Makefile 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/squashfs2_0.c linux-2.6.23-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.23/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.23/fs/squashfs/squashfs.h linux-2.6.23-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.23/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs.h linux-2.6.23-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.23/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs_i.h linux-2.6.23-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.23/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.23/include/linux/squashfs_fs_sb.h linux-2.6.23-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.23/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.23-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 16:47:40.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.23/init/do_mounts_rd.c linux-2.6.23-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.23/init/do_mounts_rd.c 2007-10-09 21:31:38.000000000 +0100 +++ linux-2.6.23-squashfs3.4/init/do_mounts_rd.c 2008-08-18 16:47:40.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.24/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.24/fs/Kconfig linux-2.6.24-squashfs3.4/fs/Kconfig --- linux-2.6.24/fs/Kconfig 2008-01-24 22:58:37.000000000 +0000 +++ linux-2.6.24-squashfs3.4/fs/Kconfig 2008-08-18 16:58:05.000000000 +0100 @@ -1405,6 +1405,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.24/fs/Makefile linux-2.6.24-squashfs3.4/fs/Makefile --- linux-2.6.24/fs/Makefile 2008-01-24 22:58:37.000000000 +0000 +++ linux-2.6.24-squashfs3.4/fs/Makefile 2008-08-18 16:58:05.000000000 +0100 @@ -72,6 +72,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/inode.c linux-2.6.24-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.24/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:24:31.000000000 +0100 @@ -0,0 +1,2173 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct export_operations squashfs_export_ops = { + .fh_to_dentry = squashfs_fh_to_dentry, + .fh_to_parent = squashfs_fh_to_parent, + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + + +static struct dentry *squashfs_export_iget(struct super_block *s, + unsigned int inode_number) +{ + squashfs_inode_t inode; + struct inode *i; + struct dentry *dentry; + + TRACE("Entered squashfs_export_iget\n"); + + inode = squashfs_inode_lookup(s, inode_number); + if(inode == SQUASHFS_INVALID_BLK) { + dentry = ERR_PTR(-ENOENT); + goto failure; + } + + i = squashfs_iget(s, inode, inode_number); + if(i == NULL) { + dentry = ERR_PTR(-EACCES); + goto failure; + } + + dentry = d_alloc_anon(i); + if (dentry == NULL) { + iput(i); + dentry = ERR_PTR(-ENOMEM); + } + +failure: + return dentry; +} + + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || + fh_len < 2) + return NULL; + + return squashfs_export_iget(s, fid->i32.ino); +} + + +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) + return NULL; + + return squashfs_export_iget(s, fid->i32.parent_ino); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + + TRACE("Entered squashfs_get_parent\n"); + + return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(struct kmem_cache *cachep, void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/Makefile linux-2.6.24-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.24/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/fs/squashfs/Makefile 2008-08-18 16:58:05.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/squashfs2_0.c linux-2.6.24-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.24/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 16:58:05.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.24/fs/squashfs/squashfs.h linux-2.6.24-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.24/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 16:58:05.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs.h linux-2.6.24-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.24/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 16:58:06.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs_i.h linux-2.6.24-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.24/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 16:58:06.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.24/include/linux/squashfs_fs_sb.h linux-2.6.24-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.24/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 16:58:06.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.24/init/do_mounts_rd.c linux-2.6.24-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.24/init/do_mounts_rd.c 2008-01-24 22:58:37.000000000 +0000 +++ linux-2.6.24-squashfs3.4/init/do_mounts_rd.c 2008-08-18 16:58:06.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.25/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.25/fs/Kconfig linux-2.6.25-squashfs3.4/fs/Kconfig --- linux-2.6.25/fs/Kconfig 2008-04-17 03:49:44.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/Kconfig 2008-08-18 16:44:29.000000000 +0100 @@ -1367,6 +1367,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.25/fs/Makefile linux-2.6.25-squashfs3.4/fs/Makefile --- linux-2.6.25/fs/Makefile 2008-04-17 03:49:44.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/Makefile 2008-08-18 16:44:29.000000000 +0100 @@ -73,6 +73,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.25/fs/squashfs/inode.c linux-2.6.25-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.25/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:24:58.000000000 +0100 @@ -0,0 +1,2173 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct export_operations squashfs_export_ops = { + .fh_to_dentry = squashfs_fh_to_dentry, + .fh_to_parent = squashfs_fh_to_parent, + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + + +static struct dentry *squashfs_export_iget(struct super_block *s, + unsigned int inode_number) +{ + squashfs_inode_t inode; + struct inode *i; + struct dentry *dentry; + + TRACE("Entered squashfs_export_iget\n"); + + inode = squashfs_inode_lookup(s, inode_number); + if(inode == SQUASHFS_INVALID_BLK) { + dentry = ERR_PTR(-ENOENT); + goto failure; + } + + i = squashfs_iget(s, inode, inode_number); + if(i == NULL) { + dentry = ERR_PTR(-EACCES); + goto failure; + } + + dentry = d_alloc_anon(i); + if (dentry == NULL) { + iput(i); + dentry = ERR_PTR(-ENOMEM); + } + +failure: + return dentry; +} + + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || + fh_len < 2) + return NULL; + + return squashfs_export_iget(s, fid->i32.ino); +} + + +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) + return NULL; + + return squashfs_export_iget(s, fid->i32.parent_ino); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + + TRACE("Entered squashfs_get_parent\n"); + + return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(struct kmem_cache *cachep, void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.25/fs/squashfs/Makefile linux-2.6.25-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.25/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/squashfs/Makefile 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.25/fs/squashfs/squashfs2_0.c linux-2.6.25-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.25/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.25/fs/squashfs/squashfs.h linux-2.6.25-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.25/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.25/include/linux/squashfs_fs.h linux-2.6.25-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.25/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.25/include/linux/squashfs_fs_i.h linux-2.6.25-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.25/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.25/include/linux/squashfs_fs_sb.h linux-2.6.25-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.25/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.25-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 16:44:29.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.25/init/do_mounts_rd.c linux-2.6.25-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.25/init/do_mounts_rd.c 2008-04-17 03:49:44.000000000 +0100 +++ linux-2.6.25-squashfs3.4/init/do_mounts_rd.c 2008-08-18 16:44:29.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.26/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.26/fs/Kconfig linux-2.6.26-squashfs3.4/fs/Kconfig --- linux-2.6.26/fs/Kconfig 2008-07-13 22:51:29.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/Kconfig 2008-08-18 16:44:36.000000000 +0100 @@ -1395,6 +1395,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.26/fs/Makefile linux-2.6.26-squashfs3.4/fs/Makefile --- linux-2.6.26/fs/Makefile 2008-07-13 22:51:29.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/Makefile 2008-08-18 16:44:36.000000000 +0100 @@ -73,6 +73,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.26/fs/squashfs/inode.c linux-2.6.26-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.26/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:25:10.000000000 +0100 @@ -0,0 +1,2173 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct export_operations squashfs_export_ops = { + .fh_to_dentry = squashfs_fh_to_dentry, + .fh_to_parent = squashfs_fh_to_parent, + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + + +static struct dentry *squashfs_export_iget(struct super_block *s, + unsigned int inode_number) +{ + squashfs_inode_t inode; + struct inode *i; + struct dentry *dentry; + + TRACE("Entered squashfs_export_iget\n"); + + inode = squashfs_inode_lookup(s, inode_number); + if(inode == SQUASHFS_INVALID_BLK) { + dentry = ERR_PTR(-ENOENT); + goto failure; + } + + i = squashfs_iget(s, inode, inode_number); + if(i == NULL) { + dentry = ERR_PTR(-EACCES); + goto failure; + } + + dentry = d_alloc_anon(i); + if (dentry == NULL) { + iput(i); + dentry = ERR_PTR(-ENOMEM); + } + +failure: + return dentry; +} + + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || + fh_len < 2) + return NULL; + + return squashfs_export_iget(s, fid->i32.ino); +} + + +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) + return NULL; + + return squashfs_export_iget(s, fid->i32.parent_ino); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + + TRACE("Entered squashfs_get_parent\n"); + + return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(struct kmem_cache *cachep, void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.26/fs/squashfs/Makefile linux-2.6.26-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.26/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/squashfs/Makefile 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.26/fs/squashfs/squashfs2_0.c linux-2.6.26-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.26/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.26/fs/squashfs/squashfs.h linux-2.6.26-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.26/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/fs/squashfs/squashfs.h 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.26/include/linux/squashfs_fs.h linux-2.6.26-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.26/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/include/linux/squashfs_fs.h 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.26/include/linux/squashfs_fs_i.h linux-2.6.26-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.26/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.26/include/linux/squashfs_fs_sb.h linux-2.6.26-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.26/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.26-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-18 16:44:36.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.26/init/do_mounts_rd.c linux-2.6.26-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.26/init/do_mounts_rd.c 2008-07-13 22:51:29.000000000 +0100 +++ linux-2.6.26-squashfs3.4/init/do_mounts_rd.c 2008-08-18 16:44:36.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -101,6 +105,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.27-rc4/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/Kconfig linux-2.6.27-rc4-squashfs3.4/fs/Kconfig --- linux-2.6.27-rc4/fs/Kconfig 2008-08-11 15:20:41.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/Kconfig 2008-08-19 18:31:56.000000000 +0100 @@ -1348,6 +1348,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/Makefile linux-2.6.27-rc4-squashfs3.4/fs/Makefile --- linux-2.6.27-rc4/fs/Makefile 2008-08-11 15:20:41.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/Makefile 2008-08-19 18:31:56.000000000 +0100 @@ -74,6 +74,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/squashfs/inode.c linux-2.6.27-rc4-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.27-rc4/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:25:23.000000000 +0100 @@ -0,0 +1,2173 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct export_operations squashfs_export_ops = { + .fh_to_dentry = squashfs_fh_to_dentry, + .fh_to_parent = squashfs_fh_to_parent, + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + + +static struct dentry *squashfs_export_iget(struct super_block *s, + unsigned int inode_number) +{ + squashfs_inode_t inode; + struct inode *i; + struct dentry *dentry; + + TRACE("Entered squashfs_export_iget\n"); + + inode = squashfs_inode_lookup(s, inode_number); + if(inode == SQUASHFS_INVALID_BLK) { + dentry = ERR_PTR(-ENOENT); + goto failure; + } + + i = squashfs_iget(s, inode, inode_number); + if(i == NULL) { + dentry = ERR_PTR(-EACCES); + goto failure; + } + + dentry = d_alloc_anon(i); + if (dentry == NULL) { + iput(i); + dentry = ERR_PTR(-ENOMEM); + } + +failure: + return dentry; +} + + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || + fh_len < 2) + return NULL; + + return squashfs_export_iget(s, fid->i32.ino); +} + + +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) + return NULL; + + return squashfs_export_iget(s, fid->i32.parent_ino); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + + TRACE("Entered squashfs_get_parent\n"); + + return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/squashfs/Makefile linux-2.6.27-rc4-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.27-rc4/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/squashfs/Makefile 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/squashfs/squashfs2_0.c linux-2.6.27-rc4-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.27-rc4/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.27-rc4/fs/squashfs/squashfs.h linux-2.6.27-rc4-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.27-rc4/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/fs/squashfs/squashfs.h 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4/include/linux/squashfs_fs.h linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.27-rc4/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs.h 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4/include/linux/squashfs_fs_i.h linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.27-rc4/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4/include/linux/squashfs_fs_sb.h linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.27-rc4/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-19 18:31:56.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4/init/do_mounts_rd.c linux-2.6.27-rc4-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.27-rc4/init/do_mounts_rd.c 2008-08-11 15:20:55.000000000 +0100 +++ linux-2.6.27-rc4-squashfs3.4/init/do_mounts_rd.c 2008-08-19 18:31:56.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -37,6 +38,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -51,6 +53,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -62,6 +65,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -99,6 +103,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/kernel-patches/linux-2.6.27-rc4-next/squashfs3.4-patch ================================================ diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/Kconfig linux-2.6.27-rc4-next-squashfs3.4/fs/Kconfig --- linux-2.6.27-rc4-next/fs/Kconfig 2008-08-20 02:17:13.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/Kconfig 2008-08-20 04:15:06.000000000 +0100 @@ -1356,6 +1356,56 @@ config CRAMFS If unsure, say N. +config SQUASHFS + tristate "SquashFS 3.4 - Squashed file system support" + select ZLIB_INFLATE + help + Saying Y here includes support for SquashFS 3.4 (a Compressed + Read-Only File System). Squashfs is a highly compressed read-only + filesystem for Linux. It uses zlib compression to compress both + files, inodes and directories. Inodes in the system are very small + and all blocks are packed to minimise data overhead. Block sizes + greater than 4K are supported up to a maximum of 1 Mbytes (default + block size 128K). SquashFS 3.3 supports 64 bit filesystems and files + (larger than 4GB), full uid/gid information, hard links and timestamps. + + Squashfs is intended for general read-only filesystem use, for + archival use (i.e. in cases where a .tar.gz file may be used), and in + embedded systems where low overhead is needed. Further information + and filesystem tools are available from http://squashfs.sourceforge.net. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called squashfs. Note that the root file system (the one + containing the directory /) cannot be compiled as a module. + + If unsure, say N. + +config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" + depends on SQUASHFS + default n + help + Saying Y here allows you to specify cache size. + + If unsure, say N. + +config SQUASHFS_FRAGMENT_CACHE_SIZE + int "Number of fragments cached" if SQUASHFS_EMBEDDED + depends on SQUASHFS + default "3" + help + By default SquashFS caches the last 3 fragments read from + the filesystem. Increasing this amount may mean SquashFS + has to re-read fragments less often from disk, at the expense + of extra system memory. Decreasing this amount will mean + SquashFS uses less memory at the expense of extra reads from disk. + + Note there must be at least one cached fragment. Anything + much more than three will probably not make much difference. + config VXFS_FS tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" depends on BLOCK diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/Makefile linux-2.6.27-rc4-next-squashfs3.4/fs/Makefile --- linux-2.6.27-rc4-next/fs/Makefile 2008-08-20 02:17:14.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/Makefile 2008-08-20 04:15:06.000000000 +0100 @@ -75,6 +75,7 @@ obj-$(CONFIG_JBD) += jbd/ obj-$(CONFIG_JBD2) += jbd2/ obj-$(CONFIG_EXT2_FS) += ext2/ obj-$(CONFIG_CRAMFS) += cramfs/ +obj-$(CONFIG_SQUASHFS) += squashfs/ obj-y += ramfs/ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ obj-$(CONFIG_CODA_FS) += coda/ diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/squashfs/inode.c linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/inode.c --- linux-2.6.27-rc4-next/fs/squashfs/inode.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/inode.c 2008-08-26 08:25:34.000000000 +0100 @@ -0,0 +1,2157 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * inode.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/exportfs.h> + +#include "squashfs.h" + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type); +static struct dentry *squashfs_get_parent(struct dentry *child); +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode); +static int squashfs_statfs(struct dentry *, struct kstatfs *); +static int squashfs_symlink_readpage(struct file *file, struct page *page); +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize); +static int squashfs_readpage(struct file *file, struct page *page); +static int squashfs_readdir(struct file *, void *, filldir_t); +static struct dentry *squashfs_lookup(struct inode *, struct dentry *, + struct nameidata *); +static int squashfs_remount(struct super_block *s, int *flags, char *data); +static void squashfs_put_super(struct super_block *); +static int squashfs_get_sb(struct file_system_type *,int, const char *, void *, + struct vfsmount *); +static struct inode *squashfs_alloc_inode(struct super_block *sb); +static void squashfs_destroy_inode(struct inode *inode); +static int init_inodecache(void); +static void destroy_inodecache(void); + +static struct file_system_type squashfs_fs_type = { + .owner = THIS_MODULE, + .name = "squashfs", + .get_sb = squashfs_get_sb, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV +}; + +static const unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static struct super_operations squashfs_super_ops = { + .alloc_inode = squashfs_alloc_inode, + .destroy_inode = squashfs_destroy_inode, + .statfs = squashfs_statfs, + .put_super = squashfs_put_super, + .remount_fs = squashfs_remount +}; + +static struct export_operations squashfs_export_ops = { + .fh_to_dentry = squashfs_fh_to_dentry, + .fh_to_parent = squashfs_fh_to_parent, + .get_parent = squashfs_get_parent +}; + +SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = { + .readpage = squashfs_symlink_readpage +}; + +SQSH_EXTERN const struct address_space_operations squashfs_aops = { + .readpage = squashfs_readpage +}; + +static const struct file_operations squashfs_dir_ops = { + .read = generic_read_dir, + .readdir = squashfs_readdir +}; + +SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { + .lookup = squashfs_lookup +}; + + +static struct buffer_head *get_block_length(struct super_block *s, + int *cur_index, int *offset, int *c_byte) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned short temp; + struct buffer_head *bh; + + if (!(bh = sb_bread(s, *cur_index))) + goto out; + + if (msblk->devblksize - *offset == 1) { + if (msblk->swap) + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + else + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + if (msblk->swap) + ((unsigned char *) &temp)[0] = *((unsigned char *) + bh->b_data); + else + ((unsigned char *) &temp)[1] = *((unsigned char *) + bh->b_data); + *c_byte = temp; + *offset = 1; + } else { + if (msblk->swap) { + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } else { + ((unsigned char *) &temp)[0] = *((unsigned char *) + (bh->b_data + *offset)); + ((unsigned char *) &temp)[1] = *((unsigned char *) + (bh->b_data + *offset + 1)); + } + *c_byte = temp; + *offset += 2; + } + + if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { + if (*offset == msblk->devblksize) { + brelse(bh); + if (!(bh = sb_bread(s, ++(*cur_index)))) + goto out; + *offset = 0; + } + if (*((unsigned char *) (bh->b_data + *offset)) != + SQUASHFS_MARKER_BYTE) { + ERROR("Metadata block marker corrupt @ %x\n", + *cur_index); + brelse(bh); + goto out; + } + (*offset)++; + } + return bh; + +out: + return NULL; +} + + +SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct buffer_head **bh; + unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); + unsigned int cur_index = index >> msblk->devblksize_log2; + int bytes, avail_bytes, b = 0, k = 0; + unsigned int compressed; + unsigned int c_byte = length; + + bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * + sizeof(struct buffer_head *), GFP_KERNEL); + if (bh == NULL) + goto read_failure; + + if (c_byte) { + bytes = -offset; + compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, + compressed ? "" : "un", (unsigned int) c_byte, srclength); + + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) + goto read_failure; + + for (b = 0; bytes < (int) c_byte; b++, cur_index++) { + bh[b] = sb_getblk(s, cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b, bh); + } else { + if (index < 0 || (index + 2) > sblk->bytes_used) + goto read_failure; + + bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); + if (bh[0] == NULL) + goto read_failure; + b = 1; + + bytes = msblk->devblksize - offset; + compressed = SQUASHFS_COMPRESSED(c_byte); + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + + TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed + ? "" : "un", (unsigned int) c_byte); + + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) + goto block_release; + + for (; bytes < c_byte; b++) { + bh[b] = sb_getblk(s, ++cur_index); + if (bh[b] == NULL) + goto block_release; + bytes += msblk->devblksize; + } + ll_rw_block(READ, b - 1, bh + 1); + } + + if (compressed) { + int zlib_err = 0; + + /* + * uncompress block + */ + + mutex_lock(&msblk->read_data_mutex); + + msblk->stream.next_out = buffer; + msblk->stream.avail_out = srclength; + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + wait_on_buffer(bh[k]); + if (!buffer_uptodate(bh[k])) + goto release_mutex; + + msblk->stream.next_in = bh[k]->b_data + offset; + msblk->stream.avail_in = avail_bytes; + + if (k == 0) { + zlib_err = zlib_inflateInit(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + + if (avail_bytes == 0) { + offset = 0; + brelse(bh[k]); + continue; + } + } + + zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); + if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { + ERROR("zlib_inflate returned unexpected result 0x%x," + " srclength %d, avail_in %d, avail_out %d\n", zlib_err, + srclength, msblk->stream.avail_in, msblk->stream.avail_out); + goto release_mutex; + } + + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + + if (zlib_err != Z_STREAM_END) + goto release_mutex; + + zlib_err = zlib_inflateEnd(&msblk->stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateEnd returned unexpected result 0x%x," + " srclength %d\n", zlib_err, srclength); + goto release_mutex; + } + bytes = msblk->stream.total_out; + mutex_unlock(&msblk->read_data_mutex); + } else { + int i; + + for(i = 0; i < b; i++) { + wait_on_buffer(bh[i]); + if (!buffer_uptodate(bh[i])) + goto block_release; + } + + for (bytes = 0; k < b; k++) { + avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); + + memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); + bytes += avail_bytes; + offset = 0; + brelse(bh[k]); + } + } + + if (next_index) + *next_index = index + c_byte + (length ? 0 : + (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); + + kfree(bh); + return bytes; + +release_mutex: + mutex_unlock(&msblk->read_data_mutex); + +block_release: + for (; k < b; k++) + brelse(bh[k]); + +read_failure: + ERROR("sb_bread failed reading block 0x%x\n", cur_index); + kfree(bh); + return 0; +} + + +static struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, + struct squashfs_cache *cache, long long block, int length) +{ + int i, n; + struct squashfs_cache_entry *entry; + + spin_lock(&cache->lock); + + while (1) { + for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); + + if (i == cache->entries) { + if (cache->unused_blks == 0) { + cache->waiting ++; + spin_unlock(&cache->lock); + wait_event(cache->wait_queue, cache->unused_blks); + spin_lock(&cache->lock); + cache->waiting --; + continue; + } + + i = cache->next_blk; + for (n = 0; n < cache->entries; n++) { + if (cache->entry[i].locked == 0) + break; + i = (i + 1) % cache->entries; + } + + cache->next_blk = (i + 1) % cache->entries; + entry = &cache->entry[i]; + + cache->unused_blks --; + entry->block = block; + entry->locked = 1; + entry->pending = 1; + entry->waiting = 0; + entry->error = 0; + spin_unlock(&cache->lock); + + entry->length = squashfs_read_data(s, entry->data, + block, length, &entry->next_index, cache->block_size); + + spin_lock(&cache->lock); + + if (entry->length == 0) + entry->error = 1; + + entry->pending = 0; + spin_unlock(&cache->lock); + if (entry->waiting) + wake_up_all(&entry->wait_queue); + goto out; + } + + entry = &cache->entry[i]; + if (entry->locked == 0) + cache->unused_blks --; + entry->locked++; + + if (entry->pending) { + entry->waiting ++; + spin_unlock(&cache->lock); + wait_event(entry->wait_queue, !entry->pending); + goto out; + } + + spin_unlock(&cache->lock); + goto out; + } + +out: + TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, + cache->name, entry->block, entry->locked, entry->error); + if (entry->error) + ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); + return entry; +} + + +static void squashfs_cache_put(struct squashfs_cache *cache, + struct squashfs_cache_entry *entry) +{ + spin_lock(&cache->lock); + entry->locked --; + if (entry->locked == 0) { + cache->unused_blks ++; + spin_unlock(&cache->lock); + if (cache->waiting) + wake_up(&cache->wait_queue); + } else + spin_unlock(&cache->lock); +} + + +static void squashfs_cache_delete(struct squashfs_cache *cache) +{ + int i; + + if (cache == NULL) + return; + + for (i = 0; i < cache->entries; i++) + if (cache->entry[i].data) { + if (cache->use_vmalloc) + vfree(cache->entry[i].data); + else + kfree(cache->entry[i].data); + } + + kfree(cache); +} + + +static struct squashfs_cache *squashfs_cache_init(char *name, int entries, + int block_size, int use_vmalloc) +{ + int i; + struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + + entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); + if (cache == NULL) { + ERROR("Failed to allocate %s cache\n", name); + goto failed; + } + + cache->next_blk = 0; + cache->unused_blks = entries; + cache->entries = entries; + cache->block_size = block_size; + cache->use_vmalloc = use_vmalloc; + cache->name = name; + cache->waiting = 0; + spin_lock_init(&cache->lock); + init_waitqueue_head(&cache->wait_queue); + + for (i = 0; i < entries; i++) { + init_waitqueue_head(&cache->entry[i].wait_queue); + cache->entry[i].block = SQUASHFS_INVALID_BLK; + cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : + kmalloc(block_size, GFP_KERNEL); + if (cache->entry[i].data == NULL) { + ERROR("Failed to allocate %s cache entry\n", name); + goto cleanup; + } + } + + return cache; + +cleanup: + squashfs_cache_delete(cache); +failed: + return NULL; +} + + +SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + int bytes, return_length = length; + struct squashfs_cache_entry *entry; + + TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); + + while (1) { + entry = squashfs_cache_get(s, msblk->block_cache, block, 0); + bytes = entry->length - offset; + + if (entry->error || bytes < 1) { + return_length = 0; + goto finish; + } else if (bytes >= length) { + if (buffer) + memcpy(buffer, entry->data + offset, length); + if (entry->length - offset == length) { + *next_block = entry->next_index; + *next_offset = 0; + } else { + *next_block = block; + *next_offset = offset + length; + } + goto finish; + } else { + if (buffer) { + memcpy(buffer, entry->data + offset, bytes); + buffer = (char *) buffer + bytes; + } + block = entry->next_index; + squashfs_cache_put(msblk->block_cache, entry); + length -= bytes; + offset = 0; + } + } + +finish: + squashfs_cache_put(msblk->block_cache, entry); + return return_length; +} + + +static int get_fragment_location(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + struct squashfs_fragment_entry fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry sfragment_entry; + + if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, + sizeof(sfragment_entry), &start_block, &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, + sizeof(fragment_entry), &start_block, &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, + struct squashfs_cache_entry *fragment) +{ + squashfs_cache_put(msblk->fragment_cache, fragment); +} + + +SQSH_EXTERN +struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, + long long start_block, int length) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + + return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header *inodeb) +{ + i->i_ino = inodeb->inode_number; + i->i_mtime.tv_sec = inodeb->mtime; + i->i_atime.tv_sec = inodeb->mtime; + i->i_ctime.tv_sec = inodeb->mtime; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_size = 0; + + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; + int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); + squashfs_inode_t inode; + + TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); + + if (msblk->swap) { + squashfs_inode_t sinode; + + if (!squashfs_get_cached_block(s, &sinode, start, offset, + sizeof(sinode), &start, &offset)) + goto out; + SQUASHFS_SWAP_INODE_T((&inode), &sinode); + } else if (!squashfs_get_cached_block(s, &inode, start, offset, + sizeof(inode), &start, &offset)) + goto out; + + TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); + + return inode; + +out: + return SQUASHFS_INVALID_BLK; +} + + + +static struct dentry *squashfs_export_iget(struct super_block *s, + unsigned int inode_number) +{ + squashfs_inode_t inode; + struct dentry *dentry = ERR_PTR(-ENOENT); + + TRACE("Entered squashfs_export_iget\n"); + + inode = squashfs_inode_lookup(s, inode_number); + if(inode != SQUASHFS_INVALID_BLK) + dentry = d_obtain_alias(squashfs_iget(s, inode, inode_number)); + + return dentry; +} + + +static struct dentry *squashfs_fh_to_dentry(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || + fh_len < 2) + return NULL; + + return squashfs_export_iget(s, fid->i32.ino); +} + + +static struct dentry *squashfs_fh_to_parent(struct super_block *s, + struct fid *fid, int fh_len, int fh_type) +{ + if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) + return NULL; + + return squashfs_export_iget(s, fid->i32.parent_ino); +} + + +static struct dentry *squashfs_get_parent(struct dentry *child) +{ + struct inode *i = child->d_inode; + + TRACE("Entered squashfs_get_parent\n"); + + return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); +} + + +SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, + squashfs_inode_t inode, unsigned int inode_number) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct inode *i = iget_locked(s, inode_number); + + TRACE("Entered squashfs_iget\n"); + + if(i && (i->i_state & I_NEW)) { + (msblk->read_inode)(i, inode); + unlock_new_inode(i); + } + + return i; +} + + +static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header id, sid; + struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodeb, block, offset, + sizeof(*sinodeb), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, inodeb, block, offset, + sizeof(*inodeb), &next_block, &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_reg_inode_header *inodep = &id.reg; + struct squashfs_reg_inode_header *sinodep = &sid.reg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if(!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = 1; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_LREG_TYPE: { + unsigned int frag_size; + long long frag_blk; + struct squashfs_lreg_inode_header *inodep = &id.lreg; + struct squashfs_lreg_inode_header *sinodep = &sid.lreg; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + + if (inodep->fragment != SQUASHFS_INVALID_FRAG) + if (!get_fragment_location(s, inodep->fragment, &frag_blk, + &frag_size)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %llx, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header *inodep = &id.dir; + struct squashfs_dir_inode_header *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header *inodep = &id.ldir; + struct squashfs_ldir_inode_header *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops; + i->i_fop = &squashfs_dir_ops; + i->i_mode |= S_IFDIR; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; + + TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header *inodep = &id.symlink; + struct squashfs_symlink_inode_header *sinodep = &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header *inodep = &id.dev; + struct squashfs_dev_inode_header *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_CHRDEV_TYPE) ? + S_IFCHR : S_IFBLK; + init_special_inode(i, i->i_mode, old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + struct squashfs_ipc_inode_header *inodep = &id.ipc; + struct squashfs_ipc_inode_header *sinodep = &sid.ipc; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, sinodep, block, offset, + sizeof(*sinodep), &next_block, &next_offset)) + goto failed_read; + SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, inodep, block, offset, + sizeof(*inodep), &next_block, &next_offset)) + goto failed_read; + + i->i_nlink = inodep->nlink; + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%llx:%x]\n", block, offset); + +failed_read1: + make_bad_inode(i); + return 0; +} + + +static int read_inode_lookup_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); + + TRACE("In read_inode_lookup_table, length %d\n", length); + + /* Allocate inode lookup table */ + msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); + if (msblk->inode_lookup_table == NULL) { + ERROR("Failed to allocate inode lookup table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, + sblk->lookup_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read inode lookup table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long block; + + for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { + /* XXX */ + SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), + &msblk->inode_lookup_table[i], 1); + msblk->inode_lookup_table[i] = block; + } + } + + return 1; +} + + +static int read_fragment_index_table(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); + + if(length == 0) + return 1; + + /* Allocate fragment index table */ + msblk->fragment_index = kmalloc(length, GFP_KERNEL); + if (msblk->fragment_index == NULL) { + ERROR("Failed to allocate fragment index table\n"); + return 0; + } + + if (!squashfs_read_data(s, (char *) msblk->fragment_index, + sblk->fragment_table_start, length | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + long long fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { + /* XXX */ + SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), + &msblk->fragment_index[i], 1); + msblk->fragment_index[i] = fragment; + } + } + + return 1; +} + + +static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode; + msblk->read_blocklist = read_blocklist; + msblk->read_fragment_index_table = read_fragment_index_table; + + if (sblk->s_major == 1) { + if (!squashfs_1_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 1.0 support enabled\n"); + return 0; + } + } else if (sblk->s_major == 2) { + if (!squashfs_2_0_supported(msblk)) { + SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " + "are unsupported\n"); + SERROR("Please recompile with Squashfs 2.0 support enabled\n"); + return 0; + } + } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > + SQUASHFS_MINOR) { + SERROR("Major/Minor mismatch, trying to mount newer %d.%d " + "filesystem\n", sblk->s_major, sblk->s_minor); + SERROR("Please update your kernel\n"); + return 0; + } + + return 1; +} + + +static int squashfs_fill_super(struct super_block *s, void *data, int silent) +{ + struct squashfs_sb_info *msblk; + struct squashfs_super_block *sblk; + char b[BDEVNAME_SIZE]; + struct inode *root; + + TRACE("Entered squashfs_fill_superblock\n"); + + s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); + if (s->s_fs_info == NULL) { + ERROR("Failed to allocate superblock\n"); + goto failure; + } + msblk = s->s_fs_info; + + msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); + if (msblk->stream.workspace == NULL) { + ERROR("Failed to allocate zlib workspace\n"); + goto failure; + } + sblk = &msblk->sblk; + + msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); + msblk->devblksize_log2 = ffz(~msblk->devblksize); + + mutex_init(&msblk->read_data_mutex); + mutex_init(&msblk->read_page_mutex); + mutex_init(&msblk->meta_index_mutex); + + /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not + * beyond filesystem end. As we're using squashfs_read_data to read sblk here, + * first set sblk->bytes_used to a useful value */ + sblk->bytes_used = sizeof(struct squashfs_super_block); + if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, + sizeof(struct squashfs_super_block) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { + SERROR("unable to read superblock\n"); + goto failed_mount; + } + + /* Check it is a SQUASHFS superblock */ + if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { + if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { + struct squashfs_super_block ssblk; + + WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", + bdevname(s->s_bdev, b)); + + SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); + memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); + msblk->swap = 1; + } else { + SERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(s->s_bdev, b)); + goto failed_mount; + } + } + + /* Check the MAJOR & MINOR versions */ + if(!supported_squashfs_filesystem(msblk, silent)) + goto failed_mount; + + /* Check the filesystem does not extend beyond the end of the + block device */ + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) + goto failed_mount; + + /* Check the root inode for sanity */ + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) + goto failed_mount; + + TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); + TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) + ? "un" : ""); + TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) + ? "un" : ""); + TRACE("Check data is %spresent in the filesystem\n", + SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); + TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); + TRACE("Block size %d\n", sblk->block_size); + TRACE("Number of inodes %d\n", sblk->inodes); + if (sblk->s_major > 1) + TRACE("Number of fragments %d\n", sblk->fragments); + TRACE("Number of uids %d\n", sblk->no_uids); + TRACE("Number of gids %d\n", sblk->no_guids); + TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); + TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); + if (sblk->s_major > 1) + TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); + TRACE("sblk->uid_start %llx\n", sblk->uid_start); + + s->s_maxbytes = MAX_LFS_FILESIZE; + s->s_flags |= MS_RDONLY; + s->s_op = &squashfs_super_ops; + + msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, + SQUASHFS_METADATA_SIZE, 0); + if (msblk->block_cache == NULL) + goto failed_mount; + + /* Allocate read_page block */ + msblk->read_page = vmalloc(sblk->block_size); + if (msblk->read_page == NULL) { + ERROR("Failed to allocate read_page block\n"); + goto failed_mount; + } + + /* Allocate uid and gid tables */ + msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int), GFP_KERNEL); + if (msblk->uid == NULL) { + ERROR("Failed to allocate uid/gid table\n"); + goto failed_mount; + } + msblk->guid = msblk->uid + sblk->no_uids; + + if (msblk->swap) { + unsigned int suid[sblk->no_uids + sblk->no_guids]; + + if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + + sblk->no_guids), (sizeof(unsigned int) * 8)); + } else + if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, + ((sblk->no_uids + sblk->no_guids) * + sizeof(unsigned int)) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) { + ERROR("unable to read uid/gid table\n"); + goto failed_mount; + } + + + if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) + goto allocate_root; + + msblk->fragment_cache = squashfs_cache_init("fragment", + SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); + if (msblk->fragment_cache == NULL) + goto failed_mount; + + /* Allocate and read fragment index table */ + if (msblk->read_fragment_index_table(s) == 0) + goto failed_mount; + + if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) + goto allocate_root; + + /* Allocate and read inode lookup table */ + if (read_inode_lookup_table(s) == 0) + goto failed_mount; + + s->s_export_op = &squashfs_export_ops; + +allocate_root: + root = new_inode(s); + if ((msblk->read_inode)(root, sblk->root_inode) == 0) + goto failed_mount; + insert_inode_hash(root); + + s->s_root = d_alloc_root(root); + if (s->s_root == NULL) { + ERROR("Root inode create failed\n"); + iput(root); + goto failed_mount; + } + + TRACE("Leaving squashfs_fill_super\n"); + return 0; + +failed_mount: + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + squashfs_cache_delete(msblk->fragment_cache); + kfree(msblk->uid); + vfree(msblk->read_page); + squashfs_cache_delete(msblk->block_cache); + kfree(msblk->fragment_index_2); + vfree(msblk->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + return -EINVAL; + +failure: + return -ENOMEM; +} + + +static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + TRACE("Entered squashfs_statfs\n"); + + buf->f_type = SQUASHFS_MAGIC; + buf->f_bsize = sblk->block_size; + buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; + buf->f_bfree = buf->f_bavail = 0; + buf->f_files = sblk->inodes; + buf->f_ffree = 0; + buf->f_namelen = SQUASHFS_NAME_LEN; + + return 0; +} + + +static int squashfs_symlink_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int index = page->index << PAGE_CACHE_SHIFT, length, bytes, avail_bytes; + long long block = SQUASHFS_I(inode)->start_block; + int offset = SQUASHFS_I(inode)->offset; + void *pageaddr = kmap(page); + + TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " + "%llx, offset %x\n", page->index, + SQUASHFS_I(inode)->start_block, + SQUASHFS_I(inode)->offset); + + for (length = 0; length < index; length += bytes) { + bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, + offset, PAGE_CACHE_SIZE, &block, &offset); + if (bytes == 0) { + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + goto skip_read; + } + } + + if (length != index) { + ERROR("(squashfs_symlink_readpage) length != index\n"); + bytes = 0; + goto skip_read; + } + + avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); + + bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, + avail_bytes, &block, &offset); + if (bytes == 0) + ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); + +skip_read: + memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); + kunmap(page); + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + + +static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) +{ + struct meta_index *meta = NULL; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("locate_meta_index: index %d, offset %d\n", index, offset); + + if (msblk->meta_index == NULL) + goto not_allocated; + + for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { + if (msblk->meta_index[i].inode_number == inode->i_ino && + msblk->meta_index[i].offset >= offset && + msblk->meta_index[i].offset <= index && + msblk->meta_index[i].locked == 0) { + TRACE("locate_meta_index: entry %d, offset %d\n", i, + msblk->meta_index[i].offset); + meta = &msblk->meta_index[i]; + offset = meta->offset; + } + } + + if (meta) + meta->locked = 1; + +not_allocated: + mutex_unlock(&msblk->meta_index_mutex); + + return meta; +} + + +static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct meta_index *meta = NULL; + int i; + + mutex_lock(&msblk->meta_index_mutex); + + TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); + + if (msblk->meta_index == NULL) { + msblk->meta_index = kmalloc(sizeof(struct meta_index) * + SQUASHFS_META_NUMBER, GFP_KERNEL); + if (msblk->meta_index == NULL) { + ERROR("Failed to allocate meta_index\n"); + goto failed; + } + for (i = 0; i < SQUASHFS_META_NUMBER; i++) { + msblk->meta_index[i].inode_number = 0; + msblk->meta_index[i].locked = 0; + } + msblk->next_meta_index = 0; + } + + for (i = SQUASHFS_META_NUMBER; i && + msblk->meta_index[msblk->next_meta_index].locked; i --) + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + if (i == 0) { + TRACE("empty_meta_index: failed!\n"); + goto failed; + } + + TRACE("empty_meta_index: returned meta entry %d, %p\n", + msblk->next_meta_index, + &msblk->meta_index[msblk->next_meta_index]); + + meta = &msblk->meta_index[msblk->next_meta_index]; + msblk->next_meta_index = (msblk->next_meta_index + 1) % + SQUASHFS_META_NUMBER; + + meta->inode_number = inode->i_ino; + meta->offset = offset; + meta->skip = skip; + meta->entries = 0; + meta->locked = 1; + +failed: + mutex_unlock(&msblk->meta_index_mutex); + return meta; +} + + +static void release_meta_index(struct inode *inode, struct meta_index *meta) +{ + meta->locked = 0; + smp_mb(); +} + + +static int read_block_index(struct super_block *s, int blocks, char *block_list, + long long *start_block, int *offset) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + unsigned int *block_listp; + int block = 0; + + if (msblk->swap) { + char sblock_list[blocks << 2]; + + if (!squashfs_get_cached_block(s, sblock_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + SQUASHFS_SWAP_INTS(((unsigned int *)block_list), + ((unsigned int *)sblock_list), blocks); + } else { + if (!squashfs_get_cached_block(s, block_list, *start_block, + *offset, blocks << 2, start_block, offset)) { + ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); + goto failure; + } + } + + for (block_listp = (unsigned int *) block_list; blocks; + block_listp++, blocks --) + block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); + + return block; + +failure: + return -1; +} + + +#define SIZE 256 + +static inline int calculate_skip(int blocks) { + int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); + return skip >= 7 ? 7 : skip + 1; +} + + +static int get_meta_index(struct inode *inode, int index, + long long *index_block, int *index_offset, + long long *data_block, char *block_list) +{ + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); + int offset = 0; + struct meta_index *meta; + struct meta_entry *meta_entry; + long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; + int cur_offset = SQUASHFS_I(inode)->offset; + long long cur_data_block = SQUASHFS_I(inode)->start_block; + int i; + + index /= SQUASHFS_META_INDEXES * skip; + + while (offset < index) { + meta = locate_meta_index(inode, index, offset + 1); + + if (meta == NULL) { + meta = empty_meta_index(inode, offset + 1, skip); + if (meta == NULL) + goto all_done; + } else { + if(meta->entries == 0) + goto failed; + /* XXX */ + offset = index < meta->offset + meta->entries ? index : + meta->offset + meta->entries - 1; + /* XXX */ + meta_entry = &meta->meta_entry[offset - meta->offset]; + cur_index_block = meta_entry->index_block + sblk->inode_table_start; + cur_offset = meta_entry->offset; + cur_data_block = meta_entry->data_block; + TRACE("get_meta_index: offset %d, meta->offset %d, " + "meta->entries %d\n", offset, meta->offset, meta->entries); + TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" + " data_block 0x%llx\n", cur_index_block, + cur_offset, cur_data_block); + } + + for (i = meta->offset + meta->entries; i <= index && + i < meta->offset + SQUASHFS_META_ENTRIES; i++) { + int blocks = skip * SQUASHFS_META_INDEXES; + + while (blocks) { + int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; + int res = read_block_index(inode->i_sb, block, block_list, + &cur_index_block, &cur_offset); + + if (res == -1) + goto failed; + + cur_data_block += res; + blocks -= block; + } + + meta_entry = &meta->meta_entry[i - meta->offset]; + meta_entry->index_block = cur_index_block - sblk->inode_table_start; + meta_entry->offset = cur_offset; + meta_entry->data_block = cur_data_block; + meta->entries ++; + offset ++; + } + + TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", + meta->offset, meta->entries); + + release_meta_index(inode, meta); + } + +all_done: + *index_block = cur_index_block; + *index_offset = cur_offset; + *data_block = cur_data_block; + + return offset * SQUASHFS_META_INDEXES * skip; + +failed: + release_meta_index(inode, meta); + return -1; +} + + +static long long read_blocklist(struct inode *inode, int index, + int readahead_blks, char *block_list, + unsigned short **block_p, unsigned int *bsize) +{ + long long block_ptr; + int offset; + long long block; + int res = get_meta_index(inode, index, &block_ptr, &offset, &block, + block_list); + + TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" + " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); + + if(res == -1) + goto failure; + + index -= res; + + while (index) { + int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; + int res = read_block_index(inode->i_sb, blocks, block_list, + &block_ptr, &offset); + if (res == -1) + goto failure; + block += res; + index -= blocks; + } + + if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) + goto failure; + *bsize = *((unsigned int *) block_list); + + return block; + +failure: + return 0; +} + + +static int squashfs_readpage(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned char *block_list = NULL; + long long block; + unsigned int bsize, i; + int bytes; + int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); + void *pageaddr; + struct squashfs_cache_entry *fragment = NULL; + char *data_ptr = msblk->read_page; + + int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; + int start_index = page->index & ~mask; + int end_index = start_index | mask; + int file_end = i_size_read(inode) >> sblk->block_log; + int sparse = 0; + + TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", + page->index, SQUASHFS_I(inode)->start_block); + + if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> + PAGE_CACHE_SHIFT)) + goto out; + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + block_list = kmalloc(SIZE, GFP_KERNEL); + if (block_list == NULL) { + ERROR("Failed to allocate block_list\n"); + goto error_out; + } + + block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); + if (block == 0) + goto error_out; + + if (bsize == 0) { /* hole */ + bytes = index == file_end ? + (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; + sparse = 1; + } else { + mutex_lock(&msblk->read_page_mutex); + + bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, + bsize, NULL, sblk->block_size); + + if (bytes == 0) { + ERROR("Unable to read page, block %llx, size %x\n", block, bsize); + mutex_unlock(&msblk->read_page_mutex); + goto error_out; + } + } + } else { + fragment = get_cached_fragment(inode->i_sb, + SQUASHFS_I(inode)-> u.s1.fragment_start_block, + SQUASHFS_I(inode)->u.s1.fragment_size); + + if (fragment->error) { + ERROR("Unable to read page, block %llx, size %x\n", + SQUASHFS_I(inode)->u.s1.fragment_start_block, + (int) SQUASHFS_I(inode)->u.s1.fragment_size); + release_cached_fragment(msblk, fragment); + goto error_out; + } + bytes = i_size_read(inode) & (sblk->block_size - 1); + data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; + } + + for (i = start_index; i <= end_index && bytes > 0; i++, + bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { + struct page *push_page; + int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); + + TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); + + push_page = (i == page->index) ? page : + grab_cache_page_nowait(page->mapping, i); + + if (!push_page) + continue; + + if (PageUptodate(push_page)) + goto skip_page; + + pageaddr = kmap_atomic(push_page, KM_USER0); + memcpy(pageaddr, data_ptr, avail); + memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(push_page); + SetPageUptodate(push_page); +skip_page: + unlock_page(push_page); + if(i != page->index) + page_cache_release(push_page); + } + + if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK + || index < file_end) { + if (!sparse) + mutex_unlock(&msblk->read_page_mutex); + kfree(block_list); + } else + release_cached_fragment(msblk, fragment); + + return 0; + +error_out: + SetPageError(page); +out: + pageaddr = kmap_atomic(page, KM_USER0); + memset(pageaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(pageaddr, KM_USER0); + flush_dcache_page(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + + kfree(block_list); + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + f_pos -= 3; + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); + } else + squashfs_get_cached_block(s, &index, index_start, index_offset, + sizeof(index), &index_start, &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length + 3; +} + + +static int get_dir_index_using_name(struct super_block *s, + long long *next_block, unsigned int *next_offset, + long long index_start, unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); + if (str == NULL) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index sindex; + squashfs_get_cached_block(s, &sindex, index_start, index_offset, + sizeof(sindex), &index_start, &index_offset); + SQUASHFS_SWAP_DIR_INDEX(index, &sindex); + } else + squashfs_get_cached_block(s, index, index_start, index_offset, + sizeof(struct squashfs_dir_index), &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, index_offset, + index->size + 1, &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); + +failure: + return length + 3; +} + + +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + while(file->f_pos < 3) { + char *name; + int size, i_ino; + + if(file->f_pos == 0) { + name = "."; + size = 1; + i_ino = i->i_ino; + } else { + name = ".."; + size = 2; + i_ino = SQUASHFS_I(i)->u.s2.parent_inode; + } + TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", + (unsigned int) dirent, name, size, (int) + file->f_pos, i_ino, squashfs_filetype_table[1]); + + if (filldir(dirent, name, size, file->f_pos, i_ino, + squashfs_filetype_table[1]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos += size; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", + (unsigned int) dirent, dire->name, dire->size + 1, + (int) file->f_pos, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, + dirh.inode_number + dire->inode_number, + squashfs_filetype_table[dire->type]) < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; + struct squashfs_dir_header dirh; + struct squashfs_dir_entry *dire; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL); + if (dire == NULL) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_lookup; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_lookup; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header sdirh; + if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, + next_offset, sizeof(sdirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, + next_offset, sizeof(dirh), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry sdire; + if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, + next_offset, sizeof(sdire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, dire, next_block, + next_offset, sizeof(*dire), &next_block, &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, + next_offset, dire->size + 1, &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (name[0] < dire->name[0]) + goto exit_lookup; + + if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { + squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory entry %s, inode" + " %x:%x, %d\n", name, dirh.start_block, dire->offset, + dirh.inode_number + dire->inode_number); + + inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); + + goto exit_lookup; + } + } + } + +exit_lookup: + kfree(dire); + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_lookup; +} + + +static int squashfs_remount(struct super_block *s, int *flags, char *data) +{ + *flags |= MS_RDONLY; + return 0; +} + + +static void squashfs_put_super(struct super_block *s) +{ + if (s->s_fs_info) { + struct squashfs_sb_info *sbi = s->s_fs_info; + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + vfree(sbi->read_page); + kfree(sbi->uid); + kfree(sbi->fragment_index); + kfree(sbi->fragment_index_2); + kfree(sbi->meta_index); + vfree(sbi->stream.workspace); + kfree(s->s_fs_info); + s->s_fs_info = NULL; + } +} + + +static int squashfs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, + mnt); +} + + +static int __init init_squashfs_fs(void) +{ + int err = init_inodecache(); + if (err) + goto out; + + printk(KERN_INFO "squashfs: version 3.4 (2008/08/26) " + "Phillip Lougher\n"); + + err = register_filesystem(&squashfs_fs_type); + if (err) + destroy_inodecache(); + +out: + return err; +} + + +static void __exit exit_squashfs_fs(void) +{ + unregister_filesystem(&squashfs_fs_type); + destroy_inodecache(); +} + + +static struct kmem_cache * squashfs_inode_cachep; + + +static struct inode *squashfs_alloc_inode(struct super_block *sb) +{ + struct squashfs_inode_info *ei; + ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); + return ei ? &ei->vfs_inode : NULL; +} + + +static void squashfs_destroy_inode(struct inode *inode) +{ + kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); +} + + +static void init_once(void *foo) +{ + struct squashfs_inode_info *ei = foo; + + inode_init_once(&ei->vfs_inode); +} + + +static int __init init_inodecache(void) +{ + squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", + sizeof(struct squashfs_inode_info), 0, + SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); + if (squashfs_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + + +static void destroy_inodecache(void) +{ + kmem_cache_destroy(squashfs_inode_cachep); +} + + +module_init(init_squashfs_fs); +module_exit(exit_squashfs_fs); +MODULE_DESCRIPTION("squashfs 3.4, a compressed read-only filesystem"); +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); +MODULE_LICENSE("GPL"); diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/squashfs/Makefile linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/Makefile --- linux-2.6.27-rc4-next/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/Makefile 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,7 @@ +# +# Makefile for the linux squashfs routines. +# + +obj-$(CONFIG_SQUASHFS) += squashfs.o +squashfs-y += inode.o +squashfs-y += squashfs2_0.o diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/squashfs/squashfs2_0.c linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/squashfs2_0.c --- linux-2.6.27-rc4-next/fs/squashfs/squashfs2_0.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/squashfs2_0.c 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,740 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; +} + + +static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) +{ + struct super_block *s = i->i_sb; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block - + sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_read_inode_2\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + squashfs_new_inode(msblk, i, inodeb, ino); + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size = 0; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + i->i_data.a_ops = &squashfs_aops; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + return 1; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return 0; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 *index; + char *str; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + + (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_index\n"); + goto failure; + } + + index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + kfree(str); +failure: + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto finish; + } + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + } + } + +finish: + kfree(dire); + return 0; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + kfree(dire); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + struct squashfs_dir_entry_2 *dire; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); + + if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + + SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { + ERROR("Failed to allocate squashfs_dir_entry\n"); + goto exit_loop; + } + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = squashfs_iget(i->i_sb, ino, inode_number); + + goto exit_loop; + } + } + } + +exit_loop: + kfree(dire); + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->read_inode = squashfs_read_inode_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff -x .gitignore -Nurp linux-2.6.27-rc4-next/fs/squashfs/squashfs.h linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/squashfs.h --- linux-2.6.27-rc4-next/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/fs/squashfs/squashfs.h 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index, int srclength); +extern int squashfs_get_cached_block(struct super_block *s, void *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_cache_entry *fragment); +extern struct squashfs_cache_entry *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number); +extern const struct address_space_operations squashfs_symlink_aops; +extern const struct address_space_operations squashfs_aops; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4-next/include/linux/squashfs_fs.h linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs.h --- linux-2.6.27-rc4-next/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs.h 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,935 @@ +#ifndef SQUASHFS_FS +#define SQUASHFS_FS + +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs.h + */ + +#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY +#define CONFIG_SQUASHFS_2_0_COMPATIBILITY +#endif + +#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE +#define SQUASHFS_MAJOR 3 +#define SQUASHFS_MINOR 1 +#define SQUASHFS_MAGIC 0x73717368 +#define SQUASHFS_MAGIC_SWAP 0x68737173 +#define SQUASHFS_START 0 + +/* size of metadata (inode and directory) blocks */ +#define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_METADATA_LOG 13 + +/* default size of data blocks */ +#define SQUASHFS_FILE_SIZE 131072 +#define SQUASHFS_FILE_LOG 17 + +#define SQUASHFS_FILE_MAX_SIZE 1048576 + +/* Max number of uids and gids */ +#define SQUASHFS_UIDS 256 +#define SQUASHFS_GUIDS 255 + +/* Max length of filename (not 255) */ +#define SQUASHFS_NAME_LEN 256 + +#define SQUASHFS_INVALID ((long long) 0xffffffffffff) +#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) +#define SQUASHFS_INVALID_BLK ((long long) -1) +#define SQUASHFS_USED_BLK ((long long) -2) + +/* Filesystem flags */ +#define SQUASHFS_NOI 0 +#define SQUASHFS_NOD 1 +#define SQUASHFS_CHECK 2 +#define SQUASHFS_NOF 3 +#define SQUASHFS_NO_FRAG 4 +#define SQUASHFS_ALWAYS_FRAG 5 +#define SQUASHFS_DUPLICATE 6 +#define SQUASHFS_EXPORT 7 + +#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOI) + +#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOD) + +#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOF) + +#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NO_FRAG) + +#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_ALWAYS_FRAG) + +#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_DUPLICATE) + +#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_EXPORT) + +#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_CHECK) + +#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ + duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ + | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ + (duplicate_checking << 6) | (exportable << 7)) + +/* Max number of types and file types */ +#define SQUASHFS_DIR_TYPE 1 +#define SQUASHFS_FILE_TYPE 2 +#define SQUASHFS_SYMLINK_TYPE 3 +#define SQUASHFS_BLKDEV_TYPE 4 +#define SQUASHFS_CHRDEV_TYPE 5 +#define SQUASHFS_FIFO_TYPE 6 +#define SQUASHFS_SOCKET_TYPE 7 +#define SQUASHFS_LDIR_TYPE 8 +#define SQUASHFS_LREG_TYPE 9 + +/* 1.0 filesystem type definitions */ +#define SQUASHFS_TYPES 5 +#define SQUASHFS_IPC_TYPE 0 + +/* Flag whether block is compressed or uncompressed, bit is set if block is + * uncompressed */ +#define SQUASHFS_COMPRESSED_BIT (1 << 15) + +#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ + (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) + +#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) + +#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) + +#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ + ~SQUASHFS_COMPRESSED_BIT_BLOCK) + +#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) + +/* + * Inode number ops. Inodes consist of a compressed block number, and an + * uncompressed offset within that block + */ +#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) + +#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) + +#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ + << 16) + (B))) + +/* Compute 32 bit VFS inode number from squashfs inode number */ +#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ + ((b) >> 2) + 1)) +/* XXX */ + +/* Translate between VFS mode and squashfs mode */ +#define SQUASHFS_MODE(a) ((a) & 0xfff) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) + +#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ + sizeof(long long)) + +/* inode lookup table defines */ +#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) + +#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ + sizeof(long long)) + +/* cached data constants for filesystem */ +#define SQUASHFS_CACHED_BLKS 8 + +#define SQUASHFS_MAX_FILE_SIZE_LOG 64 + +#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ + (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) + +#define SQUASHFS_MARKER_BYTE 0xff + +/* meta index cache */ +#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) +#define SQUASHFS_META_ENTRIES 31 +#define SQUASHFS_META_NUMBER 8 +#define SQUASHFS_SLOTS 4 + +struct meta_entry { + long long data_block; + unsigned int index_block; + unsigned short offset; + unsigned short pad; +}; + +struct meta_index { + unsigned int inode_number; + unsigned int offset; + unsigned short entries; + unsigned short skip; + unsigned short locked; + unsigned short pad; + struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; +}; + + +/* + * definitions for structures on disk + */ + +typedef long long squashfs_block_t; +typedef long long squashfs_inode_t; + +struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; + unsigned int bytes_used_2; + unsigned int uid_start_2; + unsigned int guid_start_2; + unsigned int inode_table_start_2; + unsigned int directory_table_start_2; + unsigned int s_major:16; + unsigned int s_minor:16; + unsigned int block_size_1:16; + unsigned int block_log:16; + unsigned int flags:8; + unsigned int no_uids:8; + unsigned int no_guids:8; + unsigned int mkfs_time /* time of filesystem creation */; + squashfs_inode_t root_inode; + unsigned int block_size; + unsigned int fragments; + unsigned int fragment_table_start_2; + long long bytes_used; + long long uid_start; + long long guid_start; + long long inode_table_start; + long long directory_table_start; + long long fragment_table_start; + long long lookup_table_start; +} __attribute__ ((packed)); + +struct squashfs_dir_index { + unsigned int index; + unsigned int start_block; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +#define SQUASHFS_BASE_INODE_HEADER \ + unsigned int inode_type:4; \ + unsigned int mode:12; \ + unsigned int uid:8; \ + unsigned int guid:8; \ + unsigned int mtime; \ + unsigned int inode_number; + +struct squashfs_base_inode_header { + SQUASHFS_BASE_INODE_HEADER; +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_lreg_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + squashfs_block_t start_block; + unsigned int fragment; + unsigned int offset; + long long file_size; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:19; + unsigned int offset:13; + unsigned int start_block; + unsigned int parent_inode; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header { + SQUASHFS_BASE_INODE_HEADER; + unsigned int nlink; + unsigned int file_size:27; + unsigned int offset:13; + unsigned int start_block; + unsigned int i_count:16; + unsigned int parent_inode; + struct squashfs_dir_index index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header { + struct squashfs_base_inode_header base; + struct squashfs_dev_inode_header dev; + struct squashfs_symlink_inode_header symlink; + struct squashfs_reg_inode_header reg; + struct squashfs_lreg_inode_header lreg; + struct squashfs_dir_inode_header dir; + struct squashfs_ldir_inode_header ldir; + struct squashfs_ipc_inode_header ipc; +}; + +struct squashfs_dir_entry { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + int inode_number:16; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_header { + unsigned int count:8; + unsigned int start_block; + unsigned int inode_number; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry { + long long start_block; + unsigned int size; + unsigned int unused; +} __attribute__ ((packed)); + +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); +extern int squashfs_uncompress_init(void); +extern int squashfs_uncompress_exit(void); + +/* + * macros to convert each packed bitfield structure from little endian to big + * endian and vice versa. These are needed when creating or using a filesystem + * on a machine with different byte ordering to the target architecture. + * + */ + +#define SQUASHFS_SWAP_START \ + int bits;\ + int b_pos;\ + unsigned long long val;\ + unsigned char *s;\ + unsigned char *d; + +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ + SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ + SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ + SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ + SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ + SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ + SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ + SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ + SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ + SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ + SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ + SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ + SQUASHFS_SWAP((s)->flags, d, 288, 8);\ + SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ + SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ + SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ + SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ + SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ + SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ + SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ + SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ + SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ + SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ + SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ + SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ + SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ + SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ +} + +#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 64, 32); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ipc_inode_header))\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dev_inode_header)); \ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_symlink_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_reg_inode_header));\ + SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ + SQUASHFS_SWAP((s)->offset, d, 192, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ +} + +#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_lreg_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ + SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ + SQUASHFS_SWAP((s)->offset, d, 224, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_dir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ + SQUASHFS_SWAP((s)->offset, d, 147, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ + SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ + sizeof(struct squashfs_ldir_inode_header));\ + SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ + SQUASHFS_SWAP((s)->offset, d, 155, 13);\ + SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ + SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ + SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ + SQUASHFS_SWAP((s)->index, d, 0, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ + SQUASHFS_SWAP((s)->size, d, 64, 8);\ +} + +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ + SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ + SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ + SQUASHFS_SWAP((s)->size, d, 64, 32);\ +} + +#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) + +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 2);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 16)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ +} + +#define SQUASHFS_SWAP_INTS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 4);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 32)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ +} + +#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + 64)\ + SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ +} + +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ + int entry;\ + int bit_position;\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, n * bits / 8);\ + for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ + bits)\ + SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) +#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY + +struct squashfs_base_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int type:4; + unsigned int offset:4; +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_1 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:4; /* index into uid table */ + unsigned int guid:4; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +union squashfs_inode_header_1 { + struct squashfs_base_inode_header_1 base; + struct squashfs_dev_inode_header_1 dev; + struct squashfs_symlink_inode_header_1 symlink; + struct squashfs_reg_inode_header_1 reg; + struct squashfs_dir_inode_header_1 dir; + struct squashfs_ipc_inode_header_1 ipc; +}; + +#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 4);\ + SQUASHFS_SWAP((s)->guid, d, 20, 4); + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_ipc_inode_header_1));\ + SQUASHFS_SWAP((s)->type, d, 24, 4);\ + SQUASHFS_SWAP((s)->offset, d, 28, 4);\ +} + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dev_inode_header_1));\ + SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_symlink_inode_header_1));\ + SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_reg_inode_header_1));\ + SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ + sizeof(struct squashfs_dir_inode_header_1));\ + SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ + SQUASHFS_SWAP((s)->offset, d, 43, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ +} + +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY + +struct squashfs_dir_index_2 { + unsigned int index:27; + unsigned int start_block:29; + unsigned char size; + unsigned char name[0]; +} __attribute__ ((packed)); + +struct squashfs_base_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_ipc_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ +} __attribute__ ((packed)); + +struct squashfs_dev_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short rdev; +} __attribute__ ((packed)); + +struct squashfs_symlink_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned short symlink_size; + char symlink[0]; +} __attribute__ ((packed)); + +struct squashfs_reg_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int mtime; + unsigned int start_block; + unsigned int fragment; + unsigned int offset; + unsigned int file_size:32; + unsigned short block_list[0]; +} __attribute__ ((packed)); + +struct squashfs_dir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:19; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_ldir_inode_header_2 { + unsigned int inode_type:4; + unsigned int mode:12; /* protection */ + unsigned int uid:8; /* index into uid table */ + unsigned int guid:8; /* index into guid table */ + unsigned int file_size:27; + unsigned int offset:13; + unsigned int mtime; + unsigned int start_block:24; + unsigned int i_count:16; + struct squashfs_dir_index_2 index[0]; +} __attribute__ ((packed)); + +union squashfs_inode_header_2 { + struct squashfs_base_inode_header_2 base; + struct squashfs_dev_inode_header_2 dev; + struct squashfs_symlink_inode_header_2 symlink; + struct squashfs_reg_inode_header_2 reg; + struct squashfs_dir_inode_header_2 dir; + struct squashfs_ldir_inode_header_2 ldir; + struct squashfs_ipc_inode_header_2 ipc; +}; + +struct squashfs_dir_header_2 { + unsigned int count:8; + unsigned int start_block:24; +} __attribute__ ((packed)); + +struct squashfs_dir_entry_2 { + unsigned int offset:13; + unsigned int type:3; + unsigned int size:8; + char name[0]; +} __attribute__ ((packed)); + +struct squashfs_fragment_entry_2 { + unsigned int start_block; + unsigned int size; +} __attribute__ ((packed)); + +#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ + SQUASHFS_MEMSET(s, d, n);\ + SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ + SQUASHFS_SWAP((s)->mode, d, 4, 12);\ + SQUASHFS_SWAP((s)->uid, d, 16, 8);\ + SQUASHFS_SWAP((s)->guid, d, 24, 8);\ + +#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ +} + +#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ + SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) + +#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dev_inode_header_2)); \ + SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_symlink_inode_header_2));\ + SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ +} + +#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_reg_inode_header_2));\ + SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ + SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ + SQUASHFS_SWAP((s)->offset, d, 128, 32);\ + SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ +} + +#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_dir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ + SQUASHFS_SWAP((s)->offset, d, 51, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ +} + +#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ + sizeof(struct squashfs_ldir_inode_header_2));\ + SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ + SQUASHFS_SWAP((s)->offset, d, 59, 13);\ + SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ + SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ + SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ +} + +#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ + SQUASHFS_SWAP((s)->index, d, 0, 27);\ + SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ + SQUASHFS_SWAP((s)->size, d, 56, 8);\ +} +#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ + SQUASHFS_SWAP((s)->count, d, 0, 8);\ + SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ +} + +#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ + SQUASHFS_SWAP((s)->offset, d, 0, 13);\ + SQUASHFS_SWAP((s)->type, d, 13, 3);\ + SQUASHFS_SWAP((s)->size, d, 16, 8);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ + SQUASHFS_SWAP_START\ + SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ + SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ + SQUASHFS_SWAP((s)->size, d, 32, 32);\ +} + +#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) + +/* fragment and fragment table defines */ +#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) + +#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ + SQUASHFS_METADATA_SIZE - 1) / \ + SQUASHFS_METADATA_SIZE) + +#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ + sizeof(int)) + +#endif + +#ifdef __KERNEL__ + +/* + * macros used to swap each structure entry, taking into account + * bitfields and different bitfield placing conventions on differing + * architectures + */ + +#include <asm/byteorder.h> + +#ifdef __BIG_ENDIAN + /* convert from little endian to big endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, b_pos) +#else + /* convert from big endian to little endian */ +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ + tbits, 64 - tbits - b_pos) +#endif + +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ + b_pos = pos % 8;\ + val = 0;\ + s = (unsigned char *)p + (pos / 8);\ + d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +} + +#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); + +#endif +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4-next/include/linux/squashfs_fs_i.h linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs_i.h --- linux-2.6.27-rc4-next/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs_i.h 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,45 @@ +#ifndef SQUASHFS_FS_I +#define SQUASHFS_FS_I +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_i.h + */ + +struct squashfs_inode_info { + long long start_block; + unsigned int offset; + union { + struct { + long long fragment_start_block; + unsigned int fragment_size; + unsigned int fragment_offset; + long long block_list_start; + } s1; + struct { + long long directory_index_start; + unsigned int directory_index_offset; + unsigned int directory_index_count; + unsigned int parent_inode; + } s2; + } u; + struct inode vfs_inode; +}; +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4-next/include/linux/squashfs_fs_sb.h linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs_sb.h --- linux-2.6.27-rc4-next/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/include/linux/squashfs_fs_sb.h 2008-08-20 04:15:06.000000000 +0100 @@ -0,0 +1,79 @@ +#ifndef SQUASHFS_FS_SB +#define SQUASHFS_FS_SB +/* + * Squashfs + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + * Phillip Lougher <phillip@lougher.demon.co.uk> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs_fs_sb.h + */ + +#include <linux/squashfs_fs.h> + +struct squashfs_cache_entry { + long long block; + int length; + int locked; + long long next_index; + char pending; + char error; + int waiting; + wait_queue_head_t wait_queue; + char *data; +}; + +struct squashfs_cache { + char *name; + int entries; + int block_size; + int next_blk; + int waiting; + int unused_blks; + int use_vmalloc; + spinlock_t lock; + wait_queue_head_t wait_queue; + struct squashfs_cache_entry entry[0]; +}; + +struct squashfs_sb_info { + struct squashfs_super_block sblk; + int devblksize; + int devblksize_log2; + int swap; + struct squashfs_cache *block_cache; + struct squashfs_cache *fragment_cache; + int next_meta_index; + unsigned int *uid; + unsigned int *guid; + long long *fragment_index; + unsigned int *fragment_index_2; + char *read_page; + struct mutex read_data_mutex; + struct mutex read_page_mutex; + struct mutex meta_index_mutex; + struct meta_index *meta_index; + z_stream stream; + long long *inode_lookup_table; + int (*read_inode)(struct inode *i, squashfs_inode_t \ + inode); + long long (*read_blocklist)(struct inode *inode, int \ + index, int readahead_blks, char *block_list, \ + unsigned short **block_p, unsigned int *bsize); + int (*read_fragment_index_table)(struct super_block *s); +}; +#endif diff -x .gitignore -Nurp linux-2.6.27-rc4-next/init/do_mounts_rd.c linux-2.6.27-rc4-next-squashfs3.4/init/do_mounts_rd.c --- linux-2.6.27-rc4-next/init/do_mounts_rd.c 2008-08-20 02:17:38.000000000 +0100 +++ linux-2.6.27-rc4-next-squashfs3.4/init/do_mounts_rd.c 2008-08-20 04:15:06.000000000 +0100 @@ -5,6 +5,7 @@ #include <linux/ext2_fs.h> #include <linux/romfs_fs.h> #include <linux/cramfs_fs.h> +#include <linux/squashfs_fs.h> #include <linux/initrd.h> #include <linux/string.h> @@ -37,6 +38,7 @@ static int __init crd_load(int in_fd, in * numbers could not be found. * * We currently check for the following magic numbers: + * squashfs * minix * ext2 * romfs @@ -51,6 +53,7 @@ identify_ramdisk_image(int fd, int start struct ext2_super_block *ext2sb; struct romfs_super_block *romfsb; struct cramfs_super *cramfsb; + struct squashfs_super_block *squashfsb; int nblocks = -1; unsigned char *buf; @@ -62,6 +65,7 @@ identify_ramdisk_image(int fd, int start ext2sb = (struct ext2_super_block *) buf; romfsb = (struct romfs_super_block *) buf; cramfsb = (struct cramfs_super *) buf; + squashfsb = (struct squashfs_super_block *) buf; memset(buf, 0xe5, size); /* @@ -99,6 +103,18 @@ identify_ramdisk_image(int fd, int start goto done; } + /* squashfs is at block zero too */ + if (squashfsb->s_magic == SQUASHFS_MAGIC) { + printk(KERN_NOTICE + "RAMDISK: squashfs filesystem found at block %d\n", + start_block); + if (squashfsb->s_major < 3) + nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + else + nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + /* * Read block 1 to test for minix and ext2 superblock */ ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/Makefile ================================================ ifndef Sqlzma $(error Sqlzma is not defined) endif INSTALL_DIR = /usr/local/bin INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ifdef UseDebugFlags DebugFlags = -g -Wall -Wno-unused-variable -O0 -UNDEBUG endif CFLAGS += -I${Sqlzma} -D_REENTRANT -DNDEBUG ${DebugFlags} LDFLAGS += -L${LzmaAlone} -L${LzmaC} all: mksquashfs unsquashfs mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) $(LDFLAGS) mksquashfs.o read_fs.o sort.o -lz -lpthread -lm -lunlzma_r -llzma_r -lstdc++ -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h \ ${LzmaAlone}/liblzma_r.a ${LzmaC}/libunlzma_r.a read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs: unsquashfs.o $(CC) $(LDFLAGS) unsquashfs.o -lpthread -lm -lunlzma -lz -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h \ ${Sqlzma}/sqlzma.h ${Sqlzma}/sqmagic.h ${LzmaC}/libunlzma.a clean: -rm -f *.o mksquashfs unsquashfs install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #endif typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include <squashfs_fs.h> #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "sqlzma.h" #include "sqmagic.h" #ifndef FNM_EXTMATCH #define FNM_EXTMATCH (1 << 5) #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; struct sqlzma_un un; struct sqlzma_opts sqlzma_opts = { .try_lzma = 1, .dicsize = SQUASHFS_FILE_SIZE }; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; int empty_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* describes the list of blocks in a file which is a possible duplicate. For each block, it indicates whether the block is in memory or on disk */ struct buffer_list { long long start; int size; struct file_buffer *read_buffer; }; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; int fragment_buffer_size; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } #define GET_FREELIST 1 struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ #ifdef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else #endif if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else #ifndef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } #endif /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found getting a * new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } res = sqlzma_cm(&sqlzma_opts, stream, (void *)s, size, (void *)d, block_size); c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(read(fd, buff, bytes) == -1) BAD_ERROR("Read on destination failed because %s\n", strerror(errno)); pthread_mutex_unlock(&pos_mutex); } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed because %s\n", strerror(errno)); if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block 0x%llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL); #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { squashfs_fragment_entry *disk_fragment; int size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char *data; char cbuffer[block_size]; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)cbuffer, .sz = size}, {.buf = (void *)buffer->data, .sz = bytes} }; if(compressed_buffer) data = compressed_buffer->data; else { data = cbuffer; read_bytes(fd, start_block, size, data); } sbuf[Src].buf = data; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) BAD_ERROR("%s:%d: res %d\n", __func__, __LINE__, res); } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else read_bytes(fd, start_block, size, buffer->data); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, entry->buffer); pthread_mutex_lock(&fragment_mutex); TRACE("fragment_locked writing fragment %d, compressed size %d\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } int add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) return FALSE; entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { long long slist[meta_blocks]; SQUASHFS_SWAP_LONG_LONGS(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_bytes(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } char buffer2[SQUASHFS_FILE_MAX_SIZE]; struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, struct buffer_list *buffer_list, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; for(block = 0; block < blocks; block ++) { struct buffer_list *b = &buffer_list[block]; struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(b->read_buffer) target_data = b->read_buffer->data; else if(b->size) { target_buffer = cache_lookup(writer_buffer, b->start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(b->start, b->size); } else continue; dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else { read_bytes(fd, dup_start, b->size, buffer2); dup_data = buffer2; } res = memcmp(target_data, dup_data, b->size); if(target_buffer) cache_block_put(target_buffer); if(dup_buffer) cache_block_put(dup_buffer); if(res != 0) break; dup_start += b->size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int index = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; byte = file_buffer->size = read(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read(file, &buffer, 1) == 1) goto restat; } file_buffer->fragment = (file_buffer->block == frag_block); if(file_buffer->fragment) queue_put(from_deflate, file_buffer); else queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } return NULL; } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer = cache_get(writer_buffer, 0, 0); if(sparse_files && all_zero(file_buffer)) write_buffer->c_byte = 0; else write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK(write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, write_buffer); TRACE("Writing fragment %lld, uncompressed size %d, compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { printf("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(current > max) { printf("%lld %lld\n", current, max); return; } if(columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); return; } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; empty_files ++; if (!progress) printf("empty file %s \n",dir_ent->pathname ); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, NULL, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; if (!progress) printf("duplicate file %s \n",dir_ent->pathname); } cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list; struct file_buffer *read_buffer; int status; *duplicate_file = FALSE; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else cache_block_put(read_buffer); inc_progress_bar(); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; inc_progress_bar(); } else read_buffer = NULL; unlock_fragments(); fragment = get_and_fill_fragment(read_buffer); cache_block_put(read_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *reader_buffer, int *duplicate_file) { int block, thresh; unsigned int frag_bytes; long long file_bytes, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer *read_buffer; struct buffer_list *buffer_list; int status, num_locked_fragments; if(!no_fragments && always_use_fragments) { blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if((buffer_list = malloc(blocks * sizeof(struct buffer_list))) == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks; block ++) { if(reader_buffer) { read_buffer = reader_buffer; reader_buffer = NULL; } else { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } block_list[block] = read_buffer->c_byte; buffer_list[block].start = bytes; buffer_list[block].size = read_buffer->size; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; if(block < thresh) { buffer_list[block].read_buffer = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block].read_buffer = read_buffer; } else { buffer_list[block].read_buffer = NULL; cache_block_put(read_buffer); } inc_progress_bar(); } if(frag_bytes != 0) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } else read_buffer = NULL; dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &start, &fragment, read_buffer, buffer_list, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block].read_buffer) queue_put(to_writer, buffer_list[block].read_buffer); fragment = get_and_fill_fragment(read_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block].read_buffer); bytes = buffer_list[0].start; if(thresh && !block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } } unlock_fragments(); cache_block_put(read_buffer); free(buffer_list); file_count ++; total_bytes += read_size; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); ftruncate(fd, bytes); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks].read_buffer); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(!no_fragments && (read_size < block_size)) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan2(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, new, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } void dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type = -1; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 23; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0 ) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; if((inode_lookup_table = realloc(inode_lookup_table, lookup_bytes)) == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; if(!swap) memcpy(&inode_lookup_table[inode_number - 1], &inode->inode, sizeof(squashfs_inode)); else SQUASHFS_SWAP_LONG_LONGS((&inode->inode), &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing exclude which subsumes the exclude currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific excludes, delete as they're subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with -wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories in the * filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in write_recovery_data\n"); read_bytes(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); if((recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) BAD_ERROR("Failed to create recovery file, because %s. Aborting\n", strerror(errno)); if(write(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int readbytes; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); if(read(recoverfd, header2, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); if(read(recoverfd, &sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); read_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in read_recovery_data\n"); if((readbytes = read(recoverfd, metadata, bytes)) == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(readbytes != bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_bytes(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_bytes(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 3.4 (2008/08/26)\n");\ printf("copyright (C) 2008 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("and LZMA %s support for slax.org by jro.\n",LZMA_VERSION); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; int s_minor; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif pthread_mutex_init(&progress_mutex, NULL); un.un_lzma = 1; block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-lzmadic") == 0) { long bs; unsigned int bl; if(++i == argc) { ERROR("%s: -b|-lzmadic missing block size\n", argv[0]); exit(1); } bs = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') bs *= 1048576; else if(*b == 'k' || *b == 'K') bs *= 1024; else if(*b != '\0') { ERROR("%s: -b|-lzmadic invalid size\n", argv[0]); exit(1); } bl = slog(bs); if(bl == 0) { ERROR("%s: -b|-lzmadic size not power of two or not between 4096 and 1Mbyte\n", argv[0]); exit(1); } if (!strcmp(argv[i - 1], "-b")) { block_size = bs; block_log = bl; } sqlzma_opts.dicsize = bs; } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-nolzma") == 0) { un.un_lzma = 0; sqlzma_opts.try_lzma = 0; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-processors <number>\tUse <number> processors. By default will use number of\n\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fagment queue to <size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards (globbing) to be used in\n\t\t\texclude dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to be used in exclude\n\t\t\tdirs/files\n"); ERROR("-lzmadic <dic_size>\tset the LZMA dictionary" " size to <dic_size>\n" "\t\t\tDefault value always follow the block" " size\n" "\t\t\tUse this alone or AFTER -b option\n"); ERROR("-nolzma\t\t\tnever try LZMA compression\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); fragment_buffer_size = fragmentb_mbytes << (20 - block_log); if(block_size <= 65536 && sparse_files == FALSE) s_minor = 0; else s_minor = SQUASHFS_MINOR; for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } be = orig_be; block_log = slog(block_size = sBlk.block_size); //sqlzma_opts.dicsize = block_size; s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { ERROR("%s:%d: %d\n", __func__, __LINE__, i); EXIT_MKSQUASHFS(); } if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -exportable options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = (char *)malloc(scache_bytes); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC_LZMA; if (!un.un_lzma) sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_uids = uid_count; if(sBlk.no_uids) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; sBlk.no_guids = guid_count; if(sBlk.no_guids) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s%s filesystem, data block size %d, %s data, %s metadata, %s fragments, duplicates are %sremoved\n", exportable ? "Exportable " : "", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", duplicate_checking ? "" : "not "); if (sqlzma_opts.try_lzma) printf("lzmadic %u\n", sqlzma_opts.dicsize); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d including %d empty files\n", file_count - dup_files, empty_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d including %d empty files\n", file_count, empty_files); if(duplicate_checking) printf("Number of non empty duplicate files %d\n", file_count - dup_files - empty_files); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { int uid = uids[i]; struct passwd *user = getpwuid(uid); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; extern struct sqlzma_un un; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; switch (sBlk->s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC_LZMA: if (!un.un_lzma) goto bad; break; case SQUASHFS_MAGIC: break; case SQUASHFS_MAGIC_LZMA_SWAP: if (!un.un_lzma) goto bad; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; bad: default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid %s%s SQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", *be ? "big endian" : "little endian", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not "); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; if((*inode_lookup_table = malloc(lookup_bytes)) == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } if(swap) { long long sindex[indexes]; read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) sindex); SQUASHFS_SWAP_FRAGMENT_INDEXES(index, sindex, indexes); } else read_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length %d\n", i, index[i], length); } if(swap) { squashfs_inode_t sinode; for(i = 0; i < sBlk->inodes; i++) { SQUASHFS_SWAP_INODE_T((&sinode), (&(*inode_lookup_table)[i])); memcpy((char *) &(*inode_lookup_table)[i], (char *) &sinode, sizeof(squashfs_inode_t)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #endif #ifdef CONFIG_SQUASHFS_VMALLOC #define SQUASHFS_ALLOC(a) vmalloc(a) #define SQUASHFS_FREE(a) vfree(a) #else #define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) #define SQUASHFS_FREE(a) kfree(a) #endif #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/others/squashfs-3.4-nb4/squashfs3.4/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define CONFIG_SQUASHFS_1_0_COMPATIBILITY #define CONFIG_SQUASHFS_2_0_COMPATIBILITY #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #include <sys/sysctl.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "read_fs.h" #include "global.h" #include "sqlzma.h" #include "sqmagic.h" typedef unsigned int UInt32; #ifndef FNM_EXTMATCH #define FNM_EXTMATCH (1 << 5) #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char symlink[65536]; time_t time; int type; uid_t uid; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); void (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 squashfs_super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; squashfs_fragment_entry_2 *fragment_table_2; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE, use_regex = FALSE, use_lzma = FALSE; char **created_inode; int root_process; struct sqlzma_un un; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for reading * off disk and decompression. The cache grows until max_blocks is reached, * once this occurs existing discarded blocks on the free list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* not in the cache */ /* first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) goto failed; entry->data = malloc(cache->buffer_size); if(entry->data == NULL) { free(entry); goto failed; } entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* queue to read thread to read and ultimately (via the decompress * threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_block_ready(struct cache_entry *entry, int error) { /* mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* if the wait_pending flag is set, one or more threads may be waiting on * this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* wait for this cache entry to become ready, when reading and (if necessary) * decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains accessible * via the hash table it can be found getting a new lease of life before it * is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* if the wait_free flag is set, one or more threads may be waiting on * this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } /* printf("i%d ", inode->inode_number); */ if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)buffer}, {.buf = (void *)block, .sz = bytes} }; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; sbuf[Src].sz = c_byte; res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)data, .sz = c_byte}, {.buf = (void *)block, .sz = bytes} }; if(read_bytes(start, c_byte, data) == FALSE) return 0; printf("la _n"); res = sqlzma_un(&un, sbuf + Src, sbuf + Dst); if (res) abort(); bytes = un.un_reslen; return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void read_block_list(unsigned int *block_list, char *block_ptr, int blocks) { if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } void read_uids_guids() { if((uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); SQUASHFS_SWAP_INTS(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else if(read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } void read_fragment_table_2() { int i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table_2 = (squashfs_fragment_entry_2 *) malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table_2) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table_2[i])); memcpy((char *) &fragment_table_2[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } } void read_fragment_table_1() { } void read_fragment(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table_2[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } int lseek_broken = FALSE; char *zero_data; int write_block(int file_fd, char *buffer, int size, int hole) { off_t off = hole; if(hole) { if(lseek_broken == FALSE && lseek(file_fd, off, SEEK_CUR) == -1) { /* failed to seek beyond end of file */ if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc zero data block\n"); memset(zero_data, 0, block_size); lseek_broken = TRUE; } if(lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write(file_fd, zero_data, avail_bytes) < avail_bytes) goto failure; } } } if(write(file_fd, buffer, size) < size) goto failure; return TRUE; failure: return FALSE; } struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; }; int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); if((file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); if((file = malloc(sizeof(struct squashfs_file))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are queued * separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry *)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry *)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } static struct inode *read_inode(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; static int inode_number = 1; if(bytes == -1) goto error; if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; error: return NULL; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_opendir(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } struct dir *squashfs_opendir_2(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(((*i) = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf component of a pre-existing extract which subsumes the extract currently being added, in which case stop adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist from more specific extracts, delete as they're subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames *)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* match on a leaf component, any subdirectories will * implicitly match, therefore return an empty new search set */ goto empty_set; if(match) /* match on a non-leaf component, add any subdirectories to * the new set of subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); unsigned char b[5]; int offset, dicSize, i; #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "little" : "big", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %s endian SQUASHFS %d:%d superblock on %s.\n", swap ? "big" : "little", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); if(sBlk.s_major > 2) printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); else printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used_2 / 1024.0, sBlk.bytes_used_2 / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); offset =-1; if (!SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags)) { offset = 0x77; } else if (!SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags)) { offset = sBlk.inode_table_start + 2; } else if (!SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags)) { offset = sBlk.directory_table_start + 2; } else if (!SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) && (sBlk.s_major > 1)) { offset = sBlk.fragment_table_start + SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments) + 2 ; } if (offset != -1) { read_bytes(SQUASHFS_START + offset, sizeof(b), (char *) b); if (b[0] == 0x5d ) { dicSize =b[1] | ((UInt32)b[2] << 8) | ((UInt32)b[3] << 16) | ((UInt32)b[4] << 24); printf("Dictionary size %u \n",dicSize); } } printf("Used bytes 0x%llx\n", sBlk.bytes_used); printf("Inode table starts at 0x%llx\n", sBlk.inode_table_start); printf("Directory table starts at 0x%llx\n", sBlk.directory_table_start); printf("UID list starts at 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) printf("Fragment table starts at 0x%llx\n\n", sBlk.fragment_table_start); /* TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); */ } int read_super(char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); /* Check it is a SQUASHFS superblock */ un.un_lzma = 1; swap = 0; switch (sBlk.s_magic) { squashfs_super_block sblk; case SQUASHFS_MAGIC: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA: break; case SQUASHFS_MAGIC_SWAP: un.un_lzma = 0; /*FALLTHROUGH*/ case SQUASHFS_MAGIC_LZMA_SWAP: ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, &sBlk); memcpy(&sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; break; default: ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } if (use_lzma) un.un_lzma=1; /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk.bytes_used_2; sBlk.uid_start = sBlk.uid_start_2; sBlk.guid_start = sBlk.guid_start_2; sBlk.inode_table_start = sBlk.inode_table_start_2; sBlk.directory_table_start = sBlk.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; } else { sBlk.fragment_table_start = sBlk.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_2; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode_2; } } else if(sBlk.s_major == 3 && sBlk.s_minor <= 1) { s_ops.squashfs_opendir = squashfs_opendir; s_ops.read_fragment = read_fragment; s_ops.read_fragment_table = read_fragment_table; s_ops.read_block_list = read_block_list; s_ops.read_inode = read_inode; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_bytes(entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* queue successfully read block to the deflate thread(s) * for further processing */ queue_put(to_deflate, entry); else /* block has either been successfully read and is uncompressed, * or an error has occurred, clear pending flag, set * error appropriately, and wake up any threads waiting on * this buffer */ cache_block_ready(entry, !res); } } /* writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; int hole = 0; int failed = FALSE; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed == FALSE && write_block(file_fd, block->buffer->data + block->offset, block->size, hole) == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* corner case for hole extending to end of file */ if(lseek(file_fd, hole, SEEK_CUR) == -1) { /* for broken lseeks which cannot seek beyond end of * file, write_block will do the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole) == FALSE) { ERROR("writer: failed to write sparse data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; struct sqlzma_un *thread_un = (struct sqlzma_un *) arg; while(1) { struct cache_entry *entry = queue_get(to_deflate); int res; unsigned long bytes = block_size; enum {Src, Dst}; struct sized_buf sbuf[] = { {.buf = (void *)entry->data, .sz = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)}, {.buf = (void *)tmp, .sz = bytes} }; res = sqlzma_un(thread_un, sbuf + Src, sbuf + Dst); if(res) abort(); bytes = thread_un->un_reslen; memcpy(entry->data, tmp, bytes); /* block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res != Z_OK); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { ERROR("TIOCGWINZ ioctl failed, defaulting to 80 columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { struct sqlzma_un *thread_un = malloc(sizeof(struct sqlzma_un)); if(thread_un == NULL) EXIT_UNSQUASH("Failed to allocate memory for sqlzma_un\n"); if(sqlzma_init(thread_un, un.un_lzma, 0) != Z_OK) EXIT_UNSQUASH("Failed to initialize: sqlzma_init\n"); if(pthread_create(&deflator_thread[i], NULL, deflator, thread_un) != 0 ) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; if(current > max) { printf("%lld %lld\n", current, max); return; } if(columns - used < 0) return; printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 3.4 (2008/08/26)\n");\ printf("copyright (C) 2008 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n");\ printf("\nand LZMA %s support for slax.org by jro.\n",LZMA_VERSION); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; struct winsize winsize; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) { use_regex = TRUE; } else if(strcmp(argv[i], "-lzma") == 0) use_lzma = TRUE; else goto options; } if(lsonly || info) progress = FALSE; if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress bar\n"); ERROR("\t-p[rocessors] <number>\tuse <number> processors. By default will use\n\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are unsquashed with file\n\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file attributes (like\n\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to <size> Mbytes. Default %d\n\t\t\t\tMbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX regular expressions\n\t\t\t\trather than use the default shell wildcard\n\t\t\t\texpansion (globbing)\n"); ERROR("\t-lzma\t\t\tuse lzma as compression method\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; block_log = sBlk.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate data\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); i = sqlzma_init(&un, un.un_lzma, 0); if (i != Z_OK) { fputs("sqlzma_init failed", stderr); abort(); } read_uids_guids(); s_ops.read_fragment_table(); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-3.4-nb4/unsquashfs-lzma ================================================ #!/bin/bash ./unsquashfs -lzma $@ ================================================ FILE: src/others/squashfs-4.0-lzma/Makefile ================================================ INCLUDEDIR = -I. -I./lzma/C LZMAPATH = ./lzma/C/LzmaLib USE_LZMA = 1 ifdef USE_LZMA LZMA_CFLAGS = -DUSE_LZMA LZMA_LIB = -L$(LZMAPATH) -llzma CFLAGS += $(LZMA_CFLAGS) endif CFLAGS := $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 USE_LZMA = 1 ifdef USE_LZMA LZMA_CFLAGS = -DUSE_LZMA LZMA_LIB = -L$(LZMAPATH) -llzma CFLAGS += $(LZMA_CFLAGS) endif all: mksquashfs-lzma unsquashfs-lzma mksquashfs-lzma: mksquashfs.o read_fs.o sort.o swap.o pseudo.o uncompress.o make -C $(LZMAPATH) $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o uncompress.o -lz -lpthread -lm $(LZMA_LIB) -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h uncompress.h Makefile read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h uncompress.h Makefile sort.o: sort.c squashfs_fs.h global.h sort.h Makefile swap.o: swap.c Makefile pseudo.o: pseudo.c pseudo.h Makefile uncompress.o: uncompress.c uncompress.h unsquashfs-lzma: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o uncompress.o $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o uncompress.o -lz -lpthread -lm $(LZMA_LIB) -o $@ unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h uncompress.h Makefile unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h uncompress.h Makefile clean: -rm -f *.o mksquashfs-lzma unsquashfs-lzma install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs $(INSTALL_DIR) cp unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-4.0-lzma/README-4.0 ================================================ SQUASHFS 4.0 - A squashed read-only filesystem for Linux Copyright 2002-2009 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs 4.0. This is an initial tools only release to support users of the 2.6.29 kernel, following the mainlining of Squashfs earlier this year. Later releases will probably contain kernel patches supporting 4.0 layouts for earlier kernels. New Mksquashfs options ---------------------- Mksquashfs now supports pseudo files, these allow fake directories, character and block devices to be specified and added to the Squashfs filesystem being built, rather than requiring them to be present in the source directories. This, for example, allows device nodes to be added to the filesystem without requiring root access. Two options are supported, -p allows one pseudo file to be specified on the command line, and -pf allows a pseudo file to be specified containing a list of pseduo definitions, one per line. Pseudo device nodes are specified using 7 arguments Filename type mode uid gid major minor Where type is either b - for block devices, and c - for character devices mode is the octal mode specifier, similar to that expected by chmod. Uid and gid can be either specified as a decimal number, or by name. For example: /dev/chr_dev c 666 root root 100 1 /dev/blk_dev b 444 0 0 200 200 Directories are specified using 5 arguments Filename type mode uid gid Where type is d. ================================================ FILE: src/others/squashfs-4.0-lzma/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; typedef unsigned int squashfs_id; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.62 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CFileItem *f = db.db.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zBuf.c ================================================ /* 7zBuf.c -- Byte Buffer 2008-03-28 Igor Pavlov Public domain */ #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)alloc->Alloc(alloc, size); if (p->data != 0) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zBuf.h ================================================ /* 7zBuf.h -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zBuf2.c ================================================ /* 7zBuf2.c -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)alloc->Alloc(alloc, newSize); if (data == 0) return 0; p->size = newSize; memcpy(data, p->data, p->pos); alloc->Free(alloc, p->data); p->data = data; } memcpy(p->data + p->pos, buf, size); p->pos += size; return 1; } void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zCrc.c ================================================ /* 7zCrc.c -- CRC32 calculation 2008-08-05 Igor Pavlov Public domain */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zCrc.h ================================================ /* 7zCrc.h -- CRC32 calculation 2008-03-13 Igor Pavlov Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zFile.c ================================================ /* 7zFile.c -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include <errno.h> #endif #ifdef USE_WINDOWS_FILE /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #define kChunkSizeMax (1 << 22) #endif void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #else p->file = NULL; #endif } static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #else p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #else if (p->file != NULL) { int res = fclose(p->file); if (res != 0) return res; p->file = NULL; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fread(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fwrite(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE LARGE_INTEGER value; DWORD moveMethod; value.LowPart = (DWORD)*pos; value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ switch (origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)value.HighPart << 32) | value.LowPart; return 0; #else int moveMethod; int res; switch (origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return 1; } res = fseek(p->file, (long)*pos, moveMethod); *pos = ftell(p->file); return res; #endif } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #else long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) { CFileSeqInStream *p = (CFileSeqInStream *)pp; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->s.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(void *pp, void *buf, size_t *size) { CFileInStream *p = (CFileInStream *)pp; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) { CFileInStream *p = (CFileInStream *)pp; return File_Seek(&p->file, pos, origin); } void FileInStream_CreateVTable(CFileInStream *p) { p->s.Read = FileInStream_Read; p->s.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(void *pp, const void *data, size_t size) { CFileOutStream *p = (CFileOutStream *)pp; File_Write(&p->file, data, &size); return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->s.Write = FileOutStream_Write; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zFile.h ================================================ /* 7zFile.h -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE #endif #ifdef USE_WINDOWS_FILE #include <windows.h> #else #include <stdio.h> #endif #include "Types.h" /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #else FILE *file; #endif } CSzFile; void File_Construct(CSzFile *p); WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream s; CSzFile file; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream s; CSzFile file; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream s; CSzFile file; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zStream.c ================================================ /* 7zStream.c -- 7z Stream functions 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "Types.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) { Int64 t = offset; return stream->Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); memcpy(buf, lookBuf, *size); return stream->Skip(stream, *size); } SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; size2 = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, &size2); p->size = size2; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; if (*size > LookToRead_BUF_SIZE) *size = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Skip(void *pp, size_t offset) { CLookToRead *p = (CLookToRead *)pp; p->pos += offset; return SZ_OK; } static SRes LookToRead_Read(void *pp, void *buf, size_t *size) { CLookToRead *p = (CLookToRead *)pp; size_t rem = p->size - p->pos; if (rem == 0) return p->realStream->Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) { CLookToRead *p = (CLookToRead *)pp; p->pos = p->size = 0; return p->realStream->Seek(p->realStream, pos, origin); } void LookToRead_CreateVTable(CLookToRead *p, int lookahead) { p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact; p->s.Skip = LookToRead_Skip; p->s.Read = LookToRead_Read; p->s.Seek = LookToRead_Seek; } void LookToRead_Init(CLookToRead *p) { p->pos = p->size = 0; } static SRes SecToLook_Read(void *pp, void *buf, size_t *size) { CSecToLook *p = (CSecToLook *)pp; return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->s.Read = SecToLook_Read; } static SRes SecToRead_Read(void *pp, void *buf, size_t *size) { CSecToRead *p = (CSecToRead *)pp; return p->realStream->Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->s.Read = SecToRead_Read; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/7zVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Alloc.c ================================================ /* Alloc.c -- Memory allocation functions 2008-09-24 Igor Pavlov Public domain */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG { void *p = malloc(size); fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); return p; } #else return malloc(size); #endif } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" #include "7zDecode.h" #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_Construct(&state); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) { if (state.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(inStream->Skip((void *)inStream, curSize)); } return SZ_OK; } #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } UInt64 GetSum(const UInt64 *values, UInt32 index) { UInt64 sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CSzCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; UInt64 unpackSize = folder->UnpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); if (temp == 0 && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = GetSum(packSizes, si); inSize = packSizes[si]; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } else { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZ_ERROR_UNSUPPORTED; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); UInt64 s3Size = packSizes[1]; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZ_ERROR_MEM; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) res = Bcj2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], tempBuf[2], tempSizes[2], outBuffer, outSize); RINOK(res) } else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SRes res = SzDecode2(packSizes, folder, inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) IAlloc_Free(allocMain, tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "7zDecode.h" #include "7zExtract.h" SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzAr_Extract( const CSzArEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c -- 7z Input functions 2008-12-31 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "../../CpuArch.h" #include "7zDecode.h" #include "7zIn.h" #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->FolderStartPackStreamIndex = 0; p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } /* UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CSzFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) { UInt32 startPos = 0; UInt64 startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); for (i = 0; i < p->db.NumFolders; i++) { p->FolderStartPackStreamIndex[i] = startPos; startPos += p->db.Folders[i].NumPackStreams; } MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); for (i = 0; i < p->db.NumPackStreams; i++) { p->PackStreamStartPositions[i] = startPosSize; startPosSize += p->db.PackSizes[i]; } MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); for (i = 0; i < p->db.NumFiles; i++) { CSzFileItem *file = p->db.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { p->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderStartFileIndex[folderIndex] = i; if (p->db.Folders[folderIndex].NumUnpackStreams != 0) break; folderIndex++; } } p->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) { return p->dataPos + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) { UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; CSzFolder *folder = p->db.Folders + folderIndex; UInt64 size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; if (t < size) /* check it */ return SZ_ERROR_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SRes SzReadTime(const CObjectVector<CBuf> &dataVector, CObjectVector<CSzFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for (int i = 0; i < files.Size(); i++) { CSzFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; } } return SZ_OK; } */ static int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; static SRes SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZ_ERROR_ARCHIVE; sd->Size--; *b = *sd->Data++; return SZ_OK; } static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } static SRes SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } static SRes SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static SRes SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } static SRes SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZ_ERROR_ARCHIVE; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } static SRes SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SzSkeepData(sd)); } } static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, alloc); MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } static SRes SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, ISzAlloc *alloc) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); MY_ALLOC(UInt32, *digests, numItems, alloc); for (i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } static SRes SzReadPackInfo( CSzData *sd, UInt64 *dataOffset, UInt32 *numPackStreams, UInt64 **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, ISzAlloc *alloc) { UInt32 i; RINOK(SzReadNumber(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { RINOK(SzReadNumber(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } static SRes SzReadStreamsInfo( CSzData *sd, UInt64 *dataOffset, CSzAr *p, UInt32 *numUnpackStreams, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ ISzAlloc *alloc, ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZ_ERROR_UNSUPPORTED; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); break; } case k7zIdUnpackInfo: { RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZ_ERROR_UNSUPPORTED; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) { UInt32 i; for (i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CSzFileItem *file = files + i; while (pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZ_ERROR_ARCHIVE; if (pos + 2 > sd->Size) return SZ_ERROR_ARCHIVE; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZ_ERROR_ARCHIVE; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, alloc); len = 0; while (2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += numAdds; } } return SZ_OK; } static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->FileCRCDefined = 0; } } } return SzArEx_Fill(p, allocMain); } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; } static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzDecode(p->PackSizes, folder, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; } static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h -- 7z Input functions 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 *FolderStartPackStreamIndex; UInt64 *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; } CSzArEx; void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #include "7zItem.h" void SzCoderInfo_Init(CSzCoderInfo *p) { Buf_Init(&p->Props); } void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) { Buf_Free(&p->Props, alloc); SzCoderInfo_Init(p); } void SzFolder_Init(CSzFolder *p) { p->Coders = 0; p->BindPairs = 0; p->PackStreams = 0; p->UnpackSizes = 0; p->NumCoders = 0; p->NumBindPairs = 0; p->NumPackStreams = 0; p->UnpackCRCDefined = 0; p->UnpackCRC = 0; p->NumUnpackStreams = 0; } void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { UInt32 i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); } UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) { UInt32 result = 0; UInt32 i; for (i = 0; i < p->NumCoders; i++) result += p->Coders[i].NumOutStreams; return result; } int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } UInt64 SzFolder_GetUnpackSize(CSzFolder *p) { int i = (int)SzFolder_GetNumOutStreams(p); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolder_FindBindPairForOutStream(p, i) < 0) return p->UnpackSizes[i]; /* throw 1; */ return 0; } void SzFile_Init(CSzFileItem *p) { p->HasStream = 1; p->IsDir = 0; p->IsAnti = 0; p->FileCRCDefined = 0; p->MTimeDefined = 0; p->Name = 0; } static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Name); SzFile_Init(p); } void SzAr_Init(CSzAr *p) { p->PackSizes = 0; p->PackCRCsDefined = 0; p->PackCRCs = 0; p->Folders = 0; p->Files = 0; p->NumPackStreams = 0; p->NumFolders = 0; p->NumFiles = 0; } void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { UInt32 i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); if (p->Files) for (i = 0; i < p->NumFiles; i++) SzFile_Free(&p->Files[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" typedef struct { UInt32 NumInStreams; UInt32 NumOutStreams; UInt64 MethodID; CBuf Props; } CSzCoderInfo; void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); typedef struct { UInt32 InIndex; UInt32 OutIndex; } CBindPair; typedef struct { CSzCoderInfo *Coders; CBindPair *BindPairs; UInt32 *PackStreams; UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; int UnpackCRCDefined; UInt32 UnpackCRC; UInt32 NumUnpackStreams; } CSzFolder; void SzFolder_Init(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { CNtfsFileTime MTime; UInt64 Size; char *Name; UInt32 FileCRC; Byte HasStream; Byte IsDir; Byte IsAnti; Byte FileCRCDefined; Byte MTimeDefined; } CSzFileItem; void SzFile_Init(CSzFileItem *p); typedef struct { UInt64 *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; CSzFolder *Folders; CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; UInt32 NumFiles; } CSzAr; void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c - Test application for 7z Decoder 2008-11-23 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "7zAlloc.h" #include "7zExtract.h" #include "7zIn.h" static void ConvertNumberToString(UInt64 value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } if (InFile_Open(&archiveStream.file, args[2])) { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *f = db.db.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) ConvertFileTimeToString(&f->MTime, t); else strcpy(t, " "); printf("%s %10s %s\n", t, s, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (f->IsDir) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) { printf("\n"); continue; } res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { CSzFile outFile; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } if (OutFile_Open(&outFile, fileName)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/makefile ================================================ MY_STATIC_LINK=1 PROG = 7zDec.exe C_OBJS = \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ $O\7zStream.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c 7zBuf2.o: ../../7zBuf2.c $(CXX) $(CFLAGS) ../../7zBuf2.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c Bcj2.o: ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c 7zFile.o: ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c 7zStream.o: ../../7zStream.c $(CXX) $(CFLAGS) ../../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Bcj2.c ================================================ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bcj2.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *buffer, *bufferLim; UInt32 range, code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; buffer = buf3; bufferLim = buffer + size3; RC_INIT2 if (outSize == 0) return SZ_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; UInt32 ttt; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IF_BIT_0(prob) { UPDATE_0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UPDATE_1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return SZ_ERROR_DATA; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return SZ_ERROR_DATA; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Bcj2.h ================================================ /* Bcj2.h -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). Returns: SZ_OK SZ_ERROR_DATA - Data error */ int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Bra.c ================================================ /* Bra.c -- Converters for RISC code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 8; for (i = 0; i <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 4; for (i = 0; i <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) { UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Bra.h ================================================ /* Bra.h -- Branch converters for executables 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. Type Endian Alignment LookAhead x86 little 1 4 ARMT little 2 2 ARM little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 size must be >= Alignment + LookAhead, if it's not last block. If (size < Alignment + LookAhead), converter returns 0. Example: UInt32 ip = 0; for () { ; size must be >= Alignment + LookAhead, if it's not last block SizeT processed = Convert(data, size, ip, 1); data += processed; size -= processed; ip += processed; } */ #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Bra86.c ================================================ /* Bra86.c -- Converter for x86 code (BCJ) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *state & 0x7; if (size < 5) return 0; ip += 5; prevPosT = (SizeT)0 - 1; for (;;) { Byte *p = data + bufferPos; Byte *limit = data + size - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - data); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (ip + (UInt32)bufferPos) + src; else dest = src - (ip + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/BraIA64.c ================================================ /* BraIA64.c -- Converter for IA-64 code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" static const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 16) return 0; size -= 16; for (i = 0; i <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)data[i + j + bytePos] << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/CpuArch.h ================================================ /* CpuArch.h 2008-08-05 Igor Pavlov Public domain */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #ifdef LITTLE_ENDIAN_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #endif #if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzFindMt.c ================================================ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include "LzHash.h" #include "LzFindMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads2(name, v, action) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ { action; for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #define NO_INLINE MY_FAST_CALL Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->crc = mf->crc; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzFindMt.h ================================================ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFINDMT_H #define __LZFINDMT_H #include "Threads.h" #include "LzFind.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #include <string.h> #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ #include <string.h> /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include <stdio.h> #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifdef COMPRESS_MF_MT ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/LzmaLib.def ================================================ EXPORTS LzmaCompress LzmaUncompress ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/LzmaLib.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # End Group # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\IStream.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\LzmaLib.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/LzmaLib.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/LzmaLibExports.c ================================================ /* LzmaLibExports.c -- LZMA library DLL Entry point 2008-10-04 : Igor Pavlov : Public domain */ #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance = hInstance; dwReason = dwReason; lpReserved = lpReserved; return TRUE; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/Makefile ================================================ CC = gcc LIB = liblzma.a RM = rm -f CFLAGS = -c -O2 -Wall AR = ar RANLIB = ranlib OBJS = \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ LzmaLib.o \ 7zFile.o \ 7zStream.o \ all: $(LIB) $(LIB): $(OBJS) rm -f $@ $(AR) rcu $@ $(OBJS) $(RANLIB) $@ Alloc.o: ../Alloc.c $(CC) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CC) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CC) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CC) $(CFLAGS) ../LzmaEnc.c LzmaLib.o: ../LzmaLib.c $(CC) $(CFLAGS) ../LzmaLib.c 7zFile.o: ../7zFile.c $(CC) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CC) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) *.o *.a ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib/resource.rc ================================================ #include "../../CPP/7zip/MyVersionInfo.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib.c ================================================ /* LzmaLib.c -- LZMA library wrapper 2008-08-05 Igor Pavlov Public domain */ #include "LzmaEnc.h" #include "LzmaDec.h" #include "Alloc.h" #include "LzmaLib.h" static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaLib.h ================================================ /* LzmaLib.h -- LZMA library interface 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMALIB_H #define __LZMALIB_H #include "Types.h" #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 16 KB 0 32 1: 64 KB 0 32 2: 256 KB 0 32 3: 1 MB 0 32 4: 4 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7+: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/Lzma86Dec.c ================================================ /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2008-04-07 Igor Pavlov Public domain */ #include "Lzma86Dec.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaDec.h" #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(dest, *destLen, 0, &x86State, 0); } return SZ_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/Lzma86Dec.h ================================================ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86DEC_H #define __LZMA86DEC_H #include "../Types.h" /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/Lzma86Enc.c ================================================ /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #include <string.h> #include "Lzma86Enc.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaEnc.h" #define SZE_OUT_OVERFLOW SZE_DATA_ERROR static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; Bool useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, srcLen, 0, &x86State, 1); } } { size_t minSize = 0; Bool bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/Lzma86Enc.h ================================================ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86ENC_H #define __LZMA86ENC_H #include "../Types.h" /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, = 1 - x86 filter 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/LzmaUtil.c ================================================ /* LzmaUtil.c -- Test application for LZMA compression 2008-11-23 : Igor Pavlov : Public domain */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../Alloc.h" #include "../7zFile.h" #include "../7zVersion.h" #include "../LzmaDec.h" #include "../LzmaEnc.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; const char *kDataErrorMessage = "Data error"; static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; void PrintHelp(char *buffer) { strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" "\nUsage: lzma <e|d> inputFile outputFile\n" " e: encode file\n" " d: decode file\n"); } int PrintError(char *buffer, const char *message) { strcat(buffer, "\nError: "); strcat(buffer, message); strcat(buffer, "\n"); return 1; } int PrintErrorNumber(char *buffer, SRes val) { sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); return 1; } int PrintUserError(char *buffer) { return PrintError(buffer, "Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) { int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)); inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || thereIsSize && unpackSize == 0) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ RINOK(SeqInStream_Read(inStream, header, sizeof(header))); unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_Construct(&state); RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; rs = rs; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int main2(int numArgs, const char *args[], char *rs) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; Bool useOutFile = False; FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); if (numArgs == 1) { PrintHelp(rs); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(rs); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(rs); { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError(rs, "Incorrect UInt32 or UInt64"); } if (InFile_Open(&inStream.file, args[2]) != 0) return PrintError(rs, "Can not open input file"); if (numArgs > 3) { useOutFile = True; if (OutFile_Open(&outStream.file, args[3]) != 0) return PrintError(rs, "Can not open output file"); } else if (encodeMode) PrintUserError(rs); if (encodeMode) { UInt64 fileSize; File_GetLength(&inStream.file, &fileSize); res = Encode(&outStream.s, &inStream.s, fileSize, rs); } else { res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(rs, kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(rs, kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError(rs, kCantWriteMessage); else if (res == SZ_ERROR_READ) return PrintError(rs, kCantReadMessage); return PrintErrorNumber(rs, res); } return 0; } int MY_CDECL main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/LzmaUtil.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\7zFile.c # End Source File # Begin Source File SOURCE=..\7zFile.h # End Source File # Begin Source File SOURCE=..\7zStream.c # End Source File # Begin Source File SOURCE=..\7zVersion.h # End Source File # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\CpuArch.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/LzmaUtil.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/makefile ================================================ MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/LzmaUtil/makefile.gcc ================================================ PROG = lzma CC = gcc LIB = liblzma.a RM = rm -f CFLAGS = -c -O2 -Wall AR = ar RANLIB = ranlib OBJS = \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ LzmaLib.o \ 7zFile.o \ 7zStream.o \ all: $(PROG) $(PROG): LzmaUtil.o $(LIB) $(CC) -o $(PROG) $(LDFLAGS) $< $(LIB) LzmaUtil.o: LzmaUtil.c $(CC) $(CFLAGS) LzmaUtil.c $(LIB): $(OBJS) rm -f $@ $(AR) rcu $@ $(OBJS) $(RANLIB) $@ Alloc.o: ../Alloc.c $(CC) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CC) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CC) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CC) $(CFLAGS) ../LzmaEnc.c LzmaLib.o: ../LzmaLib.c $(CC) $(CFLAGS) ../LzmaLib.c 7zFile.o: ../7zFile.c $(CC) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CC) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) *.o *.a ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Threads.c ================================================ /* Threads.c -- multithreading library 2008-08-05 Igor Pavlov Public domain */ #include "Threads.h" #include <process.h> static WRes GetError() { DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return 0; } WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(thread->handle); } WRes WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } WRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } WRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return HandleToWRes(p->handle); } WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return HandleToWRes(p->handle); } WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Threads.h ================================================ /* Threads.h -- multithreading library 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); WRes Thread_Wait(CThread *thread); WRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); WRes Event_Set(CEvent *event); WRes Event_Reset(CEvent *event); WRes Event_Wait(CEvent *event); WRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include <stddef.h> #ifdef _WIN32 #include <windows.h> #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zDecode.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnpackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnpackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _db.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &db = _db; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = db.Folders[folderIndex]; UInt64 unpackSize = folderInfo.GetUnpackSize(); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; // Count partial_folder_size // efi.UnpackSize += unpackSize; // importantTotalUnpacked += unpackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnpacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnpacked = 0; UInt64 totalFolderUnpacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnpacked += totalFolderUnpacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnpacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnpacked = efi.UnpackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &db = volume.Database; #else const CArchiveDatabaseEx &db = _db; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = db.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&db, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = db.Folders[folderIndex]; totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef _NO_CRYPTO bool passwordIsDefined; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &db.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; UInt64 fileSize = fi.Size; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fi.CrcDefined && _checkCrc) digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/CpuArch.h" } #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _db.Files.Size(); return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidPhySize, VT_UI8}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidOffset, VT_UI8} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _db.Folders.Size(); i++) { const CFolder &f = _db.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) { UInt64 value; if (v.GetItem(index, value)) { FILETIME ft; ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); prop = ft; } } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { case kpidPath: if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; case kpidIsDir: prop = item.IsDir; break; case kpidSize: { prop = item.Size; // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _db.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; case kpidEncrypted: prop = IsEncrypted(index2); break; case kpidIsAnti: prop = _db.IsItemAnti(index2); break; #ifndef _SFX case kpidMethod: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Props.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Props.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Props; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Props.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Props; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Props.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Props.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Props[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); #ifndef _NO_CRYPTO _passwordIsDefined = false; UString password; #endif HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO , getTextPassword, _passwordIsDefined #endif ); RINOK(result); _db.Fill(); _inStream = stream; } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); return S_OK; COM_TRY_END } #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _db; #ifndef _NO_CRYPTO bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif DECL_EXTERNAL_CODECS_VARS }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = (UInt32)kNumFastBytesForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = (UInt32)kDictionaryForHeaders; oneMethodInfo.Props.Add(prop); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Props = oneMethodInfo.Props; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Props.Size(); j++) { const CProp &prop = methodFull.Props[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) { ft = 0; ftDefined = false; if (!writeTime) return S_OK; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream != 0) db = &_db; #endif CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem ui; ui.NewProperties = IntToBool(newProperties); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; if (ui.IndexInArchive != -1) { const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; ui.Size = fi.Size; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } if (ui.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) nameIsDefined = false; else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { ui.Name = NItemName::MakeLegalName(prop.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } if (ui.NewData) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } updateItems.Add(ui); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef _NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if(encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; options.HeaderOptions.WriteATime = WriteATime; options.HeaderOptions.WriteMTime = WriteMTime; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; COutArchive archive; CArchiveDatabase newDatabase; HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, archive, newDatabase, outStream, updateCallback, options); RINOK(res); updateItems.ClearAndFree(); return archive.WriteDatabase(EXTERNAL_CODECS_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttributes, kComment, kEncodedHeader, kStartPos, kDummy }; } }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" } #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { static void BoolVector_Fill_False(CBoolVector &v, int size) { v.Clear(); v.Reserve(size); for (int i = 0; i < size; i++) v.Add(false); } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) { if (index >= (UInt32)v.Size()) return true; bool res = v[index]; v[index] = true; return res; } bool CFolder::CheckStructure() const { const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax const int kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); int i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; BoolVector_Fill_False(v, UnpackSizes.Size()); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; int i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { CIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; const CCoderInfo &coder = Coders[i]; for (j = 0; j < coder.NumInStreams; j++) inStreamToCoder.Add(i); for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } for (i = 0; i < kMaskSize; i++) for (int j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; for (i = 0; i < kMaskSize; i++) if (((1 << i) & mask[i]) != 0) return false; return true; } class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); coder.Props.SetCapacity((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bp; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { folder.PackStreams.Add(i); break; } if (folder.PackStreams.Size() != 1) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { BoolVector_Fill_False(packCRCsDefined, numPackStreams); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for (CNum i = 0; i < numPackStreams; i++) packCRCs.Add(0); } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnpackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CBoolVector crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnpackCRCDefined = crcsDefined[i]; folder.UnpackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { numUnpackStreamsInFolders.Clear(); numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnpackStreamsInFolders.IsEmpty()) for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(1); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CBoolVector digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { BoolVector_Fill_False(digestsDefined, numDigestsTotal); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) digests.Add(0); } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnpackInfo: { ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for (int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles) { ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Values.Reserve(numFiles); for (int i = 0; i < numFiles; i++) { UInt64 t = 0; if (v.Defined[i]) t = ReadUInt64(); v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArchiveInfo.DataStartPosition, db.PackSizes, db.PackCRCsDefined, db.PackCRCs, db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for (int i = 0; i < db.Folders.Size(); i++) { db.NumUnpackStreamsVector.Add(1); CFolder &folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digestsDefined.Add(folder.UnpackCRCDefined); digests.Add(folder.UnpackCRC); } } db.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!db.PackSizes.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; BoolVector_Fill_False(emptyStreamVector, (int)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); size_t ppp = _inByteBack->_pos; bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (int i = 0; i < db.Files.Size(); i++) _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; file.AttribDefined = boolVector[i]; if (file.AttribDefined) file.Attrib = ReadUInt32(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; BoolVector_Fill_False(emptyFileVector, numEmptyStreams); BoolVector_Fill_False(antiFileVector, numEmptyStreams); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThrowIncorrect(); addPropIdToList = false; break; } default: addPropIdToList = isKnownType = false; } if (isKnownType) { if(addPropIdToList) db.ArchiveInfo.FileInfoPopIDs.Add(type); } else SkeepData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; CNum numAntiItems = 0; for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti.Add(isAnti); } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; public: size_t _pos; void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnpackSizes; UInt32 UnpackCRC; bool UnpackCRCDefined; CFolder(): UnpackCRCDefined(false) {} UInt64 GetUnpackSize() const // test it { if (UnpackSizes.IsEmpty()) return 0; for (int i = UnpackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnpackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } bool CheckStructure() const; }; struct CUInt64DefVector { CRecordVector<UInt64> Values; CRecordVector<bool> Defined; void Clear() { Values.Clear(); Defined.Clear(); } void ReserveDown() { Values.ReserveDown(); Values.ReserveDown(); } bool GetItem(int index, UInt64 &value) const { if (index < Defined.Size() && Defined[index]) { value = Values[index]; return true; } value = 0; return false; } void SetItem(int index, bool defined, UInt64 value) { while (index >= Defined.Size()) Defined.Add(false); Defined[index] = defined; if (!defined) return; while (index >= Values.Size()) Values.Add(0); Values[index] = value; } bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } }; struct CFileItem { UInt64 Size; UInt32 Attrib; UInt32 Crc; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; bool AttribDefined; CFileItem(): HasStream(true), IsDir(false), CrcDefined(false), AttribDefined(false) {} void SetAttrib(UInt32 attrib) { AttribDefined = true; Attrib = attrib; } }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnpackStreamsVector; CObjectVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnpackStreamsVector.Clear(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); } void ReserveDown() { PackSizes.ReserveDown(); PackCRCsDefined.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); Files.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { int size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsSolid() const { for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } void SetItemAnti(int index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; void AddFile(const CFileItem &file, const CFileItem2 &file2); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if (processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 3; return WriteDirect(buf, 8); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[24]; SetUInt64(buf + 4, h.NextHeaderOffset); SetUInt64(buf + 12, h.NextHeaderSize); SetUInt32(buf + 20, h.NextHeaderCRC); SetUInt32(buf, CrcCalc(buf + 4, 20)); return WriteDirect(buf, 24); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) { _outByte.WriteByte(b); _crc = CRC_UPDATE_BYTE(_crc, b); } else _outByte2.WriteByte(b); } void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } WriteByte(firstByte); for (;i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef _7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propsSize = coder.Props.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propsSize != 0) ? 0x20 : 0 ); WriteByte(b); WriteBytes(longID, idSize); if (isComplex) { WriteNumber(coder.NumInStreams); WriteNumber(coder.NumOutStreams); } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; WriteNumber(bindPair.InIndex); WriteNumber(bindPair.OutIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { WriteNumber(folder.PackStreams[i]); } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for (int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } void COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for (i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); if (numDefined == digestsDefined.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(digestsDefined); } for (i = 0; i < digests.Size(); i++) if (digestsDefined[i]) WriteUInt32(digests[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); for (int i = 0; i < packSizes.Size(); i++) WriteNumber(packSizes[i]); WriteHashDigests(packCRCsDefined, packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); for (int i = 0; i < folders.Size(); i++) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); int i; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnpackSizes.Size(); j++) WriteNumber(folder.UnpackSizes[j]); } CRecordVector<bool> unpackCRCsDefined; CRecordVector<UInt32> unpackCRCs; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unpackCRCsDefined.Add(folder.UnpackCRCDefined); unpackCRCs.Add(folder.UnpackCRC); } WriteHashDigests(unpackCRCsDefined, unpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { WriteByte(NID::kSubStreamsInfo); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } } bool needFlag = true; CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) { if (j + 1 != numUnpackStreamsInFolders[i]) { if (needFlag) WriteByte(NID::kSize); needFlag = false; WriteNumber(unpackSizes[index]); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnpackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } WriteHashDigests(digestsDefined2, digests2); WriteByte(NID::kEnd); } void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) { return; } /* 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } */ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) { const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8; const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); WriteByte(type); WriteNumber(dataSize); if (numDefined == v.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(v); } WriteByte(0); } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { int numDefined = 0; int i; for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) numDefined++; if (numDefined == 0) return; WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) WriteUInt64(v.Values[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnpackCRCDefined = true; folderItem.UnpackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } void COutArchive::WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; headerOffset = packedSize; WriteByte(NID::kHeader); // Archive Properties if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCsDefined, db.PackCRCs); WriteUnpackInfo(db.Folders); CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digestsDefined.Add(file.CrcDefined); digests.Add(file.Crc); } WriteSubStreamsInfo( db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.Reserve(db.Files.Size()); int numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) if (db.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { WriteByte(NID::kEmptyStream); WriteNumber((emptyStreamVector.Size() + 7) / 8); WriteBoolVector(emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDir); if (!file.IsDir) numEmptyFiles++; bool isAnti = db.IsItemAnti(i); antiVector.Add(isAnti); if (isAnti) numAntiItems++; } } if (numEmptyFiles > 0) { WriteByte(NID::kEmptyFile); WriteNumber((emptyFileVector.Size() + 7) / 8); WriteBoolVector(emptyFileVector); } if (numAntiItems > 0) { WriteByte(NID::kAnti); WriteNumber((antiVector.Size() + 7) / 8); WriteBoolVector(antiVector); } } } { /* ---------- Names ---------- */ int numDefined = 0; size_t namesDataSize = 0; for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; if (!name.IsEmpty()) numDefined++; namesDataSize += (name.Length() + 1) * 2; } if (numDefined > 0) { namesDataSize++; SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; for (int t = 0; t <= name.Length(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } } } } if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); int numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; boolVector.Add(defined); if (defined) numDefined++; } if (numDefined > 0) { WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (file.AttribDefined) WriteUInt32(file.Attrib); } } } WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (db.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { bool encodeHeaders = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, headerOptions, headerOffset); if (encodeHeaders) { CByteBuffer buf; buf.SetCapacity(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, headerOptions, headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, (const Byte *)buf, _countSize, packSizes, folders)); _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>()); WriteUnpackInfo(folders); WriteByte(NID::kEnd); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const { file = Files[index]; file2.CTimeDefined = CTime.GetItem(index, file2.CTime); file2.ATimeDefined = ATime.GetItem(index, file2.ATime); file2.MTimeDefined = MTime.GetItem(index, file2.MTime); file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); file2.IsAnti = IsItemAnti(index); } void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) { int index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); SetItemAnti(index, file2.IsAnti); Files.Add(file); } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; bool WriteCTime; bool WriteATime; bool WriteMTime; CHeaderOptions(): CompressMainHeader(true), WriteCTime(false), WriteATime(false), WriteMTime(true) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); void WriteUnpackInfo(const CObjectVector<CFolder> &folders); void WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); void WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCTime, NULL, kpidCTime, VT_FILETIME}, { NID::kMTime, NULL, kpidMTime, VT_FILETIME}, { NID::kATime, NULL, kpidATime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttrib, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, #ifndef _SFX { 97, NULL, kpidEncrypted, VT_BOOL}, { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if ((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // 7zUpdate.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnpackStreamsVector[i1], db.NumUnpackStreamsVector[i2])); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = ui.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = ui.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kMatchFinderForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = kDictionaryForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Props.Add(prop); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData) continue; if (!ui.HasStream()) continue; if (useFilters) { const UString name = ui.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); for (int i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (db != 0) { for(i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; for (CNum fileIndex = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fileIndex++) { if (db->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnpackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)db); } //////////////////////////// RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; if (numSolidFiles == 1) { if (ui.Size > inSizeForReduce) inSizeForReduce = ui.Size; } else inSizeForReduce += ui.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = db->Folders[folderIndex]; CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; db->GetFile(fi, file, file2); if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewProperties) { CFileItem uf; FromUpdateItemToFileItem(ui, uf, file2); uf.Size = file.Size; uf.Crc = file.Crc; uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; } } newDatabase.AddFile(file, file2); } } } folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = ui.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; if (file.Size != 0) { file.CrcDefined = true; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } newDatabase.AddFile(file, file2); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; } } groups.ClearAndFree(); { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1) if (db->Files[ui.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); newDatabase.AddFile(file, file2); } } newDatabase.ReserveDown(); return S_OK; } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { return Update2( EXTERNAL_CODECS_LOC_VARS inStream, db, updateItems, archive, newDatabase, seqOutStream, updateCallback, options); } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { int IndexInArchive; int IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; UInt32 Attrib; bool NewData; bool NewProperties; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL && result != S_FALSE) return result; } RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../../ICoder.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Props.Size(); j++) if (oneMethodInfo.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; oneMethodInfo.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); prop.Id = (name.CompareNoCase(L"D") == 0) ? NCoderPropID::kDictionarySize : NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { bool isSolid; switch(value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; WriteCTime = false; WriteATime = false; WriteMTime = true; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) { RINOK(SetBoolProperty(_encryptHeaders, value)); _encryptHeadersSpecified = true; return S_OK; } if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp prop; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); prop.Id = NCoderPropID::kDictionarySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(1).CompareNoCase(L"C") == 0) { UInt32 blockSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); prop.Id = NCoderPropID::kBlockSize; prop.Value = blockSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); prop.Id = NCoderPropID::kUsedMemorySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); } return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (value.boolVal != VARIANT_FALSE); return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } #define INTERFACE_IArchiveOpenCallback(x) \ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { INTERFACE_IArchiveOpenCallback(PURE); }; #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { INTERFACE_IArchiveExtractCallback(PURE) }; #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { INTERFACE_IArchiveOpenVolumeCallback(PURE); }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ Int32 *newData, /*1 - new data, 0 - old data */ \ Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ ) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { INTERFACE_IArchiveUpdateCallback(PURE); }; #define INTERFACE_IArchiveUpdateCallback2(x) \ INTERFACE_IArchiveUpdateCallback(x) \ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { INTERFACE_IArchiveUpdateCallback2(PURE); }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp ================================================ // LzmaArcRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "LzmaHandler.h" static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } static CArcInfo g_ArcInfo = { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; REGISTER_ARC(Lzma) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp ================================================ // LzmaFiltersDecode.cpp #include "StdAfx.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; HRESULT CDecoder::Code( DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress) { *inProcessedSize = (UInt64)(Int64)-1; if (block.FilterMethod > 1) return E_NOTIMPL; if (!_lzmaDecoder) { RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); if (_lzmaDecoder == 0) return E_NOTIMPL; } { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); } bool filteredMode = (block.FilterMethod == 1); CMyComPtr<ICompressSetOutStream> setOutStream; if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { RINOK(flush->Flush()); } RINOK(setOutStream->ReleaseOutStream()); } CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); if (getInStreamProcessedSize) { RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); } return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h ================================================ // LzmaFiltersDecode.h #ifndef __LZMA_FILTERS_DECODE_H #define __LZMA_FILTERS_DECODE_H #include "../../Common/CreateCoder.h" #include "LzmaItem.h" namespace NArchive { namespace NLzma { class CDecoder { CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; public: HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.cpp ================================================ // LzmaHandler.cpp #include "StdAfx.h" #include "LzmaHandler.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/DummyOutStream.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { STATPROPSTG kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_UI1} }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = 1; return S_OK; } static void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s + MyStringLen(s)); } static void DictSizeToString(UInt32 value, wchar_t *s) { for (int i = 0; i <= 31; i++) if ((UInt32(1) << i) == value) { ConvertUInt32ToString(i, s); return; } wchar_t c = L'b'; if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = L'm'; } else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = L'k'; } ConvertUInt32ToString(value, s); int p = MyStringLen(s); s[p++] = c; s[p++] = L'\0'; } static void MyStrCat(wchar_t *d, const wchar_t *s) { MyStringCopy(d + MyStringLen(d), s); } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { if (index != 0) return E_INVALIDARG; NWindows::NCOM::CPropVariant propVariant; switch(propID) { case kpidSize: if (m_StreamInfo.HasUnpackSize()) propVariant = (UInt64)m_StreamInfo.UnpackSize; break; case kpidPackSize: propVariant = (UInt64)m_PackSize; break; case kpidMethod: { wchar_t s[64]; s[0] = '\0'; if (m_StreamInfo.IsThereFilter) { const wchar_t *f; if (m_StreamInfo.FilterMethod == 0) f = L"Copy"; else if (m_StreamInfo.FilterMethod == 1) f = L"BCJ"; else f = L"Unknown"; MyStrCat(s, f); MyStrCat(s, L" "); } MyStrCat(s, L"LZMA:"); DictSizeToString(m_StreamInfo.GetDicSize(), s); propVariant = s; break; } } propVariant.Detach(value); return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* openArchiveCallback */) { { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); if (res != S_OK) return S_FALSE; Byte b; RINOK(ReadStream_FALSE(inStream, &b, 1)); if (b != 0) return S_FALSE; UInt64 endPos; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); m_Stream = inStream; } return S_OK; } STDMETHODIMP CHandler::Close() { m_Stream.Release(); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN bool allFilesMode = (numItems == UInt32(-1)); if (!allFilesMode) { if (numItems == 0) return S_OK; if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); RINOK(extractCallback->SetTotal(m_PackSize)); UInt64 currentTotalPacked = 0; CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); { CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(); if(!testMode && !realOutStream) return S_OK; extractCallback->PrepareOperation(askMode); } CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); CDecoder decoder; RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); UInt64 streamPos = m_StreamStartPosition; Int32 opRes = NArchive::NExtract::NOperationResult::kOK; bool firstItem = true; for (;;) { CHeader st; HRESULT result = ReadStreamHeader(m_Stream, st); if (result != S_OK) { if (firstItem) return E_FAIL; break; } firstItem = false; lps->OutSize = outStreamSpec->GetSize(); lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); streamPos += st.GetHeaderSize(); UInt64 packProcessed; { result = decoder.Code( EXTERNAL_CODECS_VARS st, m_Stream, outStream, &packProcessed, progress); if (result == E_NOTIMPL) { opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; } if (result == S_FALSE) { opRes = NArchive::NExtract::NOperationResult::kDataError; break; } RINOK(result); } if (packProcessed == (UInt64)(Int64)-1) break; RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); currentTotalPacked += packProcessed; streamPos += packProcessed; } outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.h ================================================ // Lzma/Handler.h #ifndef __GZIP_HANDLER_H #define __GZIP_HANDLER_H #include "Common/MyCom.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #include "LzmaIn.h" namespace NArchive { namespace NLzma { // const UInt64 k_LZMA = 0x030101; class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(IInArchive) QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Open)(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); STDMETHOD(Close)(); STDMETHOD(GetNumberOfItems)(UInt32 *numItems); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); UString GetMethodString(); public: CHandler() { } private: CHeader m_StreamInfo; UInt64 m_StreamStartPosition; UInt64 m_PackSize; CMyComPtr<IInStream> m_Stream; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaIn.cpp ================================================ // Archive/LzmaIn.cpp #include "StdAfx.h" #include "LzmaIn.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace NLzma { static bool CheckDictSize(const Byte *p) { UInt32 dicSize = GetUi32(p); int i; for (i = 1; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return false; } HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) { Byte sig[5 + 9]; RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); const Byte kMaxProp0Val = 5 * 5 * 9 - 1; if (sig[0] > kMaxProp0Val) return S_FALSE; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i]; block.IsThereFilter = false; block.FilterMethod = 0; if (!CheckDictSize(sig + 1)) { if (sig[0] > 1 || sig[1] > kMaxProp0Val) return S_FALSE; block.IsThereFilter = true; block.FilterMethod = sig[0]; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i + 1]; if (!CheckDictSize(block.LzmaProps + 1)) return S_FALSE; RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); } UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); block.UnpackSize = GetUi64(sig + unpOffset); if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) return S_FALSE; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaIn.h ================================================ // Archive/LzmaIn.h #ifndef __ARCHIVE_LZMA_IN_H #define __ARCHIVE_LZMA_IN_H #include "LzmaItem.h" #include "../../IStream.h" namespace NArchive { namespace NLzma { HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/LzmaItem.h ================================================ // Archive/LzmaItem.h #ifndef __ARCHIVE_LZMA_ITEM_H #define __ARCHIVE_LZMA_ITEM_H #include "Common/Types.h" #include "../../../../C/CpuArch.h" namespace NArchive { namespace NLzma { struct CHeader { UInt64 UnpackSize; bool IsThereFilter; Byte FilterMethod; Byte LzmaProps[5]; UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Lzma/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Split/SplitHandler.cpp ================================================ // SplitHandler.cpp #include "StdAfx.h" #include "Common/ComTry.h" #include "Common/Defs.h" #include "Common/NewHandler.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/MultiStream.h" #include "SplitHandler.h" using namespace NWindows; using namespace NTime; namespace NArchive { namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO class CSeqName { public: UString _unchangedPart; UString _changedPart; bool _splitStyle; UString GetNextName() { UString newName; if (_splitStyle) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { c = 'a'; newName = c + newName; continue; } else if (c == 'Z') { c = 'A'; newName = c + newName; continue; } c++; if ((c == 'z' || c == 'Z') && i == 0) { _unchangedPart += c; wchar_t newChar = (c == 'z') ? L'a' : L'A'; newName.Empty(); numLetters++; for (int k = 0; k < numLetters; k++) newName += newChar; break; } newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } else { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } _changedPart = newName; return _unchangedPart + _changedPart; } }; STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); if (openArchiveCallback == 0) return S_FALSE; // try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback) != S_OK) return S_FALSE; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; _name = prop.bstrVal; } int dotPos = _name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { prefix = _name.Left(dotPos + 1); ext = _name.Mid(dotPos + 1); } else ext = _name; UString extBig = ext; extBig.MakeUpper(); CSeqName seqName; int numLetters = 2; bool splitStyle = false; if (extBig.Right(2) == L"AA") { splitStyle = true; while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != 'A') break; numLetters++; } } else if (ext.Right(2) == L"01") { while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Length()) return S_FALSE; } else return S_FALSE; _streams.Add(stream); seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); seqName._changedPart = ext.Right(numLetters); seqName._splitStyle = splitStyle; if (prefix.Length() < 1) _subName = L"file"; else _subName = prefix.Left(prefix.Length() - 1); _totalSize = 0; UInt64 size; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName = seqName.GetNextName(); CMyComPtr<IInStream> nextStream; HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } } /* catch(...) { return S_FALSE; } */ return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { _sizes.Clear(); _streams.Clear(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; } prop.Detach(value); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) { COM_TRY_BEGIN if (numItems != UInt32(-1)) { if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; extractCallback->SetTotal(_totalSize); /* CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) return E_FAIL; */ UInt64 currentTotalSize = 0; UInt64 currentItemSize; RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = 0; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->PrepareOperation(askMode)); if (testMode) { RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); return S_OK; } if (!testMode && (!realOutStream)) return S_OK; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); currentItemSize = copyCoderSpec->TotalSize; } realOutStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; for (int i = 0; i < _streams.Size(); i++) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Split/SplitHandler.h ================================================ // Split/Handler.h #ifndef __SPLIT_HANDLER_H #define __SPLIT_HANDLER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../IArchive.h" namespace NArchive { namespace NSplit { class CHandler: public IInArchive, public IInArchiveGetStream, // public IOutArchive, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); private: UString _subName; UString _name; CObjectVector<CMyComPtr<IInStream> > _streams; CRecordVector<UInt64> _sizes; UInt64 _totalSize; }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Split/SplitHandlerOut.cpp ================================================ // Split/OutHandler.cpp #include "StdAfx.h" #include "SplitHandler.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" using namespace NWindows; namespace NArchive { namespace NSplit { /* STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN if (numItems != 1) return E_INVALIDARG; UInt64 volumeSize = 0; CMyComPtr<IArchiveUpdateCallback2> callback2; updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&callback2); RINOK(callback2->GetVolumeSize(0, &volumeSize)); Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; UInt32 fileIndex = 0; RINOK(updateCallback->GetUpdateItemInfo(fileIndex, &newData, &newProperties, &indexInArchive)); if (newProperties != 0) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } } UInt64 newSize; bool thereIsCopyData = false; if (newData != 0) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; newSize = prop.uhVal.QuadPart; } else thereIsCopyData = true; UInt64 pos = 0; while(pos < newSize) { } return S_OK; COM_TRY_END } */ }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Split/SplitRegister.cpp ================================================ // SplitRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "SplitHandler.h" static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } /* #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } #else #define CreateArcOut 0 #endif */ static CArcInfo g_ArcInfo = { L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; REGISTER_ARC(Split) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/Split/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Archive/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwapRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderOpt.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # Begin Group "LZM" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaItem.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ LZM_OBJS = \ $O\LzmaArcRegister.obj \ $O\LzmaFiltersDecode.obj \ $O\LzmaHandler.obj \ $O\LzmaIn.obj \ SPLIT_OBJS = \ $O\SplitHandler.obj \ $O\SplitHandlerOut.obj \ $O\SplitRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(LZM_OBJS) \ $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp $(COMPL) $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } RINOK(WriteStream(outStream, _buffer, size)); _nowPos64 += size; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { size_t processedSize = kBufferSize - bufferPos; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } RINOK(WriteStream(_outStream, _buffer, _bufferPos)); _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; size_t processedSizeTemp = kBufferSize - _bufferPos; RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); _bufferPos = _bufferPos + (UInt32)processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if (_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } UInt32 ReadBytes(Byte *buf, UInt32 size) { if ((UInt32)(_bufferLimit - _buffer) >= size) { for (UInt32 i = 0; i < size; i++) buf[i] = _buffer[i]; _buffer += size; return size; } for (UInt32 i = 0; i < size; i++) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return i; buf[i] = *_buffer++; } return size; } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; if (processedSize != NULL) *processedSize = 0; if (size > _size) { size = (UInt32)_size; if (size == 0) { _overflow = true; return E_FAIL; } } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize != NULL) *processedSize = size; return result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size) { _size = size; _overflow = false; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "MethodProps.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProps = method.Props.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProps != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; HRESULT res = S_OK; try { for (int i = 0; i < numProps; i++) { const CProp &prop = method.Props[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "../../Common/MyVector.h" #include "../../Windows/PropVariant.h" #include "MethodId.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Props; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { memcpy(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(data, _dataPointer + _pos, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memcpy(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, (size_t)size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return (rem == size ? S_OK : E_FAIL); } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); WRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/Bcj2Coder.cpp ================================================ // Bcj2Coder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/Bcj2Coder.h ================================================ // Bcj2Coder.h #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "RangeCoderBit.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/Bcj2Register.cpp ================================================ // Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BcjCoder.cpp ================================================ // BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BcjCoder.h ================================================ // BcjCoder.h #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H extern "C" { #include "../../../C/Bra.h" } #include "BranchCoder.h" struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BcjRegister.cpp ================================================ // BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BranchCoder.h ================================================ // BranchCoder.h #ifndef __COMPRESS_BRANCH_CODER_H #define __COMPRESS_BRANCH_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BranchMisc.cpp ================================================ // BranchMisc.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Bra.h" } #include "BranchMisc.h" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BranchMisc.h ================================================ // BranchMisc.h #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) MyClassA(BC_ARMT, 0x07, 1) MyClassA(BC_PPC, 0x02, 5) MyClassA(BC_SPARC, 0x08, 5) MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMT) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/ByteSwap.h ================================================ // ByteSwap.h #ifndef __COMPRESS_BYTE_SWAP_H #define __COMPRESS_BYTE_SWAP_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPY_CODER_H #define __COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/CopyRegister.cpp ================================================ // CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaEncoder.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "LzmaUtil" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #include "LzmaBenchCon.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif extern "C" { #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/LzmaUtil/Lzma86Dec.h" #include "../../../../C/LzmaUtil/Lzma86Enc.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } static void ParseUInt32(const CParser &parser, int index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) IncorrectCommand(); } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictDefined = false; UInt32 dict = (UInt32)-1; if(parser[NKey::kDict].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dict); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; size_t inSize = (size_t)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; Byte *outBuffer = 0; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictDefined) dict = 1 << 23; int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictDefined) dict = 1 << 23; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = (BSTR)(const wchar_t *)mf; props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; int numProps = kNumPropsMax; if (!mcDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; decoderSpec->FinishStream = true; const UInt32 kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int MY_CDECL main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" } #include "../../../Common/MyCom.h" #ifdef BENCH_MT #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #else #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLzma::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLzma::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe LIBS = $(LIBS) user32.lib CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ LZMA_OPT_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra86.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ C_LZMAUTIL_OBJS = \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ OBJS = \ $O\StdAfx.obj \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(C_OBJS) \ $(C_LZMAUTIL_OBJS) \ $O\FileStreams.obj \ $O\FileIO.obj \ !include "../../../Build.mak" $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZMAUTIL_OBJS): ../../../../C/LzmaUtil/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaDecoder.o \ LzmaEncoder.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ Bra86.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ Lzma86Dec.o \ Lzma86Enc.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaDecoder.o: ../LzmaDecoder.cpp $(CXX) $(CFLAGS) ../LzmaDecoder.cpp LzmaEncoder.o: ../LzmaEncoder.cpp $(CXX) $(CFLAGS) ../LzmaEncoder.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c Bra86.o: ../../../../C/Bra86.c $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c LzFind.o: ../../../../C/LzFind.c $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c LzmaDec.o: ../../../../C/LzmaDec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c LzmaEnc.o: ../../../../C/LzmaEnc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c Lzma86Dec.o: ../../../../C/LzmaUtil/Lzma86Dec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Dec.c Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma86Enc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LzmaDecoder.cpp ================================================ // LzmaDecoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) { LzmaDec_Construct(&_state); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); MyFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; LzmaDec_Init(&_state); _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.dicPos; SizeT curSize = _state.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; } #endif }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LzmaDecoder.h ================================================ // LzmaDecoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H extern "C" { #include "../../../C/LzmaDec.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif bool FinishStream; CDecoder(); virtual ~CDecoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LzmaEncoder.cpp ================================================ // LzmaEncoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; // case SZ_ERROR_THREAD: return E_FAIL; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(void *object, void *data, size_t *size) { UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); *size = curSize; return (SRes)res; } static size_t MyWrite(void *object, const void *data, size_t size) { CSeqOutStream *p = (CSeqOutStream *)object; p->Res = WriteStream(p->RealStream, data, size); if (p->Res != 0) return 0; return size; } static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } static void SzFree(void *, void *address) { MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { _seqInStream.SeqInStream.Read = MyRead; _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) throw 1; } CEncoder::~CEncoder() { if (_encoder != 0) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; switch (propIDs[i]) { case NCoderPropID::kNumFastBytes: if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; case NCoderPropID::kMatchFinderCycles: if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; case NCoderPropID::kAlgorithm: if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; case NCoderPropID::kDictionarySize: if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; case NCoderPropID::kPosStateBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; case NCoderPropID::kLitPosBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; case NCoderPropID::kLitContextBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; case NCoderPropID::kMultiThread: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; case NCoderPropID::kMatchFinder: if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; default: return E_INVALIDARG; } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte props[LZMA_PROPS_SIZE]; size_t size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); return WriteStream(outStream, props, size); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _seqOutStream.RealStream = outStream; _seqOutStream.Res = S_OK; return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _seqOutStream.RealStream.Release(); return S_OK; } typedef struct _CCompressProgressImp { ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; } CCompressProgressImp; #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) { CCompressProgressImp *p = (CCompressProgressImp *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { CCompressProgressImp progressImp; progressImp.p.Progress = CompressProgress; progressImp.Progress = progress; progressImp.Res = SZ_OK; _seqInStream.RealStream = inStream; SetOutStream(outStream); SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); ReleaseOutStream(); if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) return _seqOutStream.Res; if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) return progressImp.Res; return SResToHRESULT(res); } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LzmaEncoder.h ================================================ // LzmaEncoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H extern "C" { #include "../../../C/LzmaEnc.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { struct CSeqInStream { ISeqInStream SeqInStream; ISequentialInStream *RealStream; }; struct CSeqOutStream { ISeqOutStream SeqOutStream; CMyComPtr<ISequentialOutStream> RealStream; HRESULT Res; }; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; CSeqInStream _seqInStream; CSeqOutStream _seqOutStream; public: CEncoder(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/LzmaRegister.cpp ================================================ // LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/RangeCoder.h ================================================ // Compress/RangeCoder.h #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) { Range >>= 1; Low += Range & (0 - ((value >> numBits) & 1)); if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/RangeCoderBit.h ================================================ // Compress/RangeCoderBit.h #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 4; const int kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/Compress/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kBlockSize, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define INTERFACE_IProgress(x) \ STDMETHOD(SetTotal)(UInt64 total) x; \ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ DECL_INTERFACE(IProgress, 0, 5) { INTERFACE_IProgress(PURE) }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_7ZIP_VERSION "7-Zip 4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/PropID.h ================================================ // PropID.h #ifndef __7ZIP_PROPID_H #define __7ZIP_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; UInt32 Attrib; bool isDir; bool AttribDefined; bool MTimeDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (NFile::NFind::FindFile(fullProcessedPath, fi)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.MTimeDefined) _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if (newData != NULL) *newData = BoolToInt(true); if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) *indexInArchive = (UInt32)-1; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: prop = dirItem.Name; break; case kpidIsDir: prop = dirItem.isDir(); break; case kpidSize: prop = dirItem.Size; break; case kpidAttrib: prop = dirItem.Attrib; break; case kpidCTime: prop = dirItem.CTime; break; case kpidATime: prop = dirItem.ATime; break; case kpidMTime: prop = dirItem.MTime; break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if (dirItem.isDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////////////////// // Main function int MY_CDECL main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; command.MakeLower(); UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.Compare("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem di; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(name, fi)) { PrintString(UString(L"Can't find file") + name); return 1; } di.Attrib = fi.Attrib; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Name = name; di.FullPath = name; dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.Compare("l") == 0) listCommand = true; else if (command.Compare("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, #ifndef _NO_CRYPTO kPassword, #endif kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, #ifndef _NO_CRYPTO { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, #endif { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for (int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for (int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for (int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); UStringVector archivePaths; { CDirItems dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } for (int i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) archivePaths.Add(dirItems.GetPhyPath(i)); } } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; int i; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if (parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if (options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if (options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO bool PasswordEnabled; UString Password; #endif bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcMTimeDefault = utcMTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDir) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) INTERFACE_IArchiveExtractCallback(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _encrypted; struct CProcessedFileInfo { FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attributes; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool IsDir; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcMTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), WriteMTime(true), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch(propID) { case kpidName: prop = _subArchiveName; break; } else switch(propID) { case kpidName: prop = _fileInfo.Name; break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; case kpidCTime: prop = _fileInfo.CTime; break; case kpidATime: prop = _fileInfo.ATime; break; case kpidMTime: prop = _fileInfo.MTime; break; } prop.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (ReOpenCallback) { CMyComPtr<ICryptoGetTextPassword> getTextPassword; ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" #ifdef _NO_CRYPTO #define INTERFACE_IOpenCallbackUI_Crypto(x) #else #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ #endif #define INTERFACE_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI { INTERFACE_IOpenCallbackUI(=0) }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L"~"; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" #include "../../Archive/IArchive.h" struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UInt32 Attrib; int PhyParent; int LogParent; CDirItem(): PhyParent(-1), LogParent(-1) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; public: CObjectVector<CDirItem> Items; int GetNumFolders() const { return Prefixes.Size(); } UString GetPhyPath(int index) const; UString GetLogPath(int index) const; int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; struct CArcItem { UInt64 Size; FILETIME MTime; UString Name; bool IsDir; bool SizeDefined; bool Censored; UInt32 IndexInServer; int TimeType; CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include <stdio.h> #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; di.Name = fi.Name; dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; int len = name.Length(); int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Length(); int totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; len -= name.Length(); memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; len -= s.Length(); memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } UString CDirItems::GetPhyPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } UString CDirItems::GetLogPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); for (;;) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParent, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; if (!NFind::FindFile(phyPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); UString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParentCur, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &curFolderName, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { const UString name2 = curFolderName + (wchar_t)kDirDelimiter; int parent = dirItems.AddPrefix(phyParent, logParent, name2); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fi.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); for (int ttt = 0; ; ttt++) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); const UString &name = fi.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", options.DefaultItemName); #ifdef _WIN32 outDir.TrimRight(); #endif if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.MTime, options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } res.TrimRight(); return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static const TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fi; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) if (!fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } #ifndef _SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int slashPos2 = arcPath.ReverseFind(L'.'); int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; for (int i = 0; i < Formats.Size(); i++) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) if (Formats[i].Name.CompareNoCase(arcType) == 0) return i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (int pos = 0; pos < arcType.Length();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) pos2 = arcType.Length(); const UString name = arcType.Mid(pos, pos2 - pos); int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = pos2 + 1; } return true; } #endif #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UInt32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) { result = defaultName; NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (arcTypeIndex >= 0) orderIndices.Add(arcTypeIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; Byte hash[1 << 16]; memset(hash, 0xFF, 1 << 16); Byte prevs[256]; if (orderIndices.Size() > 255) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < 2) continue; UInt32 v = sig[0] | ((UInt32)sig[1] << 8); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize--; for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[buf[pos] | ((UInt32)buf[pos + 1] << 8)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = buf[pos] | ((UInt32)buf[pos + 1] << 8); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + 1) if (TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif } for(int i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; RINOK(result); *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { if (formatIndices.Size() >= 3) return E_NOTIMPL; int arcTypeIndex = -1; if (formatIndices.Size() >= 1) arcTypeIndex = formatIndices[formatIndices.Size() - 1]; HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); if (formatIndices.Size() == 1) return S_OK; arcTypeIndex = -1; if (formatIndices.Size() >= 2) arcTypeIndex = formatIndices[formatIndices.Size() - 2]; HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || !getStream) return resSpec; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK || !subSeqStream) return resSpec; CMyComPtr<IInStream> subStream; result = subSeqStream.QueryInterface(IID_IInStream, &subStream); if (result != S_OK || !subStream) return resSpec; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return resSpec; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result != S_OK) return resSpec; return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, NULL, openCallback); int formatInfo; return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, formatIndices, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; SetCallback(fileName, NULL, openCallback, openCallbackNew); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; bool IsOpen; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCTime: case kpidATime: case kpidMTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttrib: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name[name.Length() - 1]; if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name = name.Left(name.Length() - 1); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/StdAfx.h ================================================ // stdafx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Time.h" #include "../../Common/FileStreams.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) { if (formatIndices.Size() > 1) return false; int arcTypeIndex = -1; if (formatIndices.Size() != 0) arcTypeIndex = formatIndices[0]; if (arcTypeIndex >= 0) MethodMode.FormatIndex = arcTypeIndex; else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; if (!arcInfo.UpdateEnabled) return false; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } /* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) { return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); } */ static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArcItem> &arcItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CDirItems &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! // CUpdateProduceCallbackImp upCallback(&arcItems, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); } UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); // check it: defaultItemName !!! if (ai.Name.IsEmpty()) ai.Name = defaultItemName; RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); { CPropVariant prop; RINOK(archive->GetProperty(i, kpidSize, &prop)); ai.SizeDefined = (prop.vt != VT_EMPTY); if (ai.SizeDefined) ai.Size = ConvertPropVariantToUInt64(prop); } { CPropVariant prop; RINOK(archive->GetProperty(i, kpidTimeType, &prop)); if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; switch(ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: break; default: return E_FAIL; } } } ai.IndexInServer = i; arcItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArcItem> &arcItems, CDirItems &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, arcItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) { return Callback->ScanProgress(numFolders, numFiles, path); } }; #ifdef _WIN32 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( ULONG_PTR ulUIParam, LPSTR lpszDelimChar, LPSTR lpszFilePaths, LPSTR lpszFileNames, ULONG ulReserved ); typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; #endif HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CDirItems dirItems; if (options.StdInMode) { CDirItem di; di.Name = options.StdInFileName; di.Size = (UInt64)(Int64)-1; di.Attrib = 0; NTime::GetCurUtcFileTime(di.MTime); di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArcItem> arcItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, arcItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArcItems(0), UpdatePairs(0), NewNames(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); } */ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData != NULL) *newData = BoolToInt(up.NewData); if (newProps != NULL) *newProps = BoolToInt(up.NewProps); if (indexInArchive != NULL) { *indexInArchive = (UInt32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = up.IsAnti; prop.Detach(value); return S_OK; } if (up.IsAnti) { switch(propID) { case kpidIsDir: case kpidPath: break; case kpidSize: prop = (UInt64)0; prop.Detach(value); return S_OK; default: prop.Detach(value); return S_OK; } } if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; } } else { if (propID == kpidPath) { if (up.NewNameIndex >= 0) { prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } if (up.ExistInArchive() && Archive) { UInt32 indexInArchive; if (ArcItems == 0) indexInArchive = up.ArcIndex; else indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if (up.IsAnti) { return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); } const CDirItem &di = DirItems->Items[up.DirIndex]; RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); if (di.IsDir()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; const CDirItems *DirItems; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (ai.SizeDefined) if (di.Size != ai.Size) pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback) { for (int i = 0; i < updatePairs.Size(); i++) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); // cout << "deleting"; */ if (callback) callback->ShowDeleteFile(pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; up2.NewData = up2.NewProps = false; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; break; } operationChain.Add(up2); } operationChain.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool IsAnti; int DirIndex; int ArcIndex; int NewNameIndex; bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback { virtual HRESULT ShowDeleteFile(int arcIndex) = 0; }; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; #endif UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "Windows/Error.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsDir, L"Folder" }, { kpidSize, L"Size" }, { kpidPackSize, L"Packed Size" }, { kpidAttrib, L"Attributes" }, { kpidCTime, L"Created" }, { kpidATime, L"Accessed" }, { kpidMTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubDirs, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" }, { kpidBit64, L"64-bit" }, { kpidBigEndian, L"Big-endian" }, { kpidCpu, L"CPU" }, { kpidPhySize, L"Physical Size" }, { kpidHeadersSize, L"Headers Size" }, { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, { kpidFreeSpace, L"Free Space" }, { kpidClusterSize, L"Cluster Size" } }; static const char kEmptyAttribChar = '.'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttribString(DWORD wa, bool isDir, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; wchar_t s[32]; ConvertUInt64ToString(propID, s); return s; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&prop.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidPath) { UString s; RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); prop = s; } else { RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (prop.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: prop = defaultItemName; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidMTime) { PrintTime(prop); } else if (fieldInfo.PropID == kpidAttrib) { if (prop.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = prop.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttribString(attributes, isFolder, s); g_StdOut << s; } else if (prop.vt == VT_BSTR) { if (techMode) g_StdOut << prop.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); } else { UString s = ConvertPropertyToString(prop, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant prop; if (archive->GetProperty(index, propID, &prop) != S_OK) throw "GetPropertyValue error"; if (prop.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(prop); return true; } HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) g_StdOut << "is not supported archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" #ifndef _NO_CRYPTO " -p{Password}: set Password\n" #endif " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) throw kUnsupportedArcTypeMessage; if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, formatIndices, options.ArchiveName)) throw kUnsupportedArcTypeMessage; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int MY_CDECL main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::Open_CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(Open_CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: INTERFACE_IOpenCallbackUI(;) CStdOutStream *OutStream; #ifndef _NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; UString Password; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) { return CheckBreak(); } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { #ifdef _NO_CRYPTO *passwordIsDefined = false; return StringToBstr(L"", password); #else if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif } /* HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) { // MT_LOCK if (StdOutMode) return S_OK; RINOK(Finilize()); m_PercentPrinter.PrintString("Deleting "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), #ifndef _NO_CRYPTO PasswordIsDefined(false), AskPassword(false), #endif StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRenameAll = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/7zip/UI/Console/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DWIN_LONG_PATH \ -DEXTERNAL_LZMA \ -DEXTERNAL_CODECS \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Registry.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Threads.obj \ !include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !include "../../Crc.mak" ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Build.mak ================================================ !IFDEF CPU !IFNDEF NO_BUFFEROVERFLOWU LIBS = $(LIBS) bufferoverflowU.lib !ENDIF !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gr -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope !ELSE CFLAGS = $(CFLAGS) -W3 !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF -OPT:ICF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if (_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while (pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for (int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for (int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "MyWindows.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for (int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { public: BSTR m_str; CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memcpy(res, m_str, byteLen); return res; } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifndef _WIN32 #include <ctype.h> #endif #ifndef _UNICODE #include "StringConvert.h" #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while ((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); // int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if (realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if (newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if (_capacity > 0) { for (int i = 0; i < _length; i++) newBuffer[i] = _chars[i]; delete []_chars; } _chars = newBuffer; _chars[_length] = 0; _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if (minBufLength >= _capacity) SetCapacity(minBufLength); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if (newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if (&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for (int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for (int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } void CBaseRecordVector::ClearAndFree() { Clear(); delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta = 1; if (_capacity >= 64) delta = _capacity / 4; else if (_capacity >= 8) delta = 8; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { // if (newCapacity <= _capacity) if (newCapacity == _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = NULL; if (newSize > 0) { p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); memcpy(p, _items, _itemSize * numRecordsToMove); } delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::ReserveDown() { Reserve(_size); } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void ClearAndFree(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); void ReserveDown(); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector(): CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while (--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector() {}; ~CObjectVector() { Clear(); }; CObjectVector(const CObjectVector &v) { *this = v; } CObjectVector& operator=(const CObjectVector &v) { Clear(); return (*this += v); } CObjectVector& operator+=(const CObjectVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for (int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for (int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if (c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while ((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if (c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if (numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { int numRequiredBytes = s.Length() * 2; BOOL defUsed; int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); #ifndef _WIN32_WCE if (numChars == 0) throw 282229; #endif dest.ReleaseBuffer(numChars); } return dest; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { bool defaultCharWasUsed; return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if (!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if (!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; UInt32 v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { if (end != NULL) *end = s; return result; } result <<= 4; result |= v; s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H extern "C" { #include "../../C/Types.h" } typedef int HRes; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; int numAdds; if (srcPos == srcLen) { *destLen = destPos; return True; } c = (Byte)src[srcPos++]; if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xC0) break; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { Byte c2; if (srcPos == srcLen) break; c2 = (Byte)src[srcPos++]; if (c2 < 0x80 || c2 >= 0xC0) break; value <<= 6; value |= (c2 - 0x80); } while (--numAdds != 0); if (value < 0x10000) { if (dest) dest[destPos] = (wchar_t)value; destPos++; } else { value -= 0x10000; if (value >= 0x100000) break; if (dest) { dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); } destPos += 2; } } *destLen = destPos; return False; } static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { unsigned numAdds; UInt32 value; if (srcPos == srcLen) { *destLen = destPos; return True; } value = src[srcPos++]; if (value < 0x80) { if (dest) dest[destPos] = (char)value; destPos++; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00 || srcPos == srcLen) break; c2 = src[srcPos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; if (dest) dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); destPos++; do { numAdds--; if (dest) dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); destPos++; } while (numAdds != 0); } *destLen = destPos; return False; } bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src.Length()); wchar_t *p = dest.GetBuffer((int)destLen); Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; Utf16_To_Utf8(NULL, &destLen, src, src.Length()); char *p = dest.GetBuffer((int)destLen); Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if (CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if (!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for (int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if (string.IsEmpty()) { if (i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if (errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA fd; _handle = ::FindFirstFile(wildcard, &fd); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW fd; _handle = ::FindFirstFileW(wildcard, &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for (UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for (UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } }}} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); }}} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if (hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) { if (c != 0) *s++ = c; char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(0, st.wYear, s, 4); s = UIntToStringSpec('-', st.wMonth, s, 2); s = UIntToStringSpec('-', st.wDay, s, 2); if (includeTime) { s = UIntToStringSpec(' ', st.wHour, s, 2); s = UIntToStringSpec(':', st.wMinute, s, 2); if (includeSeconds) UIntToStringSpec(':', st.wSecond, s, 2); } return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &prop) { switch (prop.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return prop.bstrVal; case VT_UI1: return ConvertUInt64ToString(prop.bVal); case VT_UI2: return ConvertUInt64ToString(prop.uiVal); case VT_UI4: return ConvertUInt64ToString(prop.ulVal); case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); // case VT_I1: return ConvertInt64ToString(prop.cVal); case VT_I2: return ConvertInt64ToString(prop.iVal); case VT_I4: return ConvertInt64ToString(prop.lVal); case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) { switch (prop.vt) { case VT_UI1: return prop.bVal; case VT_UI2: return prop.uiVal; case VT_UI4: return prop.ulVal; case VT_UI8: return (UInt64)prop.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 operator HANDLE() { return thread.handle; } void Attach(HANDLE handle) { thread.handle = handle; } HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Time.cpp ================================================ // Windows/Time.cpp #include "StdAfx.h" #include "Time.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &fileTime)); } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { dosTime = (fileTime.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) { resSeconds = 0; if (year < 1601 || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; UInt32 numYears = year - 1601; UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += day - 1; resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } void GetCurUtcFileTime(FILETIME &ft) { SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); } }} ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); }} #endif ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/Methods.txt ================================================ 7-Zip method IDs (4.65) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - PPC (Big Endian) 03 - Alpha 01 - Alpha 04 - IA64 01 - IA64 05 - ARM 01 - ARM 06 - M68 05 - M68 (Big Endian) 07 - ARM Thumb 01 - ARMT 08 - SPARC 05 - SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-4.0-lzma/lzma/lzma.txt ================================================ LZMA SDK 4.65 ------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK Contents ----------------- LZMA SDK includes: - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory C++/7zip/Compress/LZMA_Alone and call make to recompile it: make -f makefile.gcc clean all In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, you can use LIB = -lm -static Files --------------------- lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C/ - C files 7zCrc*.* - CRC code Alloc.* - Memory allocation functions Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code LzFind.* - Match finder for LZ (LZMA) encoders LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding LzHash.h - Additional file for LZ match finder LzmaDec.* - LZMA decoding LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). Archive - files related to archiving 7z - 7z ANSI-C Decoder CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + Types.h LzmaUtil/LzmaUtil.c is example application that uses these files. Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); For full code example, look at C/LzmaUtil/LzmaUtil.c code. How To compress data -------------------- Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Check C/LzmaUtil/LzmaUtil.c as example, When to use: file->file decompressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) LZMA Defines ------------ _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: operator new(size_t size) { void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } If you use MSCV that throws exception for "new" operator, you can compile without "NewHandler.cpp". So standard exception will be used. Actually some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.0-lzma/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "pseudo.h" #include "uncompress.h" #ifdef USE_LZMA #include <LzmaEnc.h> #include <LzmaDec.h> #define LZMA_DEFAULT_LEVEL 5 #define LZMA_DEFAULT_DICT (1 << 23) //0 //by siyou for avoid malloc fail. #define LZMA_DEFAULT_LC 1 #define LZMA_DEFAULT_LP 2 #define LZMA_DEFAULT_PB 2 #define LZMA_DEFAULT_FB 32 #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) /* offset of data in compressed metadata blocks (allowing room for * compressed size */ #define BLOCK_OFFSET 2 int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0; int silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned int id_count = 0; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is * cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* in memory uid tables */ #define ID_ENTRIES 256 #define ID_HASH(id) (id & (ID_ENTRIES - 1)) #define ISA_UID 1 #define ISA_GID 2 struct id { unsigned int id; int index; char flags; struct id *next; }; struct id *id_hash_table[ID_ENTRIES]; struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS]; unsigned int uid_count = 0, guid_count = 0; unsigned int sid_count = 0, suid_count = 0, sguid_count = 0; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; struct pseudo *pseudo = NULL; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; int fragment_buffer_size; char *read_from_disk(long long start, unsigned int avail_bytes); void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo); void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); long long generic_write_table(int length, char *buffer, int uncompressed); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } #define GET_FREELIST 1 struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ #ifdef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else #endif if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else #ifndef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } #endif /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found * getting a new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \ + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes); directory_cache_bytes = sdirectory_cache_bytes; inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; id_count = sid_count; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } #ifdef USE_LZMA static void *lzma_malloc(void *p, size_t size) { (void)p; return malloc(size); } static void lzma_free(void *p, void *addr) { (void)p; free(addr); } static ISzAlloc lzma_alloc = { lzma_malloc, lzma_free }; #endif unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; #ifdef USE_LZMA if (compression == LZMA_COMPRESSION) { size_t outsize = block_size - LZMA_PROPS_SIZE; size_t propsize = LZMA_PROPS_SIZE; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = LZMA_DEFAULT_LEVEL; props.dictSize = LZMA_DEFAULT_DICT; props.lc = LZMA_DEFAULT_LC; props.lp = LZMA_DEFAULT_LP; props.pb = LZMA_DEFAULT_PB; props.fb = LZMA_DEFAULT_FB; props.numThreads = 1; res = LzmaEncode((unsigned char *) d + LZMA_PROPS_SIZE, &outsize, (unsigned char *) s, size, &props, (unsigned char *) d, &propsize, 1, NULL, &lzma_alloc, &lzma_alloc); switch(res) { case SZ_OK: outsize += LZMA_PROPS_SIZE; break; case SZ_ERROR_DATA: BAD_ERROR("lzma::compress failed, data error\n"); break; case SZ_ERROR_MEM: BAD_ERROR("lzma::compress failed, memory allocation error\n"); break; case SZ_ERROR_PARAM: BAD_ERROR("lzma::compress failed, invalid parameters\n"); break; case SZ_ERROR_OUTPUT_EOF: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); case SZ_ERROR_THREAD: BAD_ERROR("lzma::compress failed, errors in multithreading functions\n"); break; /* should not happen */ default: BAD_ERROR("lzma::compress failed, unknown error\n"); break; } return outsize; } #endif if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough " "memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough " "memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid " "compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect " "zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown " "error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state " "inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state " "inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible" "\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { inode_table = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(inode_table == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; data_cache = realloc(data_cache, cache_size + realloc_size); if(data_cache == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *) (data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } int read_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) goto bytes_read; else if(errno != EINTR) { ERROR("Read failed because %s\n", strerror(errno)); return -1; } else res = 0; } } bytes_read: return count; } void read_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_destination: reading from position 0x%llx, bytes %d\n", byte, bytes); pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(read_bytes(fd, buff, bytes) < bytes) BAD_ERROR("Read on destination failed\n"); pthread_mutex_unlock(&pos_mutex); } int write_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write failed because %s\n", strerror(errno)); return -1; } res = 0; } } return 0; } void write_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write_bytes(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed\n"); if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { inode_table = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(inode_table == NULL) { BAD_ERROR("Out of memory in inode table " "reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += avail_bytes + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } write_destination(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(directory_table == NULL) { BAD_ERROR("Out of memory in directory table " "reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += avail_bytes + BLOCK_OFFSET; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_destination(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } long long write_id_table() { unsigned int id_bytes = SQUASHFS_ID_BYTES(id_count); char buffer[id_bytes]; unsigned int *p = (unsigned int *) buffer; int i; TRACE("write_id_table: ids %d, id_bytes %d\n", id_count, id_bytes); for(i = 0; i < id_count; i++, p++) { TRACE("write_id_table: id index %d, id %d", i, id_table[i]->id); SQUASHFS_SWAP_INTS(&id_table[i]->id, p, 1); } return generic_write_table(id_bytes, buffer, 1); } struct id *get_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = id_hash_table[hash]; for(; entry; entry = entry->next) if(entry->id == id) break; return entry; } struct id *create_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = malloc(sizeof(struct id)); if(entry == NULL) BAD_ERROR("Out of memory in create_id\n"); entry->id = id; entry->index = id_count ++; entry->flags = 0; entry->next = id_hash_table[hash]; id_hash_table[hash] = entry; id_table[entry->index] = entry; return entry; } unsigned int get_uid(unsigned int uid) { struct id *entry = get_id(uid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of uids!\n"); entry = create_id(uid); } if((entry->flags & ISA_UID) == 0) { entry->flags |= ISA_UID; uid_count ++; } return entry->index; } unsigned int get_guid(unsigned int guid) { struct id *entry = get_id(guid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of gids!\n"); entry = create_id(guid); } if((entry->flags & ISA_GID) == 0) { entry->flags |= ISA_GID; guid_count ++; } return entry->index; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in, unsigned int sparse) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((unsigned int) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((unsigned int) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("File inode, file_size %lld, start_block 0x%llx, blocks " "%d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(sparse && sparse >= byte_size) sparse = byte_size - 1; reg->sparse = sparse; SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("Long file inode, file_size %lld, start_block 0x%llx, " "blocks %d, fragment %d, offset %d, size %d, nlink %d" "\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inodep); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { SQUASHFS_SWAP_DIR_INDEX(&index[i].index, (squashfs_dir_index *) p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block " "0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_DIR_INODE_HEADER(dir, (squashfs_dir_inode_header *) inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, " "offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); SQUASHFS_SWAP_DEV_INODE_HEADER(dev, (squashfs_dev_inode_header *) inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inodep); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, (squashfs_ipc_inode_header *) inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan3_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ..." "\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE); if(buff == NULL) { BAD_ERROR("Out of memory reallocating directory buffer" "\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < -32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) { dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index)); if(dir->index == NULL) BAD_ERROR("Out of memory in " "directory index table " "reallocation!\n"); } dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); SQUASHFS_SWAP_DIR_ENTRY(&idir, idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; directory_data_cache = realloc(directory_data_cache, directory_cache_size + realloc_size); if(directory_data_cache == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(directory_table == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL, 0); #ifdef SQUASHFS_TRACE { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header dirh; SQUASHFS_SWAP_DIR_HEADER((squashfs_dir_header *) dirp, &dirh); count = dirh.count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh.start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; SQUASHFS_SWAP_DIR_ENTRY(idirp, &idir); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type " "%d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { squashfs_fragment_entry *disk_fragment; int size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char *data; if(compressed_buffer) data = compressed_buffer->data; else data = read_from_disk(start_block, size); res = uncompress_wrapper((unsigned char *) buffer->data, &bytes, (const unsigned char *) data, size); if(res != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("uncompress failed, not enough " "memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("uncompress failed, not enough " "room in output buffer\n"); else BAD_ERROR("uncompress failed," " unknown error %d\n", res); } } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else read_destination(fd, start_block, size, buffer->data); cache_block_put(compressed_buffer); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, entry->buffer); pthread_mutex_lock(&fragment_mutex); TRACE("fragment_locked writing fragment %d, compressed size %d" "\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } int add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) return FALSE; entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { fragment_table = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry)); if(fragment_table == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) cbuffer, 1); list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_destination(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } SQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks); write_destination(fd, bytes, sizeof(list), (char *) list); start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, " "size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } char read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk2(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer2); return read_from_file_buffer2; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long target_start, dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; target_start = *start; for(block = 0; block < blocks; block ++) { int size = SQUASHFS_COMPRESSED_SIZE_BLOCK ((*block_list)[block]); struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(size == 0) continue; target_buffer = cache_lookup(writer_buffer, target_start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(target_start, size); dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else dup_data = read_from_disk2(dup_start, size); res = memcmp(target_data, dup_data, size); cache_block_put(target_buffer); cache_block_put(dup_buffer); if(res != 0) break; target_start += size; dup_start += size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start " "0x%llx, size %lld, checksum " "0x%x, fragment %d, size %d, " "offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int index = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; file_buffer->fragment = (file_buffer->block == frag_block); bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read_bytes(file, &buffer, 1) == 1) goto restat; } queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write_bytes(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer; if(sparse_files && all_zero(file_buffer)) { file_buffer->c_byte = 0; queue_put(from_deflate, file_buffer); } else if(file_buffer->fragment) { file_buffer->c_byte = file_buffer->size; queue_put(from_deflate, file_buffer); } else { write_buffer = cache_get(writer_buffer, 0, 0); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK (write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, write_buffer); TRACE("Writing fragment %lld, uncompressed size %d, " "compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; static int tty = -1; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { long long file_bytes, start; struct fragment *fragment; unsigned int *block_list; int block, status; int blocks = (read_size + block_size - 1) >> block_log; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { int block, thresh; long long file_bytes, dup_start, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer **buffer_list; int status, num_locked_fragments; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; buffer_list = malloc(blocks * sizeof(struct file_buffer *)); if(buffer_list == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = dup_start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); if(block < thresh) { buffer_list[block] = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block] = read_buffer; } else { buffer_list[block] = NULL; sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block]) queue_put(to_writer, buffer_list[block]); fragment = get_and_fill_fragment(fragment_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block]); bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because" " %s\n", strerror(errno)); } } unlock_fragments(); cache_block_put(fragment_buffer); free(buffer_list); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && dup_start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks]); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(read_buffer->fragment && read_buffer->c_byte) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, " "attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation" "\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) { dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *)); if(dir->list == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); } if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) continue; else return dir_info->list[current_count]; return NULL; } struct dir_ent *scan2_lookup(struct dir_info *dir, char *name) { int i; for(i = 0; i < dir->count; i++) if(strcmp(dir->list[i]->name, name) == 0) return dir->list[i]; return NULL; } struct dir_ent *scan3_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return NULL; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct dir_info *dir) { dir->current_count = 0; } void scan3_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; dir_scan2(dir_info, pseudo); if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* *dummy top level directory, if multiple sources specified on * command line */ memset(&buf, 0, sizeof(buf)); buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan3(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring" "\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { sub_dir = dir_scan1(filename, new, scan1_readdir); if(sub_dir == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); error: return dir; } struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo) { struct dir_info *sub_dir; struct dir_ent *dir_ent; struct pseudo_entry *pseudo_ent; struct stat buf; static pseudo_ino = 1; if(dir == NULL && (dir = scan1_opendir("")) == NULL) return NULL; while((dir_ent = scan2_readdir(dir)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *name = dir_ent->name; if((buf->st_mode & S_IFMT) == S_IFDIR) dir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo)); } while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { dir_ent = scan2_lookup(dir, pseudo_ent->name); if(dir_ent) { ERROR("Pseudo file \"%s\" exists in source filesystem " "\"%s\"\n", pseudo_ent->pathname, dir_ent->pathname); ERROR("Ignoring, exclude it (-e/-ef) to override\n"); continue; } if(pseudo_ent->dev->type == 'd') { sub_dir = dir_scan2(NULL, pseudo_ent->pseudo); if(sub_dir == NULL) { ERROR("Could not create pseudo directory \"%s\"" ", skipping...\n", pseudo_ent->pathname); continue; } dir->directory_count ++; } else sub_dir = NULL; memset(&buf, 0, sizeof(buf)); buf.st_mode = pseudo_ent->dev->mode; buf.st_uid = pseudo_ent->dev->uid; buf.st_gid = pseudo_ent->dev->gid; buf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor); buf.st_mtime = time(NULL); buf.st_ino = pseudo_ino ++; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, lookup_inode(&buf), NULL, dir); } scan2_freedir(dir); sort_directory(dir); return dir; } void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan3_init_dir(&dir); while((dir_ent = scan3_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld " "bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan3(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("character device %s inode 0x%llx" "\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("fifo %s inode 0x%llx\n",dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("unix domain socket %s inode " "0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, " "mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed " "size %lld bytes LINK" "\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode " "0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan3_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) { \ exclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \ * sizeof(struct exclude_info)); \ if(exclude_paths == NULL) \ BAD_ERROR("Out of memory in exclude dir/file table\n"); \ } \ exclude_paths[exclude].st_dev = buf.st_dev; \ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, " "ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because " "%s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { old_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1)); if(old_root_entry == NULL) BAD_ERROR("Out of memory in old root directory entries " "reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; inode_lookup_table = realloc(inode_lookup_table, lookup_bytes); if(inode_lookup_table == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; SQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing exclude which subsumes * the exclude currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist * from more specific excludes, delete as they're * subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with " "-wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories * in the filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "write_recovery_data\n"); read_destination(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(recoverfd == -1) BAD_ERROR("Failed to create recovery file, because %s. " "Aborting\n", strerror(errno)); if(write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int res; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < RECOVER_ID_SIZE) BAD_ERROR("Recovery file appears to be truncated\n"); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); res = read_bytes(recoverfd, &sBlk, sizeof(squashfs_super_block)); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < sizeof(squashfs_super_block)) BAD_ERROR("Recovery file appears to be truncated\n"); read_destination(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to " "match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "read_recovery_data\n"); res = read_bytes(recoverfd, metadata, bytes); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_destination(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_destination(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 4.0 (2009/04/05)\n");\ printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int nopad = FALSE, keep_as_directory = FALSE; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; int s_minor = SQUASHFS_MINOR; compression=LZMA_COMPRESSION; pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-pf") == 0) { if(++i == argc) { ERROR("%s: -pf missing filename\n", argv[0]); exit(1); } if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { ERROR("Failed to parse pseudo file \"%s\"\n", argv[i]); exit(1); } } else if(strcmp(argv[i], "-p") == 0) { if(++i == argc) { ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { ERROR("Failed to parse pseudo definition\n"); exit(1); } } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte " "or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 " "megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or " "not between 4096 and 1Mbyte\n", argv[0]); exit(1); } #ifdef USE_LZMA } else if(strcmp(argv[i], "-nolzma") == 0) { compression = ZLIB_COMPRESSION; #endif } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range" "\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or " "unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range" "\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or " "unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] " "[-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and " "copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data " "using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery " "file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem " "exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress " "bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to " "<block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); #ifdef USE_LZMA ERROR("-lzma Enable LZMA compression\n"); #endif ERROR("-processors <number>\tUse <number> processors." " By default will use number of\n"); ERROR("\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> " "Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> " "Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fagment queue to " "<size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for " "files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate " "checking\n"); ERROR("-noappend\t\tdo not append to existing " "filesystem\n"); ERROR("-keep-as-directory\tif one source directory is " "specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, " "rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source " "files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in " "the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new " "source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " "of 4K\n"); ERROR("-root-owned\t\talternative name for -all-root" "\n"); ERROR("-noInodeCompression\talternative name for -noI" "\n"); ERROR("-noDataCompression\talternative name for -noD" "\n"); ERROR("-noFragmentCompression\talternative name for " "-noF\n"); ERROR("-sort <sort_file>\tsort files according to " "priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. " "Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files." " One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards " "(globbing) to be used in\n\t\t\texclude " "dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to " "be used in exclude\n\t\t\tdirs/files\n"); ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n"); ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); fragment_buffer_size = fragmentb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" " "because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRUSR |S_IWUSR|S_IRGRP|S_IROTH); if(fd == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as " "destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR); if(fd == -1) { perror("Could not open regular file for " "writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has * been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-p") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-p") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { if(read_super(fd, &sBlk, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } block_log = slog(block_size = sBlk.block_size); s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); if(delete) { printf("Creating %d.%d filesystem on %s, block size %d.\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %d.%d filesystem on %s, block " "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " "-always-use-fragments and -exportable options ignored" "\n"); printf("\nIf appending is not wanted, please re-run with " "-noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = malloc(scache_bytes); sdirectory_data_cache = malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; sid_count = id_count; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_destination(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* * set the filesystem state up to be able to append to the * original filesystem. The filesystem state differs depending * on whether we're appending to the original root directory, or * if the original root directory becomes a sub-directory * (root-becomes specified on command line, here root_name != * NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_ids = id_count; sBlk.id_table_start = write_id_table(); sBlk.bytes_used = bytes; /* Only compression supported */ sBlk.compression = compression; /* Xattrs are not currently supported */ sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk); write_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_destination(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, block_size); printf("\t%s data, %s metadata, %s fragments\n", noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of ids (unique uids + gids) %d\n", id_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_UID) { struct passwd *user = getpwuid(id_table[i]->id); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, id_table[i]->id); } } printf("Number of gids %d\n", guid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_GID) { struct group *group = getgrgid(id_table[i]->id); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, id_table[i]->id); } } return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/mksquashfs.c.orig ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "pseudo.h" #include "uncompress.h" #ifdef USE_LZMA #include <LzmaEnc.h> #include <LzmaDec.h> #define LZMA_DEFAULT_LEVEL 5 #define LZMA_DEFAULT_DICT 0 #define LZMA_DEFAULT_LC 1 #define LZMA_DEFAULT_LP 2 #define LZMA_DEFAULT_PB 2 #define LZMA_DEFAULT_FB 32 #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) /* offset of data in compressed metadata blocks (allowing room for * compressed size */ #define BLOCK_OFFSET 2 int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0; int silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned int id_count = 0; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is * cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* in memory uid tables */ #define ID_ENTRIES 256 #define ID_HASH(id) (id & (ID_ENTRIES - 1)) #define ISA_UID 1 #define ISA_GID 2 struct id { unsigned int id; int index; char flags; struct id *next; }; struct id *id_hash_table[ID_ENTRIES]; struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS]; unsigned int uid_count = 0, guid_count = 0; unsigned int sid_count = 0, suid_count = 0, sguid_count = 0; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; struct pseudo *pseudo = NULL; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; int fragment_buffer_size; char *read_from_disk(long long start, unsigned int avail_bytes); void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo); void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); long long generic_write_table(int length, char *buffer, int uncompressed); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } #define GET_FREELIST 1 struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ #ifdef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else #endif if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else #ifndef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } #endif /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found * getting a new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \ + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes); directory_cache_bytes = sdirectory_cache_bytes; inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; id_count = sid_count; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } #ifdef USE_LZMA static void *lzma_malloc(void *p, size_t size) { (void)p; return malloc(size); } static void lzma_free(void *p, void *addr) { (void)p; free(addr); } static ISzAlloc lzma_alloc = { lzma_malloc, lzma_free }; #endif unsigned int mangle2(z_stream **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte; unsigned int res; z_stream *stream = *strm; if(uncompressed) goto notcompressed; #ifdef USE_LZMA if (compression == LZMA_COMPRESSION) { size_t outsize = block_size - LZMA_PROPS_SIZE; size_t propsize = LZMA_PROPS_SIZE; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = LZMA_DEFAULT_LEVEL; props.dictSize = LZMA_DEFAULT_DICT; props.lc = LZMA_DEFAULT_LC; props.lp = LZMA_DEFAULT_LP; props.pb = LZMA_DEFAULT_PB; props.fb = LZMA_DEFAULT_FB; props.numThreads = 1; res = LzmaEncode((unsigned char *) d + LZMA_PROPS_SIZE, &outsize, (unsigned char *) s, size, &props, (unsigned char *) d, &propsize, 1, NULL, &lzma_alloc, &lzma_alloc); switch(res) { case SZ_OK: outsize += LZMA_PROPS_SIZE; break; case SZ_ERROR_DATA: BAD_ERROR("lzma::compress failed, data error\n"); break; case SZ_ERROR_MEM: BAD_ERROR("lzma::compress failed, memory allocation error\n"); break; case SZ_ERROR_PARAM: BAD_ERROR("lzma::compress failed, invalid parameters\n"); break; case SZ_ERROR_OUTPUT_EOF: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); case SZ_ERROR_THREAD: BAD_ERROR("lzma::compress failed, errors in multithreading functions\n"); break; /* should not happen */ default: BAD_ERROR("lzma::compress failed, unknown error\n"); break; } return outsize; } #endif if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) BAD_ERROR("mangle::compress failed, not enough " "memory\n"); stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough " "memory\n"); else if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, not a valid " "compression level\n"); else if(res == Z_VERSION_ERROR) BAD_ERROR("zlib::compress failed, incorrect " "zlib version\n"); else BAD_ERROR("zlib::compress failed, unknown " "error %d\n", res); } } else if((res = deflateReset(stream)) != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state " "inconsistent\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res != Z_STREAM_END && res != Z_OK) { if(res == Z_STREAM_ERROR) BAD_ERROR("zlib::compress failed, stream state " "inconsistent\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, no progress possible" "\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); } c_byte = stream->total_out; if(res != Z_STREAM_END || c_byte >= size) { notcompressed: memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static z_stream *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { inode_table = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(inode_table == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; data_cache = realloc(data_cache, cache_size + realloc_size); if(data_cache == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *) (data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } int read_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) goto bytes_read; else if(errno != EINTR) { ERROR("Read failed because %s\n", strerror(errno)); return -1; } else res = 0; } } bytes_read: return count; } void read_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_destination: reading from position 0x%llx, bytes %d\n", byte, bytes); pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(read_bytes(fd, buff, bytes) < bytes) BAD_ERROR("Read on destination failed\n"); pthread_mutex_unlock(&pos_mutex); } int write_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write failed because %s\n", strerror(errno)); return -1; } res = 0; } } return 0; } void write_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write_bytes(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed\n"); if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { inode_table = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(inode_table == NULL) { BAD_ERROR("Out of memory in inode table " "reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += avail_bytes + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } write_destination(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(directory_table == NULL) { BAD_ERROR("Out of memory in directory table " "reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += avail_bytes + BLOCK_OFFSET; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_destination(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } long long write_id_table() { unsigned int id_bytes = SQUASHFS_ID_BYTES(id_count); char buffer[id_bytes]; unsigned int *p = (unsigned int *) buffer; int i; TRACE("write_id_table: ids %d, id_bytes %d\n", id_count, id_bytes); for(i = 0; i < id_count; i++, p++) { TRACE("write_id_table: id index %d, id %d", i, id_table[i]->id); SQUASHFS_SWAP_INTS(&id_table[i]->id, p, 1); } return generic_write_table(id_bytes, buffer, 1); } struct id *get_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = id_hash_table[hash]; for(; entry; entry = entry->next) if(entry->id == id) break; return entry; } struct id *create_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = malloc(sizeof(struct id)); if(entry == NULL) BAD_ERROR("Out of memory in create_id\n"); entry->id = id; entry->index = id_count ++; entry->flags = 0; entry->next = id_hash_table[hash]; id_hash_table[hash] = entry; id_table[entry->index] = entry; return entry; } unsigned int get_uid(unsigned int uid) { struct id *entry = get_id(uid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of uids!\n"); entry = create_id(uid); } if((entry->flags & ISA_UID) == 0) { entry->flags |= ISA_UID; uid_count ++; } return entry->index; } unsigned int get_guid(unsigned int guid) { struct id *entry = get_id(guid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of gids!\n"); entry = create_id(guid); } if((entry->flags & ISA_GID) == 0) { entry->flags |= ISA_GID; guid_count ++; } return entry->index; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in, unsigned int sparse) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((unsigned int) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((unsigned int) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("File inode, file_size %lld, start_block 0x%llx, blocks " "%d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(sparse && sparse >= byte_size) sparse = byte_size - 1; reg->sparse = sparse; SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("Long file inode, file_size %lld, start_block 0x%llx, " "blocks %d, fragment %d, offset %d, size %d, nlink %d" "\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inodep); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { SQUASHFS_SWAP_DIR_INDEX(&index[i].index, (squashfs_dir_index *) p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block " "0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_DIR_INODE_HEADER(dir, (squashfs_dir_inode_header *) inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, " "offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); SQUASHFS_SWAP_DEV_INODE_HEADER(dev, (squashfs_dev_inode_header *) inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inodep); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, (squashfs_ipc_inode_header *) inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan3_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ..." "\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE); if(buff == NULL) { BAD_ERROR("Out of memory reallocating directory buffer" "\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < -32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) { dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index)); if(dir->index == NULL) BAD_ERROR("Out of memory in " "directory index table " "reallocation!\n"); } dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); SQUASHFS_SWAP_DIR_ENTRY(&idir, idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; directory_data_cache = realloc(directory_data_cache, directory_cache_size + realloc_size); if(directory_data_cache == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(directory_table == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL, 0); #ifdef SQUASHFS_TRACE { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header dirh; SQUASHFS_SWAP_DIR_HEADER((squashfs_dir_header *) dirp, &dirh); count = dirh.count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh.start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; SQUASHFS_SWAP_DIR_ENTRY(idirp, &idir); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type " "%d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { squashfs_fragment_entry *disk_fragment; int size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char *data; if(compressed_buffer) data = compressed_buffer->data; else data = read_from_disk(start_block, size); res = uncompress_wrapper((unsigned char *) buffer->data, &bytes, (const unsigned char *) data, size); if(res != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("uncompress failed, not enough " "memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("uncompress failed, not enough " "room in output buffer\n"); else BAD_ERROR("uncompress failed," " unknown error %d\n", res); } } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else read_destination(fd, start_block, size, buffer->data); cache_block_put(compressed_buffer); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, entry->buffer); pthread_mutex_lock(&fragment_mutex); TRACE("fragment_locked writing fragment %d, compressed size %d" "\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } int add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) return FALSE; entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { fragment_table = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry)); if(fragment_table == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; long long obytes = bytes; for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) cbuffer, 1); list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_destination(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } SQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks); write_destination(fd, bytes, sizeof(list), (char *) list); start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, " "size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } char read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk2(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer2); return read_from_file_buffer2; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long target_start, dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; target_start = *start; for(block = 0; block < blocks; block ++) { int size = SQUASHFS_COMPRESSED_SIZE_BLOCK ((*block_list)[block]); struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(size == 0) continue; target_buffer = cache_lookup(writer_buffer, target_start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(target_start, size); dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else dup_data = read_from_disk2(dup_start, size); res = memcmp(target_data, dup_data, size); cache_block_put(target_buffer); cache_block_put(dup_buffer); if(res != 0) break; target_start += size; dup_start += size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start " "0x%llx, size %lld, checksum " "0x%x, fragment %d, size %d, " "offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; static int index = 0; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; file_buffer->fragment = (file_buffer->block == frag_block); bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read_bytes(file, &buffer, 1) == 1) goto restat; } queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = index ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write_bytes(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer; if(sparse_files && all_zero(file_buffer)) { file_buffer->c_byte = 0; queue_put(from_deflate, file_buffer); } else if(file_buffer->fragment) { file_buffer->c_byte = file_buffer->size; queue_put(from_deflate, file_buffer); } else { write_buffer = cache_get(writer_buffer, 0, 0); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK (write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } } void *frag_deflator(void *arg) { z_stream *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; pthread_mutex_unlock(&fragment_mutex); queue_put(to_writer, write_buffer); TRACE("Writing fragment %lld, uncompressed size %d, " "compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; static int tty = -1; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); return; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { long long file_bytes, start; struct fragment *fragment; unsigned int *block_list; int block, status; int blocks = (read_size + block_size - 1) >> block_log; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { int block, thresh; long long file_bytes, dup_start, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer **buffer_list; int status, num_locked_fragments; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; buffer_list = malloc(blocks * sizeof(struct file_buffer *)); if(buffer_list == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = dup_start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); if(block < thresh) { buffer_list[block] = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block] = read_buffer; } else { buffer_list[block] = NULL; sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block]) queue_put(to_writer, buffer_list[block]); fragment = get_and_fill_fragment(fragment_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block]); bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because" " %s\n", strerror(errno)); } } unlock_fragments(); cache_block_put(fragment_buffer); free(buffer_list); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && dup_start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks]); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(read_buffer->fragment && read_buffer->c_byte) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, " "attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation" "\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) { dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *)); if(dir->list == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); } if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) continue; else return dir_info->list[current_count]; return NULL; } struct dir_ent *scan2_lookup(struct dir_info *dir, char *name) { int i; for(i = 0; i < dir->count; i++) if(strcmp(dir->list[i]->name, name) == 0) return dir->list[i]; return NULL; } struct dir_ent *scan3_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return NULL; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct dir_info *dir) { dir->current_count = 0; } void scan3_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; dir_scan2(dir_info, pseudo); if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* *dummy top level directory, if multiple sources specified on * command line */ memset(&buf, 0, sizeof(buf)); buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan3(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring" "\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { sub_dir = dir_scan1(filename, new, scan1_readdir); if(sub_dir == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); error: return dir; } struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo) { struct dir_info *sub_dir; struct dir_ent *dir_ent; struct pseudo_entry *pseudo_ent; struct stat buf; static pseudo_ino = 1; if(dir == NULL && (dir = scan1_opendir("")) == NULL) return NULL; while((dir_ent = scan2_readdir(dir)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *name = dir_ent->name; if((buf->st_mode & S_IFMT) == S_IFDIR) dir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo)); } while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { dir_ent = scan2_lookup(dir, pseudo_ent->name); if(dir_ent) { ERROR("Pseudo file \"%s\" exists in source filesystem " "\"%s\"\n", pseudo_ent->pathname, dir_ent->pathname); ERROR("Ignoring, exclude it (-e/-ef) to override\n"); continue; } if(pseudo_ent->dev->type == 'd') { sub_dir = dir_scan2(NULL, pseudo_ent->pseudo); if(sub_dir == NULL) { ERROR("Could not create pseudo directory \"%s\"" ", skipping...\n", pseudo_ent->pathname); continue; } dir->directory_count ++; } else sub_dir = NULL; memset(&buf, 0, sizeof(buf)); buf.st_mode = pseudo_ent->dev->mode; buf.st_uid = pseudo_ent->dev->uid; buf.st_gid = pseudo_ent->dev->gid; buf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor); buf.st_mtime = time(NULL); buf.st_ino = pseudo_ino ++; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, lookup_inode(&buf), NULL, dir); } scan2_freedir(dir); sort_directory(dir); return dir; } void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan3_init_dir(&dir); while((dir_ent = scan3_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld " "bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan3(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("character device %s inode 0x%llx" "\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("fifo %s inode 0x%llx\n",dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("unix domain socket %s inode " "0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, " "mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed " "size %lld bytes LINK" "\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode " "0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan3_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) { \ exclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \ * sizeof(struct exclude_info)); \ if(exclude_paths == NULL) \ BAD_ERROR("Out of memory in exclude dir/file table\n"); \ } \ exclude_paths[exclude].st_dev = buf.st_dev; \ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, " "ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because " "%s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { old_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1)); if(old_root_entry == NULL) BAD_ERROR("Out of memory in old root directory entries " "reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; inode_lookup_table = realloc(inode_lookup_table, lookup_bytes); if(inode_lookup_table == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; SQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing exclude which subsumes * the exclude currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist * from more specific excludes, delete as they're * subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with " "-wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories * in the filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "write_recovery_data\n"); read_destination(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(recoverfd == -1) BAD_ERROR("Failed to create recovery file, because %s. " "Aborting\n", strerror(errno)); if(write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int res; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < RECOVER_ID_SIZE) BAD_ERROR("Recovery file appears to be truncated\n"); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); res = read_bytes(recoverfd, &sBlk, sizeof(squashfs_super_block)); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < sizeof(squashfs_super_block)) BAD_ERROR("Recovery file appears to be truncated\n"); read_destination(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to " "match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "read_recovery_data\n"); res = read_bytes(recoverfd, metadata, bytes); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_destination(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_destination(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 4.0 (2009/04/05)\n");\ printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int nopad = FALSE, keep_as_directory = FALSE; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; int s_minor = SQUASHFS_MINOR; pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-pf") == 0) { if(++i == argc) { ERROR("%s: -pf missing filename\n", argv[0]); exit(1); } if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { ERROR("Failed to parse pseudo file \"%s\"\n", argv[i]); exit(1); } } else if(strcmp(argv[i], "-p") == 0) { if(++i == argc) { ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { ERROR("Failed to parse pseudo definition\n"); exit(1); } } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte " "or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 " "megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or " "not between 4096 and 1Mbyte\n", argv[0]); exit(1); } #ifdef USE_LZMA } else if(strcmp(argv[i], "-lzma") == 0) { compression = LZMA_COMPRESSION; #endif } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range" "\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or " "unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range" "\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or " "unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] " "[-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and " "copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data " "using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery " "file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-exports\t\tdon't make the filesystem " "exportable via NFS\n"); ERROR("-no-progress\t\tdon't display the progress " "bar\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-b <block_size>\t\tset data block to " "<block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); #ifdef USE_LZMA ERROR("-lzma Enable LZMA compression\n"); #endif ERROR("-processors <number>\tUse <number> processors." " By default will use number of\n"); ERROR("\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> " "Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> " "Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fagment queue to " "<size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for " "files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate " "checking\n"); ERROR("-noappend\t\tdo not append to existing " "filesystem\n"); ERROR("-keep-as-directory\tif one source directory is " "specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, " "rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source " "files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in " "the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new " "source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " "of 4K\n"); ERROR("-root-owned\t\talternative name for -all-root" "\n"); ERROR("-noInodeCompression\talternative name for -noI" "\n"); ERROR("-noDataCompression\talternative name for -noD" "\n"); ERROR("-noFragmentCompression\talternative name for " "-noF\n"); ERROR("-sort <sort_file>\tsort files according to " "priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. " "Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files." " One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards " "(globbing) to be used in\n\t\t\texclude " "dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to " "be used in exclude\n\t\t\tdirs/files\n"); ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n"); ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); fragment_buffer_size = fragmentb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" " "because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(fd == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as " "destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR); if(fd == -1) { perror("Could not open regular file for " "writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has * been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-p") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-p") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { if(read_super(fd, &sBlk, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } block_log = slog(block_size = sBlk.block_size); s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } initialise_threads(); if(delete) { printf("Creating %d.%d filesystem on %s, block size %d.\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %d.%d filesystem on %s, block " "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " "-always-use-fragments and -exportable options ignored" "\n"); printf("\nIf appending is not wanted, please re-run with " "-noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = malloc(scache_bytes); sdirectory_data_cache = malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; sid_count = id_count; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_destination(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* * set the filesystem state up to be able to append to the * original filesystem. The filesystem state differs depending * on whether we're appending to the original root directory, or * if the original root directory becomes a sub-directory * (root-becomes specified on command line, here root_name != * NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_ids = id_count; sBlk.id_table_start = write_id_table(); sBlk.bytes_used = bytes; /* Only compression supported */ sBlk.compression = compression; /* Xattrs are not currently supported */ sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk); write_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_destination(fd, bytes, 4096 - i, temp); } close(fd); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, block_size); printf("\t%s data, %s metadata, %s fragments\n", noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of ids (unique uids + gids) %d\n", id_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_UID) { struct passwd *user = getpwuid(id_table[i]->id); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, id_table[i]->id); } } printf("Number of gids %d\n", guid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_GID) { struct group *group = getgrgid(id_table[i]->id); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, id_table[i]->id); } } return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/mksquashfs.h ================================================ #ifndef MKSQUASHFS_H #define MKSQUASHFS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(s, d, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(s, d, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) swap_le64_num(s, d, n) #define SWAP_LE16(s, d, field) swap_le16(&((s)->field), &((d)->field)) #define SWAP_LE32(s, d, field) swap_le32(&((s)->field), &((d)->field)) #define SWAP_LE64(s, d, field) swap_le64(&((s)->field), &((d)->field)) #define SWAP_LES16(s, d, field) swap_le16((unsigned short *) &((s)->field), \ (unsigned short *) &((d)->field)) #else #define SQUASHFS_MEMCPY(s, d, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(s, d, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(s, d, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \ memcpy(d, s, n * sizeof(long long)) #endif extern int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, const unsigned char *src, unsigned long src_len); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/pseudo.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.c */ #include <pwd.h> #include <grp.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include "pseudo.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); #define TRUE 1 #define FALSE 0 static void dump_pseudo(struct pseudo *pseudo, char *string) { int i; char path[1024]; for(i = 0; i < pseudo->names; i++) { struct pseudo_entry *entry = &pseudo->name[i]; if(string) strcat(strcat(strcpy(path, string), "/"), entry->name); else strcpy(path, entry->name); if(entry->pseudo == NULL) ERROR("%s %c %o %d %d %d %d\n", path, entry->dev->type, entry->dev->mode, entry->dev->uid, entry->dev->gid, entry->dev->major, entry->dev->minor); else dump_pseudo(entry->pseudo, path); } } static char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } /* * Add pseudo device target to the set of pseudo devices. Pseudo_dev * describes the pseudo device attributes. */ struct pseudo *add_pseudo(struct pseudo *pseudo, struct pseudo_dev *pseudo_dev, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(pseudo == NULL) { if((pseudo = malloc(sizeof(struct pseudo))) == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->names = 0; pseudo->count = 0; pseudo->name = NULL; } for(i = 0; i < pseudo->names; i++) if(strcmp(pseudo->name[i].name, targname) == 0) break; if(i == pseudo->names) { /* allocate new name entry */ pseudo->names ++; pseudo->name = realloc(pseudo->name, (i + 1) * sizeof(struct pseudo_entry)); if(pseudo->name == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->name[i].name = strdup(targname); if(target[0] == '\0') { /* at leaf pathname component */ pseudo->name[i].pseudo = NULL; pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); if(pseudo->name[i].dev == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->name[i].pathname = strdup(alltarget); memcpy(pseudo->name[i].dev, pseudo_dev, sizeof(struct pseudo_dev)); } else { /* recurse adding child components */ pseudo->name[i].dev = NULL; pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); } } else { /* existing matching entry */ if(pseudo->name[i].pseudo == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing pseudo file. */ if(target[0] != '\0') { /* entry must exist as a 'd' type pseudo file */ if(pseudo->name[i].dev->type == 'd') /* recurse adding child components */ pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); else ERROR("%s already exists as a non " "directory. Ignoring %s!\n", targname, alltarget); } else if(memcmp(pseudo_dev, pseudo->name[i].dev, sizeof(struct pseudo_dev)) != 0) ERROR("%s already exists as a different pseudo " "definition. Ignoring!\n", alltarget); else ERROR("%s already exists as an identical " "pseudo definition!\n", alltarget); } else { /* sub-directory exists which means this can only be a * 'd' type pseudo file */ if(target[0] == '\0') { if(pseudo->name[i].dev == NULL && pseudo_dev->type == 'd') { pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); if(pseudo->name[i].dev == NULL) BAD_ERROR("failed to allocate " "pseudo file\n"); pseudo->name[i].pathname = strdup(alltarget); memcpy(pseudo->name[i].dev, pseudo_dev, sizeof(struct pseudo_dev)); } else ERROR("%s already exists as a " "directory. Ignoring %s!\n", targname, alltarget); } else /* recurse adding child components */ add_pseudo(pseudo->name[i].pseudo, pseudo_dev, target, alltarget); } } return pseudo; } /* * Find subdirectory in pseudo directory referenced by pseudo, matching * filename. If filename doesn't exist or if filename is a leaf file * return NULL */ struct pseudo *pseudo_subdir(char *filename, struct pseudo *pseudo) { int i; if(pseudo == NULL) return NULL; for(i = 0; i < pseudo->names; i++) if(strcmp(filename, pseudo->name[i].name) == 0) return pseudo->name[i].pseudo; return NULL; } struct pseudo_entry *pseudo_readdir(struct pseudo *pseudo) { if(pseudo == NULL) return NULL; while(pseudo->count < pseudo->names) { if(pseudo->name[pseudo->count].dev != NULL) return &pseudo->name[pseudo->count++]; else pseudo->count++; } return NULL; } int read_pseudo_def(struct pseudo **pseudo, char *def) { int n; unsigned int major = 0, minor = 0, mode; char filename[2048], type, suid[100], sgid[100], *ptr; long long uid, gid; struct pseudo_dev dev; n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid, &major, &minor); if(n < 5) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } switch(type) { case 'b': case 'c': if(n < 7) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } if(major > 0xfff) { ERROR("Major %d out of range\n", major); goto error; } if(minor > 0xfffff) { ERROR("Minor %d out of range\n", minor); goto error; } /* fall through */ case 'd': if(mode > 0777) { ERROR("Mode %o out of range\n", mode); goto error; } uid = strtoll(suid, &ptr, 10); if(*ptr == '\0') { if(uid < 0 || uid > ((1LL << 32) - 1)) { ERROR("Uid %s out of range\n", suid); goto error; } } else { struct passwd *pwuid = getpwnam(suid); if(pwuid) uid = pwuid->pw_uid; else { ERROR("Uid %s invalid uid or unknown user\n", suid); goto error; } } gid = strtoll(sgid, &ptr, 10); if(*ptr == '\0') { if(gid < 0 || gid > ((1LL << 32) - 1)) { ERROR("Gid %s out of range\n", sgid); goto error; } } else { struct group *grgid = getgrnam(sgid); if(grgid) gid = grgid->gr_gid; else { ERROR("Gid %s invalid uid or unknown user\n", sgid); goto error; } } break; default: ERROR("Unsupported type %c\n", type); goto error; } switch(type) { case 'b': mode |= S_IFBLK; break; case 'c': mode |= S_IFCHR; break; case 'd': mode |= S_IFDIR; break; } dev.type = type; dev.mode = mode; dev.uid = uid; dev.gid = gid; dev.major = major; dev.minor = minor; *pseudo = add_pseudo(*pseudo, &dev, filename, filename); return TRUE; error: ERROR("Bad pseudo file definition \"%s\"\n", def); return FALSE; } int read_pseudo_file(struct pseudo **pseudo, char *filename) { FILE *fd; char line[2048]; int res = TRUE; fd = fopen(filename, "r"); if(fd == NULL) { ERROR("Could not open pseudo device file \"%s\" because %s\n", filename, strerror(errno)); return FALSE; } while(fscanf(fd, "%2047[^\n]\n", line) > 0) { res = read_pseudo_def(pseudo, line); if(res == FALSE) break; }; fclose(fd); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/pseudo.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.h */ struct pseudo_dev { char type; unsigned int mode; unsigned int uid; unsigned int gid; unsigned int major; unsigned int minor; }; struct pseudo_entry { char *name; char *pathname; struct pseudo *pseudo; struct pseudo_dev *dev; }; struct pseudo { int names; int count; struct pseudo_entry *name; }; extern int read_pseudo_def(struct pseudo **, char *); extern int read_pseudo_file(struct pseudo **, char *); extern struct pseudo *pseudo_subdir(char *, struct pseudo *); extern struct pseudo_entry *pseudo_readdir(struct pseudo *); ================================================ FILE: src/others/squashfs-4.0-lzma/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_destination(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); extern void *create_id(unsigned int); extern unsigned int get_uid(unsigned int); extern unsigned int get_guid(unsigned int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "global.h" #include "uncompress.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; read_destination(fd, start, 2, (char *)&c_byte); SQUASHFS_INSWAP_SHORTS(&c_byte, 1); if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_destination(fd, start + offset, c_byte, buffer); res = uncompress_wrapper(block, &bytes, (const unsigned char *) buffer, c_byte); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("uncompress failed, not enough " "memory\n"); else if(res == Z_BUF_ERROR) ERROR("uncompress failed, not enough " "room in output buffer\n"); else ERROR("uncompress failed, unknown error " "%d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_destination(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, unsigned int *id_table) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start " "0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx " "containing root inode\n", start); *root_inode_block = bytes; } if(size - bytes < SQUASHFS_METADATA_SIZE) { *inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE); if(*inode_table == NULL) return FALSE; } TRACE("scan_inode_table: reading block 0x%llx\n", start); byte = read_block(fd, start, &start, *inode_table + bytes, sBlk); if(byte == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain * the last directory start block index. This is used when calculating * the total uncompressed directory size. The directory bytes in the * last * block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, (squashfs_base_inode_header *) (*inode_table + bytes)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, (squashfs_dir_inode_header *) (*inode_table + bytes)); directory_start_block = dir_inode->dir.start_block; } else { SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, (squashfs_ldir_inode_header *) (*inode_table + bytes)); directory_start_block = dir_inode->ldir.start_block; } get_uid(id_table[dir_inode->base.uid]); get_guid(id_table[dir_inode->base.guid]); for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { SQUASHFS_SWAP_REG_INODE_HEADER(&inode, (squashfs_reg_inode_header *) cur_ptr); TRACE("scan_inode_table: processing inode @ byte position " "0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); get_uid(id_table[inode.uid]); get_guid(id_table[inode.guid]); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, " "file_size %d, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, (unsigned int *) cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, (squashfs_lreg_inode_header *) cur_ptr); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular " "file, file_size %lld, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, (unsigned int *) cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, (squashfs_symlink_inode_header *) cur_ptr); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, (squashfs_dir_inode_header *) cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, (squashfs_ldir_inode_header *) cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; SQUASHFS_SWAP_DIR_INDEX(&index, (squashfs_dir_index *) cur_ptr); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in " "scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, char *source) { read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); SQUASHFS_INSWAP_SUPER_BLOCK(sBlk); if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) ERROR("Pre 4.0 big-endian filesystem on %s, appending" " to this is unsupported\n", source); else ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 4) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem." " Appending\nto SQUASHFS %d.%d filesystems is " "not supported. Please convert it to a " "SQUASHFS 4 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later " "filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } printf("Found a valid %sSQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of ids %d\n", sBlk->no_ids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1)); if(directory_table == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so " "far %d\n", start, bytes); last_start_block = start; byte = read_block(fd, start, &start, directory_table + bytes, sBlk); if(byte == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, (squashfs_dir_header *) (directory_table + bytes)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position " "0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, (squashfs_dir_entry *) (directory_table + bytes)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, " "inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } unsigned int *read_id_table(int fd, squashfs_super_block *sBlk) { int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids); long long index[indexes]; int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids); unsigned int *id_table; int i; id_table = malloc(bytes); if(id_table == NULL) { ERROR("Failed to allocate id table\n"); return NULL; } read_destination(fd, sBlk->id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), (char *) index); SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); for(i = 0; i < indexes; i++) { int length; length = read_block(fd, index[i], NULL, ((unsigned char *) id_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read id table block %d, from 0x%llx, length %d\n", i, index[i], length); } SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); for(i = 0; i < sBlk->no_ids; i++) { TRACE("Adding id %d to id tables\n", id_table[i]); create_id(id_table[i]); } return id_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; *fragment_table = malloc(sBlk->fragments * sizeof(squashfs_fragment_entry)); if(*fragment_table == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } read_destination(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } for(i = 0; i < sBlk->fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]); return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; *inode_lookup_table = malloc(lookup_bytes); if(*inode_lookup_table == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } read_destination(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); SQUASHFS_INSWAP_LONG_LONGS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length " "%d\n", i, index[i], length); } SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start; long long end = sBlk->directory_table_start; long long root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode); unsigned int root_inode_block, files; squashfs_inode_header inode; unsigned int *id_table; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; id_table = read_id_table(fd, sBlk); if(id_table == NULL) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count, id_table)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry); if(directory_table == NULL) { ERROR("read_filesystem: Could not read root directory" "\n"); goto error; } root_inode_start -= start; *cinode_table = malloc(root_inode_start); if(*cinode_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem inode table\n"); goto error; } read_destination(fd, start, root_inode_start, *cinode_table); *cdirectory_table = malloc(*last_directory_block); if(*cdirectory_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem directory table\n"); goto error; } read_destination(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); *data_cache = malloc(root_inode_offset + *root_inode_size); if(*data_cache == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); *directory_data_cache = malloc(*inode_dir_offset + *inode_dir_file_size); if(*directory_data_cache == NULL) { ERROR("read_filesystem: failed to alloc directory " "cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/read_fs.h ================================================ #ifndef READ_FS_H #define READ_FS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(d, s, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(d, s, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) swap_le64_num(s, d, n) #define SWAP_LE16(d, s, field) swap_le16(&((s)->field), &((d)->field)) #define SWAP_LE32(d, s, field) swap_le32(&((s)->field), &((d)->field)) #define SWAP_LE64(d, s, field) swap_le64(&((s)->field), &((d)->field)) #define SWAP_LES16(d, s, field) swap_le16((unsigned short *) &((s)->field), \ (unsigned short *) &((d)->field)) #else #define SQUASHFS_MEMCPY(d, s, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(d, s, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(d, s, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) \ memcpy(d, s, n * sizeof(long long)) #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino " "%llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is " "supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry"); ERROR(" should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to " "$PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source " "directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory " "test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more " "than one source entry! Please use an absolute path." "\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of " "-32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s" "\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes " "LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-4.0-lzma/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; char read; struct inode_info *next; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/squashfs_compat.h ================================================ #ifndef SQUASHFS_COMPAT #define SQUASHFS_COMPAT /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_compat.h */ /* * definitions for structures on disk - layout 3.x */ #define SQUASHFS_CHECK 2 #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 struct squashfs_super_block_3 { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index_3 { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER_3 \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; } __attribute__ ((packed)); struct squashfs_ipc_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index_3 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_3 { struct squashfs_base_inode_header_3 base; struct squashfs_dev_inode_header_3 dev; struct squashfs_symlink_inode_header_3 symlink; struct squashfs_reg_inode_header_3 reg; struct squashfs_lreg_inode_header_3 lreg; struct squashfs_dir_inode_header_3 dir; struct squashfs_ldir_inode_header_3 ldir; struct squashfs_ipc_inode_header_3 ipc; }; struct squashfs_dir_entry_3 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header_3 { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry_3 { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); typedef struct squashfs_super_block_3 squashfs_super_block_3; typedef struct squashfs_dir_index_3 squashfs_dir_index_3; typedef struct squashfs_base_inode_header_3 squashfs_base_inode_header_3; typedef struct squashfs_ipc_inode_header_3 squashfs_ipc_inode_header_3; typedef struct squashfs_dev_inode_header_3 squashfs_dev_inode_header_3; typedef struct squashfs_symlink_inode_header_3 squashfs_symlink_inode_header_3; typedef struct squashfs_reg_inode_header_3 squashfs_reg_inode_header_3; typedef struct squashfs_lreg_inode_header_3 squashfs_lreg_inode_header_3; typedef struct squashfs_dir_inode_header_3 squashfs_dir_inode_header_3; typedef struct squashfs_ldir_inode_header_3 squashfs_ldir_inode_header_3; typedef struct squashfs_dir_entry_3 squashfs_dir_entry_3; typedef struct squashfs_dir_header_3 squashfs_dir_header_3; typedef struct squashfs_fragment_entry_3 squashfs_fragment_entry_3; typedef union squashfs_inode_header_3 squashfs_inode_header_3; /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block_3));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER_3(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ipc_inode_header_3))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dev_inode_header_3)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_symlink_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_reg_inode_header_3));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_lreg_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ldir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_3));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_3));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_3));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_INODE_T_3(s, d) SQUASHFS_SWAP_LONG_LONGS_3(s, d, 1) #define SQUASHFS_SWAP_SHORTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_FRAGMENT_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_3));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_3(A) ((A) * sizeof(struct squashfs_fragment_entry_3)) #define SQUASHFS_FRAGMENT_INDEX_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_3(A) ((SQUASHFS_FRAGMENT_BYTES_3(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_3(A) (SQUASHFS_FRAGMENT_INDEXES_3(A) *\ sizeof(long long)) /* * definitions for structures on disk - layout 1.x */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } /* * definitions for structures on disk - layout 2.x */ struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS_3(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) ((A) * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif ================================================ FILE: src/others/squashfs-4.0-lzma/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 4 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_IDS 65536 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_MKFLAGS(noi, nod, nof, no_frag, always_frag, \ duplicate_checking, exportable) (noi | (nod << 1) | \ (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 #define SQUASHFS_LSYMLINK_TYPE 10 #define SQUASHFS_LBLKDEV_TYPE 11 #define SQUASHFS_LCHRDEV_TYPE 12 #define SQUASHFS_LFIFO_TYPE 13 #define SQUASHFS_LSOCKET_TYPE 14 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* uid lookup table defines */ #define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int)) #define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; #define ZLIB_COMPRESSION 1 #define LZMA_COMPRESSION 2 struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time /* time of filesystem creation */; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode_t root_inode; long long bytes_used; long long id_table_start; long long xattr_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; }; struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned int size; unsigned char name[0]; }; #define SQUASHFS_BASE_INODE_HEADER \ unsigned short inode_type; \ unsigned short mode; \ unsigned short uid; \ unsigned short guid; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; }; struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; }; struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int rdev; }; struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int symlink_size; char symlink[0]; }; struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned int block_list[0]; }; struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; long long file_size; long long sparse; unsigned int nlink; unsigned int fragment; unsigned int offset; unsigned int xattr; unsigned int block_list[0]; }; struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int start_block; unsigned int nlink; unsigned short file_size; unsigned short offset; unsigned int parent_inode; }; struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size; unsigned int start_block; unsigned int parent_inode; unsigned short i_count; unsigned short offset; unsigned int xattr; struct squashfs_dir_index index[0]; }; union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned short offset; short inode_number; unsigned short type; unsigned short size; char name[0]; }; struct squashfs_dir_header { unsigned int count; unsigned int start_block; unsigned int inode_number; }; struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; }; #endif ================================================ FILE: src/others/squashfs-4.0-lzma/squashfs_swap.h ================================================ #ifndef SQUASHFS_SWAP_H #define SQUASHFS_SWAP_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_swap.h */ /* * macros to convert each stucture from big endian to little endian */ #if __BYTE_ORDER == __BIG_ENDIAN extern void swap_le16(unsigned short *, unsigned short *); extern void swap_le32(unsigned int *, unsigned int *); extern void swap_le64(long long *, long long *); extern void swap_le16_num(unsigned short *, unsigned short *, int); extern void swap_le32_num(unsigned int *, unsigned int *, int); extern void swap_le64_num(long long *, long long *, int); extern unsigned short inswap_le16(unsigned short); extern unsigned int inswap_le32(unsigned int); extern long long inswap_le64(long long); extern void inswap_le16_num(unsigned short *, int); extern void inswap_le32_num(unsigned int *, int); extern void inswap_le64_num(long long *, int); #define _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, s_magic);\ SWAP_FUNC##32(s, d, inodes);\ SWAP_FUNC##32(s, d, mkfs_time);\ SWAP_FUNC##32(s, d, block_size);\ SWAP_FUNC##32(s, d, fragments);\ SWAP_FUNC##16(s, d, compression);\ SWAP_FUNC##16(s, d, block_log);\ SWAP_FUNC##16(s, d, flags);\ SWAP_FUNC##16(s, d, no_ids);\ SWAP_FUNC##16(s, d, s_major);\ SWAP_FUNC##16(s, d, s_minor);\ SWAP_FUNC##64(s, d, root_inode);\ SWAP_FUNC##64(s, d, bytes_used);\ SWAP_FUNC##64(s, d, id_table_start);\ SWAP_FUNC##64(s, d, xattr_table_start);\ SWAP_FUNC##64(s, d, inode_table_start);\ SWAP_FUNC##64(s, d, directory_table_start);\ SWAP_FUNC##64(s, d, fragment_table_start);\ SWAP_FUNC##64(s, d, lookup_table_start);\ } #define _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, index);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, size);\ } #define _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ } #define _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ } #define _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, rdev);\ } #define _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, symlink_size);\ } #define _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, fragment);\ SWAP_FUNC##32(s, d, offset);\ SWAP_FUNC##32(s, d, file_size);\ } #define _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##64(s, d, start_block);\ SWAP_FUNC##64(s, d, file_size);\ SWAP_FUNC##64(s, d, sparse);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, fragment);\ SWAP_FUNC##32(s, d, offset);\ SWAP_FUNC##32(s, d, xattr);\ } #define _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##16(s, d, file_size);\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##32(s, d, parent_inode);\ } #define _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, file_size);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, parent_inode);\ SWAP_FUNC##16(s, d, i_count);\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##32(s, d, xattr);\ } #define _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##S16(s, d, inode_number);\ SWAP_FUNC##16(s, d, type);\ SWAP_FUNC##16(s, d, size);\ } #define _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, count);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, inode_number);\ } #define _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC##64(s, d, start_block);\ SWAP_FUNC##32(s, d, size);\ } #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_LE) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_INSWAP_SUPER_BLOCK(s) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INDEX(s) \ _SQUASHFS_SWAP_DIR_INDEX(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_ENTRY(s) \ _SQUASHFS_SWAP_DIR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_HEADER(s) \ _SQUASHFS_SWAP_DIR_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, s, INSWAP_LE) #define INSWAP_LE16(s, d, field) (s)->field = inswap_le16((s)->field) #define INSWAP_LE32(s, d, field) (s)->field = inswap_le32((s)->field) #define INSWAP_LE64(s, d, field) (s)->field = inswap_le64((s)->field) #define INSWAP_LES16(s, d, field) \ (s)->field = (short) inswap_le16((unsigned short) (s)->field) #define SQUASHFS_INSWAP_INODE_T(s) s = inswap_le64(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) inswap_le16_num(s, n) #define SQUASHFS_INSWAP_INTS(s, n) inswap_le32_num(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) inswap_le64_num(s, n) #else #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_INSWAP_SUPER_BLOCK(s) #define SQUASHFS_INSWAP_DIR_INDEX(s) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_ENTRY(s) #define SQUASHFS_INSWAP_DIR_HEADER(s) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) #define SQUASHFS_INSWAP_INODE_T(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) #define SQUASHFS_INSWAP_INTS(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) #endif #endif ================================================ FILE: src/others/squashfs-4.0-lzma/swap.c ================================================ /* * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * swap.c */ #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #if __BYTE_ORDER == __BIG_ENDIAN void swap_le16(unsigned short *src, unsigned short *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[1]; d[1] = s[0]; } void swap_le32(unsigned int *src, unsigned int *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } void swap_le64(long long *src, long long *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; d[3] = s[4]; d[4] = s[3]; d[5] = s[2]; d[6] = s[1]; d[7] = s[0]; } unsigned short inswap_le16(unsigned short num) { return (num >> 8) | ((num & 0xff) << 8); } unsigned int inswap_le32(unsigned int num) { return (num >> 24) | ((num & 0xff0000) >> 8) | ((num & 0xff00) << 8) | ((num & 0xff) << 24); } long long inswap_le64(long long n) { unsigned long long num = n; return (num >> 56) | ((num & 0xff000000000000LL) >> 40) | ((num & 0xff0000000000LL) >> 24) | ((num & 0xff00000000LL) >> 8) | ((num & 0xff000000) << 8) | ((num & 0xff0000) << 24) | ((num & 0xff00) << 40) | ((num & 0xff) << 56); } #define SWAP_LE_NUM(BITS, TYPE) \ void swap_le##BITS##_num(TYPE *s, TYPE *d, int n) \ {\ int i;\ for(i = 0; i < n; i++, s++, d++)\ swap_le##BITS(s, d);\ } SWAP_LE_NUM(16, unsigned short) SWAP_LE_NUM(32, unsigned int) SWAP_LE_NUM(64, long long) #define INSWAP_LE_NUM(BITS, TYPE) \ void inswap_le##BITS##_num(TYPE *s, int n) \ {\ int i;\ for(i = 0; i < n; i++)\ s[i] = inswap_le##BITS(s[i]);\ } INSWAP_LE_NUM(16, unsigned short) INSWAP_LE_NUM(32, unsigned int) INSWAP_LE_NUM(64, long long) #endif ================================================ FILE: src/others/squashfs-4.0-lzma/uncompress.c ================================================ /* * Copyright (c) 2009 Felix Fietkau <nbd@openwrt.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * uncompress.c */ #ifdef USE_LZMA #include <LzmaLib.h> #endif #include <zlib.h> #include "squashfs_fs.h" /* compression algorithm */ int compression = ZLIB_COMPRESSION; int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, const unsigned char *src, unsigned long src_len) { int res; #ifdef USE_LZMA if (compression == LZMA_COMPRESSION) { size_t slen = src_len - LZMA_PROPS_SIZE; res = LzmaUncompress((unsigned char *)dest, dest_len, (const unsigned char *) src + LZMA_PROPS_SIZE, &slen, (const unsigned char *) src, LZMA_PROPS_SIZE); switch(res) { case SZ_OK: res = Z_OK; break; case SZ_ERROR_MEM: res = Z_MEM_ERROR; break; } } else #endif res = uncompress(dest, dest_len, src, src_len); return res; } ================================================ FILE: src/others/squashfs-4.0-lzma/uncompress.h ================================================ /* * Copyright (c) 2009 Felix Fietkau <nbd@openwrt.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * uncompress.h */ #ifdef USE_LZMA #include <LzmaLib.h> #endif extern int compression; extern int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, const unsigned char *src, unsigned long src_len); ================================================ FILE: src/others/squashfs-4.0-lzma/unsquash-1.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-1.c */ #include "unsquashfs.h" #include "squashfs_compat.h" void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; TRACE("read_block_list: blocks %d\n", blocks); for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS_3((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } int read_fragment_table_1() { TRACE("read_fragment_table\n"); return TRUE; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; i.sparse = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_1(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(((*i) = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_1() { int res; TRACE("read_uids_guids: no_uids %d, no_guids %d\n", sBlk.no_uids, sBlk.no_guids); uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int)); if(uid_table == NULL) { ERROR("read_uids_guids: failed to allocate uid/gid table\n"); return FALSE; } guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; res = read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } SQUASHFS_SWAP_INTS_3(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else { res = read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } } return TRUE; } ================================================ FILE: src/others/squashfs-4.0-lzma/unsquash-2.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-2.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_2 *fragment_table; void read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) { TRACE("read_block_list: blocks %d\n", blocks); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } int read_fragment_table_2() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return TRUE; fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry_2)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else { res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } return TRUE; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; } ================================================ FILE: src/others/squashfs-4.0-lzma/unsquash-3.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-3.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_3 *fragment_table; int read_fragment_table_3() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry_3))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.fragments), (char *) sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index, sfragment_table_index, indexes); } else { res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_3 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_3)); } } return TRUE; } void read_fragment_3(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_3 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_3(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_3 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_3(&header.base, &sinode, sizeof(squashfs_base_inode_header_3)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_3 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_3(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_3 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_3(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_3 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header_3 *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_3 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_3), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_3 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_3(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_3 dirh; char buffer[sizeof(squashfs_dir_entry_3) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_3 *dire = (squashfs_dir_entry_3 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_3 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_3(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_3 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_3(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } ================================================ FILE: src/others/squashfs-4.0-lzma/unsquash-4.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-4.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "read_fs.h" static struct squashfs_fragment_entry *fragment_table; static unsigned int *id_table; int read_fragment_table_4() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return; if((fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment table " "index\n"); return FALSE; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < sBlk.fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]); return TRUE; } void read_fragment_4(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_4(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, (squashfs_base_inode_header *) block_ptr); i.uid = (uid_t) id_table[header.base.uid]; i.gid = (uid_t) id_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; SQUASHFS_SWAP_DIR_INODE_HEADER(inode, (squashfs_dir_inode_header *) block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; SQUASHFS_SWAP_LDIR_INODE_HEADER(inode, (squashfs_ldir_inode_header *) block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; SQUASHFS_SWAP_REG_INODE_HEADER(inode, (squashfs_reg_inode_header *) block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; SQUASHFS_SWAP_LREG_INODE_HEADER(inode, (squashfs_lreg_inode_header *) block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = inode->sparse != 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { squashfs_symlink_inode_header *inode = &header.symlink; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inode, (squashfs_symlink_inode_header *) block_ptr); i.symlink = malloc(inode->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inode->symlink_size); i.symlink[inode->symlink_size] = '\0'; i.data = inode->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { squashfs_dev_inode_header *inode = &header.dev; SQUASHFS_SWAP_DEV_INODE_HEADER(inode, (squashfs_dev_inode_header *) block_ptr); i.data = inode->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: case SQUASHFS_LFIFO_TYPE: case SQUASHFS_LSOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_4(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, (squashfs_dir_header *) (directory_table + bytes)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, (squashfs_dir_entry *) (directory_table + bytes)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_4() { int res, i, indexes = SQUASHFS_ID_BLOCKS(sBlk.no_ids); long long id_index_table[indexes]; TRACE("read_uids_guids: no_ids %d\n", sBlk.no_ids); id_table = malloc(SQUASHFS_ID_BYTES(sBlk.no_ids)); if(id_table == NULL) { ERROR("read_uids_guids: failed to allocate id table\n"); return FALSE; } res = read_bytes(sBlk.id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk.no_ids), (char *) id_index_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read id index table\n"); return FALSE; } SQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes); for(i = 0; i < indexes; i++) { res = read_block(id_index_table[i], NULL, ((char *) id_table) + i * SQUASHFS_METADATA_SIZE); if(res == FALSE) { ERROR("read_uids_guids: failed to read id table block" "\n"); return FALSE; } } SQUASHFS_INSWAP_INTS(id_table, sBlk.no_ids); return TRUE; } ================================================ FILE: src/others/squashfs-4.0-lzma/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "squashfs_compat.h" #include "uncompress.h" #include "read_fs.h" struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; struct super_block sBlk; squashfs_operations s_ops; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; int use_regex = FALSE; char **created_inode; int root_process; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int inode_number = 1; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* * Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for * reading off disk and decompression. The cache grows until max_blocks * is reached, once this occurs existing discarded blocks on the free * list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* *found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* * not in the cache * * first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) goto failed; entry->data = malloc(cache->buffer_size); if(entry->data == NULL) { free(entry); goto failed; } entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* * try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* * initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* * queue to read thread to read and ultimately (via the * decompress threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_block_ready(struct cache_entry *entry, int error) { /* * mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* * if the wait_pending flag is set, one or more threads may be waiting * on this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* * wait for this cache entry to become ready, when reading and (if * necessary) decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* * finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains * accessible via the hash table it can be found getting a new lease of * life before it is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* * if the wait_free flag is set, one or more threads may be * waiting on this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } int add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], long long start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; int res, count; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) { ERROR("Read on filesystem failed because EOF\n"); return FALSE; } else if(errno != EINTR) { ERROR("Read on filesystem failed because %s\n", strerror(errno)); return FALSE; } else res = 0; } } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; res = uncompress_wrapper((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("uncompress failed, not enough " "memory\n"); else if(res == Z_BUF_ERROR) ERROR("uncompress failed, not enough " "room in output buffer\n"); else ERROR("uncompress failed, unknown error " "%d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: ERROR("read_block: failed to read block @0x%llx\n", start); return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) goto failed; res = uncompress_wrapper((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("uncompress failed, not enough " "memory\n"); else if(res == Z_BUF_ERROR) ERROR("uncompress failed, not enough " "room in output buffer\n"); else ERROR("uncompress failed, unknown error " "%d\n", res); goto failed; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) goto failed; return c_byte; } failed: ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, size); return FALSE; } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory " "in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); res = read_block(start, &start, inode_table + bytes); if(res == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read " "block \n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids " "on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } int write_bytes(int fd, char *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write on output file failed because " "%s\n", strerror(errno)); return -1; } res = 0; } } return 0; } int lseek_broken = FALSE; char *zero_data = NULL; int write_block(int file_fd, char *buffer, int size, int hole, int sparse) { off_t off = hole; if(hole) { if(sparse && lseek_broken == FALSE) { int error = lseek(file_fd, off, SEEK_CUR); if(error == -1) /* failed to seek beyond end of file */ lseek_broken = TRUE; } if((sparse == FALSE || lseek_broken) && zero_data == NULL) { if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc " "zero data block\n"); memset(zero_data, 0, block_size); } if(sparse == FALSE || lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write_bytes(file_fd, zero_data, avail_bytes) == -1) goto failure; } } } if(write_bytes(file_fd, buffer, size) == -1) goto failure; return TRUE; failure: return FALSE; } int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); if(file_fd == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); if((file = malloc(sizeof(struct squashfs_file))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* * the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are * queued separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); file->sparse = inode->sparse; queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, " "because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, " "blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink " "%s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change " "uid and gids on %s, because " "%s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create " "%s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s " "device %s, because you're not " "superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, " "because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of " "memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); res = read_block(start, &start, directory_table + bytes); if(res == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to " "read block\n"); bytes += res; } } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* * allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* * at leaf pathname component */ paths->name[i].paths = NULL; else /* * recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* * existing matching entry */ if(paths->name[i].paths == NULL) { /* * No sub-directory which means this is the leaf * component of a pre-existing extract which subsumes * the extract currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* * at leaf pathname component and child components exist * from more specific extracts, delete as they're * subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* * recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* * match on a leaf component, any subdirectories * will implicitly match, therefore return an * empty new search set */ goto empty_set; if(match) /* * match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* * no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* * one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* * found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } if(i->type == SQUASHFS_SYMLINK_TYPE || i->type == SQUASHFS_LSYMLINK_TYPE) free(i->symlink); } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s_major == 4 ? "" : swap ? "little endian " : "big endian ", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s_major == 4 ? "" : swap ? "big endian " : "little endian ", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); printf("Block size %d\n", sBlk.block_size); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); if(sBlk.s_major == 4) printf("Number of ids %d\n", sBlk.no_ids); else { printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); } TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); if(sBlk.s_major == 4) TRACE("sBlk.id_table_start 0x%llx\n", sBlk.id_table_start); else { TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); } if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { squashfs_super_block_3 sBlk_3; squashfs_super_block sBlk_4; /* * Try to read a Squashfs 4 superblock */ read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_4); swap = sBlk_4.s_magic != SQUASHFS_MAGIC; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && sBlk_4.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir_4; s_ops.read_fragment = read_fragment_4; s_ops.read_fragment_table = read_fragment_table_4; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_4; s_ops.read_uids_guids = read_uids_guids_4; memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); goto done; } /* * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock * (compatible with 1 and 2 filesystems) */ read_bytes(SQUASHFS_START, sizeof(squashfs_super_block_3), (char *) &sBlk_3); /* * Check it is a SQUASHFS superblock */ swap = 0; if(sBlk_3.s_magic != SQUASHFS_MAGIC) { if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block_3 sblk; ERROR("Reading a different endian SQUASHFS filesystem " "on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } sBlk.s_magic = sBlk_3.s_magic; sBlk.inodes = sBlk_3.inodes; sBlk.mkfs_time = sBlk_3.mkfs_time; sBlk.block_size = sBlk_3.block_size; sBlk.fragments = sBlk_3.fragments; sBlk.block_log = sBlk_3.block_log; sBlk.flags = sBlk_3.flags; sBlk.s_major = sBlk_3.s_major; sBlk.s_minor = sBlk_3.s_minor; sBlk.root_inode = sBlk_3.root_inode; sBlk.bytes_used = sBlk_3.bytes_used; sBlk.inode_table_start = sBlk_3.inode_table_start; sBlk.directory_table_start = sBlk_3.directory_table_start; sBlk.fragment_table_start = sBlk_3.fragment_table_start; sBlk.lookup_table_start = sBlk_3.lookup_table_start; sBlk.no_uids = sBlk_3.no_uids; sBlk.no_guids = sBlk_3.no_guids; sBlk.uid_start = sBlk_3.uid_start; sBlk.guid_start = sBlk_3.guid_start; /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk_3.bytes_used_2; sBlk.uid_start = sBlk_3.uid_start_2; sBlk.guid_start = sBlk_3.guid_start_2; sBlk.inode_table_start = sBlk_3.inode_table_start_2; sBlk.directory_table_start = sBlk_3.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk_3.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; s_ops.read_uids_guids = read_uids_guids_1; } else { sBlk.fragment_table_start = sBlk_3.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_2; s_ops.read_uids_guids = read_uids_guids_1; } } else if(sBlk.s_major == 3) { s_ops.squashfs_opendir = squashfs_opendir_3; s_ops.read_fragment = read_fragment_3; s_ops.read_fragment_table = read_fragment_table_3; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_3; s_ops.read_uids_guids = read_uids_guids_1; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } done: compression = sBlk.compression; return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* * reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_bytes(entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* * queue successfully read block to the deflate * thread(s) for further processing */ queue_put(to_deflate, entry); else /* * block has either been successfully read and is * uncompressed, or an error has occurred, clear pending * flag, set error appropriately, and wake up any * threads waiting on this buffer */ cache_block_ready(entry, !res); } } /* * writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; int hole = 0; int failed = FALSE; int error; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed) continue; error = write_block(file_fd, block->buffer->data + block->offset, block->size, hole, file->sparse); if(error == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* * corner case for hole extending to end of file */ if(file->sparse == FALSE || lseek(file_fd, hole, SEEK_CUR) == -1) { /* * for files which we don't want to write * sparsely, or for broken lseeks which cannot * seek beyond end of file, write_block will do * the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole, file->sparse) == FALSE) { ERROR("writer: failed to write sparse " "data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data " "block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* * decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; while(1) { struct cache_entry *entry = queue_get(to_deflate); int res; unsigned long bytes = block_size; res = uncompress_wrapper((unsigned char *) tmp, &bytes, (const unsigned char *) entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); if(res != Z_OK) { if(res == Z_MEM_ERROR) ERROR("uncompress failed, not enough" "memory\n"); else if(res == Z_BUF_ERROR) ERROR("uncompress failed, not enough " "room in output buffer\n"); else ERROR("uncompress failed, unknown error " "%d\n", res); } else memcpy(entry->data, tmp, bytes); /* * block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res != Z_OK); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; static int tty = -1; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 4.0 (2009/04/05)\n");\ printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\ "\n\n");\ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,"\ "\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,"\ "\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ "\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; struct winsize winsize; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(lsonly || info) progress = FALSE; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or " "files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and " "copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " "default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress " "bar\n"); ERROR("\t-p[rocessors] <number>\tuse <number> " "processors. By default will use\n"); ERROR("\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are " "unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are " "unsquashed with file\n"); ERROR("\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" "\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file " "attributes (like\n"); ERROR("\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then " "overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " "information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or " "files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to " "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to " "<size> Mbytes. Default %d\n\t\t\t\t Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX " "regular expressions\n"); ERROR("\t\t\t\trather than use the default shell " "wildcard\n\t\t\t\texpansion (globbing)\n"); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; block_log = sBlk.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate data\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); if(s_ops.read_uids_guids() == FALSE) EXIT_UNSQUASH("failed to uid/gid table\n"); if(s_ops.read_fragment_table() == FALSE) EXIT_UNSQUASH("failed to read fragment table\n"); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); inode_number = 1; printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-4.0-lzma/unsquashfs.h ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.h */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "global.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) /* * Unified superblock containing fields for all superblocks */ struct super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode_t root_inode; long long bytes_used; long long id_table_start; long long xattr_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; /* fields only used by squashfs 3 and earlier layouts */ unsigned int no_uids; unsigned int no_guids; long long uid_start; long long guid_start; }; struct hash_table_entry { long long start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char *symlink; time_t time; int type; uid_t uid; char sparse; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); int (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); int (*read_uids_guids)(); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; char sparse; }; struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 /* globals */ extern struct super_block sBlk; extern squashfs_operations s_ops; extern int swap; extern char *inode_table, *directory_table; extern struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; extern unsigned int *uid_table, *guid_table; extern pthread_mutex_t screen_mutex; extern int progress_enabled; extern int inode_number; extern int lookup_type[]; /* unsquashfs.c */ extern int lookup_entry(struct hash_table_entry **, long long); extern int read_bytes(long long, int, char *); extern int read_block(long long, long long *, char *); /* unsquash-1.c */ extern void read_block_list_1(unsigned int *, char *, int); extern int read_fragment_table_1(); extern struct inode *read_inode_1(unsigned int, unsigned int); extern struct dir *squashfs_opendir_1(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_1(); /* unsquash-2.c */ extern void read_block_list_2(unsigned int *, char *, int); extern int read_fragment_table_2(); extern void read_fragment_2(unsigned int, long long *, int *); extern struct inode *read_inode_2(unsigned int, unsigned int); /* unsquash-3.c */ extern int read_fragment_table_3(); extern void read_fragment_3(unsigned int, long long *, int *); extern struct inode *read_inode_3(unsigned int, unsigned int); extern struct dir *squashfs_opendir_3(unsigned int, unsigned int, struct inode **); /* unsquash-4.c */ extern int read_fragment_table_4(); extern void read_fragment_4(unsigned int, long long *, int *); extern struct inode *read_inode_4(unsigned int, unsigned int); extern struct dir *squashfs_opendir_4(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_4(); ================================================ FILE: src/others/squashfs-4.0-realtek/Makefile ================================================ # # Building LZMA support # Download LZMA sdk (4.65 used in development, other versions may work), # set LZMA_DIR to unpacked source, and uncomment next line LZMA_SUPPORT = 1 LZMA_DIR = ./lzma #LZMA_DIR = ../../lzma465 #LZMA_DIR = ../../LZMA/lzma465 CC=gcc #Compression default. COMP_DEFAULT = gzip INCLUDEDIR = -I. INSTALL_DIR = /usr/local/bin MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \ gzip_wrapper.o UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ unsquash-4.o swap.o compressor.o gzip_wrapper.o CFLAGS = $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall ifdef LZMA_SUPPORT LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o INCLUDEDIR += -I$(LZMA_DIR)/C CFLAGS += -DLZMA_SUPPORT MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) endif .PHONY: all all: mksquashfs unsquashfs mksquashfs: $(MKSQUASHFS_OBJS) $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ squashfs_swap.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h sort.o: sort.c squashfs_fs.h global.h sort.h swap.o: swap.c pseudo.o: pseudo.c pseudo.h compressor.o: compressor.c compressor.h unsquashfs: $(UNSQUASHFS_OBJS) $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@ unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ squashfs_compat.h global.h unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \ global.h unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \ squashfs_compat.h global.h unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \ global.h unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ global.h .PHONY: romfs @echo "Done" .PHONY: clean clean: -rm -f *.o mksquashfs unsquashfs .PHONY: install install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs $(INSTALL_DIR) cp unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-4.0-realtek/compressor.c ================================================ /* * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.c */ #include <stdio.h> #include <string.h> #include "compressor.h" #include "squashfs_fs.h" extern int gzip_compress(void **, char *, char *, int, int, int *); extern int gzip_uncompress(char *, char *, int, int, int *); extern int lzma_compress(void **, char *, char *, int, int, int *); extern int lzma_uncompress(char *, char *, int, int, int *); struct compressor compressor[] = { { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, #ifdef LZMA_SUPPORT { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, #else { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, #endif { NULL, NULL , 0, "unknown", 0} }; struct compressor *lookup_compressor(char *name) { int i; for(i = 0; compressor[i].id; i++) if(strcmp(compressor[i].name, name) == 0) break; return &compressor[i]; } struct compressor *lookup_compressor_id(int id) { int i; for(i = 0; compressor[i].id; i++) if(id == compressor[i].id) break; return &compressor[i]; } void display_compressors(char *indent, char *def_comp) { int i; for(i = 0; compressor[i].id; i++) if(compressor[i].supported) fprintf(stderr, "%s\t%s%s\n", indent, compressor[i].name, strcmp(compressor[i].name, def_comp) == 0 ? " (default)" : ""); } ================================================ FILE: src/others/squashfs-4.0-realtek/compressor.h ================================================ /* * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.h */ struct compressor { int (*compress)(void **, char *, char *, int, int, int *); int (*uncompress)(char *, char *, int, int, int *); int id; char *name; int supported; }; extern struct compressor *lookup_compressor(char *); extern struct compressor *lookup_compressor_id(int); extern void display_compressors(char *, char *); ================================================ FILE: src/others/squashfs-4.0-realtek/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; typedef unsigned int squashfs_id; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/gzip_wrapper.c ================================================ /* * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * gzip_wrapper.c */ #include <zlib.h> #include <stdlib.h> int gzip_compress(void **strm, char *d, char *s, int size, int block_size, int *error) { int res = 0; z_stream *stream = *strm; if(stream == NULL) { if((stream = *strm = malloc(sizeof(z_stream))) == NULL) goto failed; stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; if((res = deflateInit(stream, 9)) != Z_OK) goto failed; } else if((res = deflateReset(stream)) != Z_OK) goto failed; stream->next_in = (unsigned char *) s; stream->avail_in = size; stream->next_out = (unsigned char *) d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res == Z_STREAM_END) /* * Success, return the compressed size. */ return (int) stream->total_out; if(res == Z_OK) /* * Output buffer overflow. Return out of buffer space */ return 0; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } int gzip_uncompress(char *d, char *s, int size, int block_size, int *error) { int res; unsigned long bytes = block_size; res = uncompress((unsigned char *) d, &bytes, (const unsigned char *) s, size); *error = res; return res == Z_OK ? (int) bytes : -1; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.62 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CFileItem *f = db.db.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zBuf.c ================================================ /* 7zBuf.c -- Byte Buffer 2008-03-28 Igor Pavlov Public domain */ #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)alloc->Alloc(alloc, size); if (p->data != 0) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zBuf.h ================================================ /* 7zBuf.h -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zBuf2.c ================================================ /* 7zBuf2.c -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)alloc->Alloc(alloc, newSize); if (data == 0) return 0; p->size = newSize; memcpy(data, p->data, p->pos); alloc->Free(alloc, p->data); p->data = data; } memcpy(p->data + p->pos, buf, size); p->pos += size; return 1; } void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zCrc.c ================================================ /* 7zCrc.c -- CRC32 calculation 2008-08-05 Igor Pavlov Public domain */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zCrc.h ================================================ /* 7zCrc.h -- CRC32 calculation 2008-03-13 Igor Pavlov Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zFile.c ================================================ /* 7zFile.c -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include <errno.h> #endif #ifdef USE_WINDOWS_FILE /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #define kChunkSizeMax (1 << 22) #endif void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #else p->file = NULL; #endif } static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #else p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #else if (p->file != NULL) { int res = fclose(p->file); if (res != 0) return res; p->file = NULL; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fread(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fwrite(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE LARGE_INTEGER value; DWORD moveMethod; value.LowPart = (DWORD)*pos; value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ switch (origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)value.HighPart << 32) | value.LowPart; return 0; #else int moveMethod; int res; switch (origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return 1; } res = fseek(p->file, (long)*pos, moveMethod); *pos = ftell(p->file); return res; #endif } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #else long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) { CFileSeqInStream *p = (CFileSeqInStream *)pp; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->s.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(void *pp, void *buf, size_t *size) { CFileInStream *p = (CFileInStream *)pp; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) { CFileInStream *p = (CFileInStream *)pp; return File_Seek(&p->file, pos, origin); } void FileInStream_CreateVTable(CFileInStream *p) { p->s.Read = FileInStream_Read; p->s.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(void *pp, const void *data, size_t size) { CFileOutStream *p = (CFileOutStream *)pp; File_Write(&p->file, data, &size); return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->s.Write = FileOutStream_Write; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zFile.h ================================================ /* 7zFile.h -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE #endif #ifdef USE_WINDOWS_FILE #include <windows.h> #else #include <stdio.h> #endif #include "Types.h" /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #else FILE *file; #endif } CSzFile; void File_Construct(CSzFile *p); WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream s; CSzFile file; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream s; CSzFile file; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream s; CSzFile file; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zStream.c ================================================ /* 7zStream.c -- 7z Stream functions 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "Types.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) { Int64 t = offset; return stream->Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); memcpy(buf, lookBuf, *size); return stream->Skip(stream, *size); } SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; size2 = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, &size2); p->size = size2; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; if (*size > LookToRead_BUF_SIZE) *size = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Skip(void *pp, size_t offset) { CLookToRead *p = (CLookToRead *)pp; p->pos += offset; return SZ_OK; } static SRes LookToRead_Read(void *pp, void *buf, size_t *size) { CLookToRead *p = (CLookToRead *)pp; size_t rem = p->size - p->pos; if (rem == 0) return p->realStream->Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) { CLookToRead *p = (CLookToRead *)pp; p->pos = p->size = 0; return p->realStream->Seek(p->realStream, pos, origin); } void LookToRead_CreateVTable(CLookToRead *p, int lookahead) { p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact; p->s.Skip = LookToRead_Skip; p->s.Read = LookToRead_Read; p->s.Seek = LookToRead_Seek; } void LookToRead_Init(CLookToRead *p) { p->pos = p->size = 0; } static SRes SecToLook_Read(void *pp, void *buf, size_t *size) { CSecToLook *p = (CSecToLook *)pp; return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->s.Read = SecToLook_Read; } static SRes SecToRead_Read(void *pp, void *buf, size_t *size) { CSecToRead *p = (CSecToRead *)pp; return p->realStream->Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->s.Read = SecToRead_Read; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/7zVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Alloc.c ================================================ /* Alloc.c -- Memory allocation functions 2008-09-24 Igor Pavlov Public domain */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG { void *p = malloc(size); fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); return p; } #else return malloc(size); #endif } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" #include "7zDecode.h" #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_Construct(&state); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) { if (state.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(inStream->Skip((void *)inStream, curSize)); } return SZ_OK; } #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } UInt64 GetSum(const UInt64 *values, UInt32 index) { UInt64 sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CSzCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; UInt64 unpackSize = folder->UnpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); if (temp == 0 && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = GetSum(packSizes, si); inSize = packSizes[si]; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } else { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZ_ERROR_UNSUPPORTED; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); UInt64 s3Size = packSizes[1]; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZ_ERROR_MEM; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) res = Bcj2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], tempBuf[2], tempSizes[2], outBuffer, outSize); RINOK(res) } else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SRes res = SzDecode2(packSizes, folder, inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) IAlloc_Free(allocMain, tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "7zDecode.h" #include "7zExtract.h" SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzAr_Extract( const CSzArEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c -- 7z Input functions 2008-12-31 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "../../CpuArch.h" #include "7zDecode.h" #include "7zIn.h" #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->FolderStartPackStreamIndex = 0; p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } /* UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CSzFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) { UInt32 startPos = 0; UInt64 startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); for (i = 0; i < p->db.NumFolders; i++) { p->FolderStartPackStreamIndex[i] = startPos; startPos += p->db.Folders[i].NumPackStreams; } MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); for (i = 0; i < p->db.NumPackStreams; i++) { p->PackStreamStartPositions[i] = startPosSize; startPosSize += p->db.PackSizes[i]; } MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); for (i = 0; i < p->db.NumFiles; i++) { CSzFileItem *file = p->db.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { p->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderStartFileIndex[folderIndex] = i; if (p->db.Folders[folderIndex].NumUnpackStreams != 0) break; folderIndex++; } } p->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) { return p->dataPos + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) { UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; CSzFolder *folder = p->db.Folders + folderIndex; UInt64 size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; if (t < size) /* check it */ return SZ_ERROR_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SRes SzReadTime(const CObjectVector<CBuf> &dataVector, CObjectVector<CSzFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for (int i = 0; i < files.Size(); i++) { CSzFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; } } return SZ_OK; } */ static int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; static SRes SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZ_ERROR_ARCHIVE; sd->Size--; *b = *sd->Data++; return SZ_OK; } static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } static SRes SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } static SRes SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static SRes SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } static SRes SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZ_ERROR_ARCHIVE; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } static SRes SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SzSkeepData(sd)); } } static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, alloc); MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } static SRes SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, ISzAlloc *alloc) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); MY_ALLOC(UInt32, *digests, numItems, alloc); for (i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } static SRes SzReadPackInfo( CSzData *sd, UInt64 *dataOffset, UInt32 *numPackStreams, UInt64 **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, ISzAlloc *alloc) { UInt32 i; RINOK(SzReadNumber(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { RINOK(SzReadNumber(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } static SRes SzReadStreamsInfo( CSzData *sd, UInt64 *dataOffset, CSzAr *p, UInt32 *numUnpackStreams, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ ISzAlloc *alloc, ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZ_ERROR_UNSUPPORTED; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); break; } case k7zIdUnpackInfo: { RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZ_ERROR_UNSUPPORTED; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) { UInt32 i; for (i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CSzFileItem *file = files + i; while (pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZ_ERROR_ARCHIVE; if (pos + 2 > sd->Size) return SZ_ERROR_ARCHIVE; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZ_ERROR_ARCHIVE; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, alloc); len = 0; while (2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += numAdds; } } return SZ_OK; } static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->FileCRCDefined = 0; } } } return SzArEx_Fill(p, allocMain); } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; } static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzDecode(p->PackSizes, folder, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; } static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h -- 7z Input functions 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 *FolderStartPackStreamIndex; UInt64 *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; } CSzArEx; void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #include "7zItem.h" void SzCoderInfo_Init(CSzCoderInfo *p) { Buf_Init(&p->Props); } void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) { Buf_Free(&p->Props, alloc); SzCoderInfo_Init(p); } void SzFolder_Init(CSzFolder *p) { p->Coders = 0; p->BindPairs = 0; p->PackStreams = 0; p->UnpackSizes = 0; p->NumCoders = 0; p->NumBindPairs = 0; p->NumPackStreams = 0; p->UnpackCRCDefined = 0; p->UnpackCRC = 0; p->NumUnpackStreams = 0; } void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { UInt32 i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); } UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) { UInt32 result = 0; UInt32 i; for (i = 0; i < p->NumCoders; i++) result += p->Coders[i].NumOutStreams; return result; } int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } UInt64 SzFolder_GetUnpackSize(CSzFolder *p) { int i = (int)SzFolder_GetNumOutStreams(p); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolder_FindBindPairForOutStream(p, i) < 0) return p->UnpackSizes[i]; /* throw 1; */ return 0; } void SzFile_Init(CSzFileItem *p) { p->HasStream = 1; p->IsDir = 0; p->IsAnti = 0; p->FileCRCDefined = 0; p->MTimeDefined = 0; p->Name = 0; } static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Name); SzFile_Init(p); } void SzAr_Init(CSzAr *p) { p->PackSizes = 0; p->PackCRCsDefined = 0; p->PackCRCs = 0; p->Folders = 0; p->Files = 0; p->NumPackStreams = 0; p->NumFolders = 0; p->NumFiles = 0; } void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { UInt32 i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); if (p->Files) for (i = 0; i < p->NumFiles; i++) SzFile_Free(&p->Files[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" typedef struct { UInt32 NumInStreams; UInt32 NumOutStreams; UInt64 MethodID; CBuf Props; } CSzCoderInfo; void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); typedef struct { UInt32 InIndex; UInt32 OutIndex; } CBindPair; typedef struct { CSzCoderInfo *Coders; CBindPair *BindPairs; UInt32 *PackStreams; UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; int UnpackCRCDefined; UInt32 UnpackCRC; UInt32 NumUnpackStreams; } CSzFolder; void SzFolder_Init(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { CNtfsFileTime MTime; UInt64 Size; char *Name; UInt32 FileCRC; Byte HasStream; Byte IsDir; Byte IsAnti; Byte FileCRCDefined; Byte MTimeDefined; } CSzFileItem; void SzFile_Init(CSzFileItem *p); typedef struct { UInt64 *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; CSzFolder *Folders; CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; UInt32 NumFiles; } CSzAr; void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c - Test application for 7z Decoder 2008-11-23 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "7zAlloc.h" #include "7zExtract.h" #include "7zIn.h" static void ConvertNumberToString(UInt64 value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } if (InFile_Open(&archiveStream.file, args[2])) { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *f = db.db.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) ConvertFileTimeToString(&f->MTime, t); else strcpy(t, " "); printf("%s %10s %s\n", t, s, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (f->IsDir) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) { printf("\n"); continue; } res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { CSzFile outFile; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } if (OutFile_Open(&outFile, fileName)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/makefile ================================================ MY_STATIC_LINK=1 PROG = 7zDec.exe C_OBJS = \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ $O\7zStream.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c 7zBuf2.o: ../../7zBuf2.c $(CXX) $(CFLAGS) ../../7zBuf2.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c Bcj2.o: ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c 7zFile.o: ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c 7zStream.o: ../../7zStream.c $(CXX) $(CFLAGS) ../../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Bcj2.c ================================================ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bcj2.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *buffer, *bufferLim; UInt32 range, code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; buffer = buf3; bufferLim = buffer + size3; RC_INIT2 if (outSize == 0) return SZ_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; UInt32 ttt; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IF_BIT_0(prob) { UPDATE_0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UPDATE_1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return SZ_ERROR_DATA; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return SZ_ERROR_DATA; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Bcj2.h ================================================ /* Bcj2.h -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). Returns: SZ_OK SZ_ERROR_DATA - Data error */ int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Bra.c ================================================ /* Bra.c -- Converters for RISC code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 8; for (i = 0; i <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 4; for (i = 0; i <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) { UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Bra.h ================================================ /* Bra.h -- Branch converters for executables 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. Type Endian Alignment LookAhead x86 little 1 4 ARMT little 2 2 ARM little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 size must be >= Alignment + LookAhead, if it's not last block. If (size < Alignment + LookAhead), converter returns 0. Example: UInt32 ip = 0; for () { ; size must be >= Alignment + LookAhead, if it's not last block SizeT processed = Convert(data, size, ip, 1); data += processed; size -= processed; ip += processed; } */ #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Bra86.c ================================================ /* Bra86.c -- Converter for x86 code (BCJ) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *state & 0x7; if (size < 5) return 0; ip += 5; prevPosT = (SizeT)0 - 1; for (;;) { Byte *p = data + bufferPos; Byte *limit = data + size - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - data); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (ip + (UInt32)bufferPos) + src; else dest = src - (ip + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/BraIA64.c ================================================ /* BraIA64.c -- Converter for IA-64 code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" static const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 16) return 0; size -= 16; for (i = 0; i <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)data[i + j + bytePos] << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/CpuArch.h ================================================ /* CpuArch.h 2008-08-05 Igor Pavlov Public domain */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #ifdef LITTLE_ENDIAN_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #endif #if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzFindMt.c ================================================ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include "LzHash.h" #include "LzFindMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads2(name, v, action) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ { action; for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #define NO_INLINE MY_FAST_CALL Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->crc = mf->crc; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzFindMt.h ================================================ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFINDMT_H #define __LZFINDMT_H #include "Threads.h" #include "LzFind.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #include <string.h> #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ #include <string.h> /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include <stdio.h> #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifdef COMPRESS_MF_MT ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/LzmaLib.def ================================================ EXPORTS LzmaCompress LzmaUncompress ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/LzmaLib.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # End Group # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\IStream.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\LzmaLib.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/LzmaLib.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/LzmaLibExports.c ================================================ /* LzmaLibExports.c -- LZMA library DLL Entry point 2008-10-04 : Igor Pavlov : Public domain */ #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance = hInstance; dwReason = dwReason; lpReserved = lpReserved; return TRUE; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/Makefile ================================================ CC = gcc LIB = liblzma.a RM = rm -f CFLAGS = -c -O2 -Wall AR = ar RANLIB = ranlib OBJS = \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ LzmaLib.o \ 7zFile.o \ 7zStream.o \ all: $(LIB) $(LIB): $(OBJS) rm -f $@ $(AR) rcu $@ $(OBJS) $(RANLIB) $@ Alloc.o: ../Alloc.c $(CC) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CC) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CC) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CC) $(CFLAGS) ../LzmaEnc.c LzmaLib.o: ../LzmaLib.c $(CC) $(CFLAGS) ../LzmaLib.c 7zFile.o: ../7zFile.c $(CC) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CC) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) *.o *.a ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib/resource.rc ================================================ #include "../../CPP/7zip/MyVersionInfo.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib.c ================================================ /* LzmaLib.c -- LZMA library wrapper 2008-08-05 Igor Pavlov Public domain */ #include "LzmaEnc.h" #include "LzmaDec.h" #include "Alloc.h" #include "LzmaLib.h" static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaLib.h ================================================ /* LzmaLib.h -- LZMA library interface 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMALIB_H #define __LZMALIB_H #include "Types.h" #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 16 KB 0 32 1: 64 KB 0 32 2: 256 KB 0 32 3: 1 MB 0 32 4: 4 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7+: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/Lzma86Dec.c ================================================ /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2008-04-07 Igor Pavlov Public domain */ #include "Lzma86Dec.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaDec.h" #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(dest, *destLen, 0, &x86State, 0); } return SZ_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/Lzma86Dec.h ================================================ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86DEC_H #define __LZMA86DEC_H #include "../Types.h" /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/Lzma86Enc.c ================================================ /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #include <string.h> #include "Lzma86Enc.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaEnc.h" #define SZE_OUT_OVERFLOW SZE_DATA_ERROR static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; Bool useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, srcLen, 0, &x86State, 1); } } { size_t minSize = 0; Bool bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/Lzma86Enc.h ================================================ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86ENC_H #define __LZMA86ENC_H #include "../Types.h" /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, = 1 - x86 filter 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/LzmaUtil.c ================================================ /* LzmaUtil.c -- Test application for LZMA compression 2008-11-23 : Igor Pavlov : Public domain */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../Alloc.h" #include "../7zFile.h" #include "../7zVersion.h" #include "../LzmaDec.h" #include "../LzmaEnc.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; const char *kDataErrorMessage = "Data error"; static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; void PrintHelp(char *buffer) { strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" "\nUsage: lzma <e|d> inputFile outputFile\n" " e: encode file\n" " d: decode file\n"); } int PrintError(char *buffer, const char *message) { strcat(buffer, "\nError: "); strcat(buffer, message); strcat(buffer, "\n"); return 1; } int PrintErrorNumber(char *buffer, SRes val) { sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); return 1; } int PrintUserError(char *buffer) { return PrintError(buffer, "Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) { int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)); inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || thereIsSize && unpackSize == 0) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ RINOK(SeqInStream_Read(inStream, header, sizeof(header))); unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_Construct(&state); RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; rs = rs; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int main2(int numArgs, const char *args[], char *rs) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; Bool useOutFile = False; FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); if (numArgs == 1) { PrintHelp(rs); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(rs); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(rs); { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError(rs, "Incorrect UInt32 or UInt64"); } if (InFile_Open(&inStream.file, args[2]) != 0) return PrintError(rs, "Can not open input file"); if (numArgs > 3) { useOutFile = True; if (OutFile_Open(&outStream.file, args[3]) != 0) return PrintError(rs, "Can not open output file"); } else if (encodeMode) PrintUserError(rs); if (encodeMode) { UInt64 fileSize; File_GetLength(&inStream.file, &fileSize); res = Encode(&outStream.s, &inStream.s, fileSize, rs); } else { res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(rs, kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(rs, kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError(rs, kCantWriteMessage); else if (res == SZ_ERROR_READ) return PrintError(rs, kCantReadMessage); return PrintErrorNumber(rs, res); } return 0; } int MY_CDECL main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/LzmaUtil.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\7zFile.c # End Source File # Begin Source File SOURCE=..\7zFile.h # End Source File # Begin Source File SOURCE=..\7zStream.c # End Source File # Begin Source File SOURCE=..\7zVersion.h # End Source File # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\CpuArch.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/LzmaUtil.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/makefile ================================================ MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/LzmaUtil/makefile.gcc ================================================ PROG = lzma CC = gcc LIB = liblzma.a RM = rm -f CFLAGS = -c -O2 -Wall AR = ar RANLIB = ranlib OBJS = \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ LzmaLib.o \ 7zFile.o \ 7zStream.o \ all: $(PROG) $(PROG): LzmaUtil.o $(LIB) $(CC) -o $(PROG) $(LDFLAGS) $< $(LIB) LzmaUtil.o: LzmaUtil.c $(CC) $(CFLAGS) LzmaUtil.c $(LIB): $(OBJS) rm -f $@ $(AR) rcu $@ $(OBJS) $(RANLIB) $@ Alloc.o: ../Alloc.c $(CC) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CC) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CC) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CC) $(CFLAGS) ../LzmaEnc.c LzmaLib.o: ../LzmaLib.c $(CC) $(CFLAGS) ../LzmaLib.c 7zFile.o: ../7zFile.c $(CC) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CC) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) *.o *.a ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Threads.c ================================================ /* Threads.c -- multithreading library 2008-08-05 Igor Pavlov Public domain */ #include "Threads.h" #include <process.h> static WRes GetError() { DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return 0; } WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(thread->handle); } WRes WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } WRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } WRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return HandleToWRes(p->handle); } WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return HandleToWRes(p->handle); } WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Threads.h ================================================ /* Threads.h -- multithreading library 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); WRes Thread_Wait(CThread *thread); WRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); WRes Event_Set(CEvent *event); WRes Event_Reset(CEvent *event); WRes Event_Wait(CEvent *event); WRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include <stddef.h> #ifdef _WIN32 #include <windows.h> #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zDecode.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnpackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnpackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _db.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &db = _db; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = db.Folders[folderIndex]; UInt64 unpackSize = folderInfo.GetUnpackSize(); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; // Count partial_folder_size // efi.UnpackSize += unpackSize; // importantTotalUnpacked += unpackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnpacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnpacked = 0; UInt64 totalFolderUnpacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnpacked += totalFolderUnpacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnpacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnpacked = efi.UnpackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &db = volume.Database; #else const CArchiveDatabaseEx &db = _db; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = db.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&db, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = db.Folders[folderIndex]; totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef _NO_CRYPTO bool passwordIsDefined; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &db.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; UInt64 fileSize = fi.Size; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fi.CrcDefined && _checkCrc) digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/CpuArch.h" } #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _db.Files.Size(); return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidPhySize, VT_UI8}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidOffset, VT_UI8} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _db.Folders.Size(); i++) { const CFolder &f = _db.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) { UInt64 value; if (v.GetItem(index, value)) { FILETIME ft; ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); prop = ft; } } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { case kpidPath: if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; case kpidIsDir: prop = item.IsDir; break; case kpidSize: { prop = item.Size; // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _db.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; case kpidEncrypted: prop = IsEncrypted(index2); break; case kpidIsAnti: prop = _db.IsItemAnti(index2); break; #ifndef _SFX case kpidMethod: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Props.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Props.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Props; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Props.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Props; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Props.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Props.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Props[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); #ifndef _NO_CRYPTO _passwordIsDefined = false; UString password; #endif HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO , getTextPassword, _passwordIsDefined #endif ); RINOK(result); _db.Fill(); _inStream = stream; } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); return S_OK; COM_TRY_END } #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _db; #ifndef _NO_CRYPTO bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif DECL_EXTERNAL_CODECS_VARS }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = (UInt32)kNumFastBytesForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = (UInt32)kDictionaryForHeaders; oneMethodInfo.Props.Add(prop); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Props = oneMethodInfo.Props; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Props.Size(); j++) { const CProp &prop = methodFull.Props[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) { ft = 0; ftDefined = false; if (!writeTime) return S_OK; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream != 0) db = &_db; #endif CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem ui; ui.NewProperties = IntToBool(newProperties); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; if (ui.IndexInArchive != -1) { const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; ui.Size = fi.Size; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } if (ui.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) nameIsDefined = false; else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { ui.Name = NItemName::MakeLegalName(prop.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } if (ui.NewData) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } updateItems.Add(ui); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef _NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if(encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; options.HeaderOptions.WriteATime = WriteATime; options.HeaderOptions.WriteMTime = WriteMTime; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; COutArchive archive; CArchiveDatabase newDatabase; HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, archive, newDatabase, outStream, updateCallback, options); RINOK(res); updateItems.ClearAndFree(); return archive.WriteDatabase(EXTERNAL_CODECS_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttributes, kComment, kEncodedHeader, kStartPos, kDummy }; } }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" } #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { static void BoolVector_Fill_False(CBoolVector &v, int size) { v.Clear(); v.Reserve(size); for (int i = 0; i < size; i++) v.Add(false); } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) { if (index >= (UInt32)v.Size()) return true; bool res = v[index]; v[index] = true; return res; } bool CFolder::CheckStructure() const { const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax const int kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); int i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; BoolVector_Fill_False(v, UnpackSizes.Size()); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; int i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { CIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; const CCoderInfo &coder = Coders[i]; for (j = 0; j < coder.NumInStreams; j++) inStreamToCoder.Add(i); for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } for (i = 0; i < kMaskSize; i++) for (int j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; for (i = 0; i < kMaskSize; i++) if (((1 << i) & mask[i]) != 0) return false; return true; } class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); coder.Props.SetCapacity((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bp; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { folder.PackStreams.Add(i); break; } if (folder.PackStreams.Size() != 1) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { BoolVector_Fill_False(packCRCsDefined, numPackStreams); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for (CNum i = 0; i < numPackStreams; i++) packCRCs.Add(0); } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnpackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CBoolVector crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnpackCRCDefined = crcsDefined[i]; folder.UnpackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { numUnpackStreamsInFolders.Clear(); numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnpackStreamsInFolders.IsEmpty()) for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(1); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CBoolVector digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { BoolVector_Fill_False(digestsDefined, numDigestsTotal); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) digests.Add(0); } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnpackInfo: { ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for (int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles) { ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Values.Reserve(numFiles); for (int i = 0; i < numFiles; i++) { UInt64 t = 0; if (v.Defined[i]) t = ReadUInt64(); v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArchiveInfo.DataStartPosition, db.PackSizes, db.PackCRCsDefined, db.PackCRCs, db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for (int i = 0; i < db.Folders.Size(); i++) { db.NumUnpackStreamsVector.Add(1); CFolder &folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digestsDefined.Add(folder.UnpackCRCDefined); digests.Add(folder.UnpackCRC); } } db.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!db.PackSizes.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; BoolVector_Fill_False(emptyStreamVector, (int)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); size_t ppp = _inByteBack->_pos; bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (int i = 0; i < db.Files.Size(); i++) _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; file.AttribDefined = boolVector[i]; if (file.AttribDefined) file.Attrib = ReadUInt32(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; BoolVector_Fill_False(emptyFileVector, numEmptyStreams); BoolVector_Fill_False(antiFileVector, numEmptyStreams); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThrowIncorrect(); addPropIdToList = false; break; } default: addPropIdToList = isKnownType = false; } if (isKnownType) { if(addPropIdToList) db.ArchiveInfo.FileInfoPopIDs.Add(type); } else SkeepData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; CNum numAntiItems = 0; for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti.Add(isAnti); } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; public: size_t _pos; void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnpackSizes; UInt32 UnpackCRC; bool UnpackCRCDefined; CFolder(): UnpackCRCDefined(false) {} UInt64 GetUnpackSize() const // test it { if (UnpackSizes.IsEmpty()) return 0; for (int i = UnpackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnpackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } bool CheckStructure() const; }; struct CUInt64DefVector { CRecordVector<UInt64> Values; CRecordVector<bool> Defined; void Clear() { Values.Clear(); Defined.Clear(); } void ReserveDown() { Values.ReserveDown(); Values.ReserveDown(); } bool GetItem(int index, UInt64 &value) const { if (index < Defined.Size() && Defined[index]) { value = Values[index]; return true; } value = 0; return false; } void SetItem(int index, bool defined, UInt64 value) { while (index >= Defined.Size()) Defined.Add(false); Defined[index] = defined; if (!defined) return; while (index >= Values.Size()) Values.Add(0); Values[index] = value; } bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } }; struct CFileItem { UInt64 Size; UInt32 Attrib; UInt32 Crc; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; bool AttribDefined; CFileItem(): HasStream(true), IsDir(false), CrcDefined(false), AttribDefined(false) {} void SetAttrib(UInt32 attrib) { AttribDefined = true; Attrib = attrib; } }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnpackStreamsVector; CObjectVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnpackStreamsVector.Clear(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); } void ReserveDown() { PackSizes.ReserveDown(); PackCRCsDefined.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); Files.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { int size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsSolid() const { for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } void SetItemAnti(int index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; void AddFile(const CFileItem &file, const CFileItem2 &file2); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if (processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 3; return WriteDirect(buf, 8); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[24]; SetUInt64(buf + 4, h.NextHeaderOffset); SetUInt64(buf + 12, h.NextHeaderSize); SetUInt32(buf + 20, h.NextHeaderCRC); SetUInt32(buf, CrcCalc(buf + 4, 20)); return WriteDirect(buf, 24); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) { _outByte.WriteByte(b); _crc = CRC_UPDATE_BYTE(_crc, b); } else _outByte2.WriteByte(b); } void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } WriteByte(firstByte); for (;i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef _7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propsSize = coder.Props.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propsSize != 0) ? 0x20 : 0 ); WriteByte(b); WriteBytes(longID, idSize); if (isComplex) { WriteNumber(coder.NumInStreams); WriteNumber(coder.NumOutStreams); } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; WriteNumber(bindPair.InIndex); WriteNumber(bindPair.OutIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { WriteNumber(folder.PackStreams[i]); } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for (int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } void COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for (i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); if (numDefined == digestsDefined.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(digestsDefined); } for (i = 0; i < digests.Size(); i++) if (digestsDefined[i]) WriteUInt32(digests[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); for (int i = 0; i < packSizes.Size(); i++) WriteNumber(packSizes[i]); WriteHashDigests(packCRCsDefined, packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); for (int i = 0; i < folders.Size(); i++) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); int i; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnpackSizes.Size(); j++) WriteNumber(folder.UnpackSizes[j]); } CRecordVector<bool> unpackCRCsDefined; CRecordVector<UInt32> unpackCRCs; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unpackCRCsDefined.Add(folder.UnpackCRCDefined); unpackCRCs.Add(folder.UnpackCRC); } WriteHashDigests(unpackCRCsDefined, unpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { WriteByte(NID::kSubStreamsInfo); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } } bool needFlag = true; CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) { if (j + 1 != numUnpackStreamsInFolders[i]) { if (needFlag) WriteByte(NID::kSize); needFlag = false; WriteNumber(unpackSizes[index]); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnpackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } WriteHashDigests(digestsDefined2, digests2); WriteByte(NID::kEnd); } void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) { return; } /* 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } */ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) { const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8; const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); WriteByte(type); WriteNumber(dataSize); if (numDefined == v.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(v); } WriteByte(0); } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { int numDefined = 0; int i; for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) numDefined++; if (numDefined == 0) return; WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) WriteUInt64(v.Values[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnpackCRCDefined = true; folderItem.UnpackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } void COutArchive::WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; headerOffset = packedSize; WriteByte(NID::kHeader); // Archive Properties if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCsDefined, db.PackCRCs); WriteUnpackInfo(db.Folders); CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digestsDefined.Add(file.CrcDefined); digests.Add(file.Crc); } WriteSubStreamsInfo( db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.Reserve(db.Files.Size()); int numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) if (db.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { WriteByte(NID::kEmptyStream); WriteNumber((emptyStreamVector.Size() + 7) / 8); WriteBoolVector(emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDir); if (!file.IsDir) numEmptyFiles++; bool isAnti = db.IsItemAnti(i); antiVector.Add(isAnti); if (isAnti) numAntiItems++; } } if (numEmptyFiles > 0) { WriteByte(NID::kEmptyFile); WriteNumber((emptyFileVector.Size() + 7) / 8); WriteBoolVector(emptyFileVector); } if (numAntiItems > 0) { WriteByte(NID::kAnti); WriteNumber((antiVector.Size() + 7) / 8); WriteBoolVector(antiVector); } } } { /* ---------- Names ---------- */ int numDefined = 0; size_t namesDataSize = 0; for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; if (!name.IsEmpty()) numDefined++; namesDataSize += (name.Length() + 1) * 2; } if (numDefined > 0) { namesDataSize++; SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; for (int t = 0; t <= name.Length(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } } } } if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); int numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; boolVector.Add(defined); if (defined) numDefined++; } if (numDefined > 0) { WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (file.AttribDefined) WriteUInt32(file.Attrib); } } } WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (db.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { bool encodeHeaders = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, headerOptions, headerOffset); if (encodeHeaders) { CByteBuffer buf; buf.SetCapacity(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, headerOptions, headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, (const Byte *)buf, _countSize, packSizes, folders)); _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>()); WriteUnpackInfo(folders); WriteByte(NID::kEnd); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const { file = Files[index]; file2.CTimeDefined = CTime.GetItem(index, file2.CTime); file2.ATimeDefined = ATime.GetItem(index, file2.ATime); file2.MTimeDefined = MTime.GetItem(index, file2.MTime); file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); file2.IsAnti = IsItemAnti(index); } void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) { int index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); SetItemAnti(index, file2.IsAnti); Files.Add(file); } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; bool WriteCTime; bool WriteATime; bool WriteMTime; CHeaderOptions(): CompressMainHeader(true), WriteCTime(false), WriteATime(false), WriteMTime(true) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); void WriteUnpackInfo(const CObjectVector<CFolder> &folders); void WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); void WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCTime, NULL, kpidCTime, VT_FILETIME}, { NID::kMTime, NULL, kpidMTime, VT_FILETIME}, { NID::kATime, NULL, kpidATime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttrib, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, #ifndef _SFX { 97, NULL, kpidEncrypted, VT_BOOL}, { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if ((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // 7zUpdate.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnpackStreamsVector[i1], db.NumUnpackStreamsVector[i2])); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = ui.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = ui.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kMatchFinderForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = kDictionaryForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Props.Add(prop); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData) continue; if (!ui.HasStream()) continue; if (useFilters) { const UString name = ui.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); for (int i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (db != 0) { for(i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; for (CNum fileIndex = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fileIndex++) { if (db->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnpackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)db); } //////////////////////////// RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; if (numSolidFiles == 1) { if (ui.Size > inSizeForReduce) inSizeForReduce = ui.Size; } else inSizeForReduce += ui.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = db->Folders[folderIndex]; CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; db->GetFile(fi, file, file2); if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewProperties) { CFileItem uf; FromUpdateItemToFileItem(ui, uf, file2); uf.Size = file.Size; uf.Crc = file.Crc; uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; } } newDatabase.AddFile(file, file2); } } } folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = ui.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; if (file.Size != 0) { file.CrcDefined = true; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } newDatabase.AddFile(file, file2); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; } } groups.ClearAndFree(); { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1) if (db->Files[ui.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); newDatabase.AddFile(file, file2); } } newDatabase.ReserveDown(); return S_OK; } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { return Update2( EXTERNAL_CODECS_LOC_VARS inStream, db, updateItems, archive, newDatabase, seqOutStream, updateCallback, options); } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { int IndexInArchive; int IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; UInt32 Attrib; bool NewData; bool NewProperties; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL && result != S_FALSE) return result; } RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../../ICoder.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Props.Size(); j++) if (oneMethodInfo.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; oneMethodInfo.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); prop.Id = (name.CompareNoCase(L"D") == 0) ? NCoderPropID::kDictionarySize : NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { bool isSolid; switch(value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; WriteCTime = false; WriteATime = false; WriteMTime = true; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) { RINOK(SetBoolProperty(_encryptHeaders, value)); _encryptHeadersSpecified = true; return S_OK; } if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp prop; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); prop.Id = NCoderPropID::kDictionarySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(1).CompareNoCase(L"C") == 0) { UInt32 blockSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); prop.Id = NCoderPropID::kBlockSize; prop.Value = blockSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); prop.Id = NCoderPropID::kUsedMemorySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); } return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (value.boolVal != VARIANT_FALSE); return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } #define INTERFACE_IArchiveOpenCallback(x) \ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { INTERFACE_IArchiveOpenCallback(PURE); }; #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { INTERFACE_IArchiveExtractCallback(PURE) }; #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { INTERFACE_IArchiveOpenVolumeCallback(PURE); }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ Int32 *newData, /*1 - new data, 0 - old data */ \ Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ ) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { INTERFACE_IArchiveUpdateCallback(PURE); }; #define INTERFACE_IArchiveUpdateCallback2(x) \ INTERFACE_IArchiveUpdateCallback(x) \ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { INTERFACE_IArchiveUpdateCallback2(PURE); }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp ================================================ // LzmaArcRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "LzmaHandler.h" static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } static CArcInfo g_ArcInfo = { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; REGISTER_ARC(Lzma) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp ================================================ // LzmaFiltersDecode.cpp #include "StdAfx.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; HRESULT CDecoder::Code( DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress) { *inProcessedSize = (UInt64)(Int64)-1; if (block.FilterMethod > 1) return E_NOTIMPL; if (!_lzmaDecoder) { RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); if (_lzmaDecoder == 0) return E_NOTIMPL; } { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); } bool filteredMode = (block.FilterMethod == 1); CMyComPtr<ICompressSetOutStream> setOutStream; if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { RINOK(flush->Flush()); } RINOK(setOutStream->ReleaseOutStream()); } CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); if (getInStreamProcessedSize) { RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); } return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h ================================================ // LzmaFiltersDecode.h #ifndef __LZMA_FILTERS_DECODE_H #define __LZMA_FILTERS_DECODE_H #include "../../Common/CreateCoder.h" #include "LzmaItem.h" namespace NArchive { namespace NLzma { class CDecoder { CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; public: HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.cpp ================================================ // LzmaHandler.cpp #include "StdAfx.h" #include "LzmaHandler.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/DummyOutStream.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { STATPROPSTG kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_UI1} }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = 1; return S_OK; } static void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s + MyStringLen(s)); } static void DictSizeToString(UInt32 value, wchar_t *s) { for (int i = 0; i <= 31; i++) if ((UInt32(1) << i) == value) { ConvertUInt32ToString(i, s); return; } wchar_t c = L'b'; if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = L'm'; } else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = L'k'; } ConvertUInt32ToString(value, s); int p = MyStringLen(s); s[p++] = c; s[p++] = L'\0'; } static void MyStrCat(wchar_t *d, const wchar_t *s) { MyStringCopy(d + MyStringLen(d), s); } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { if (index != 0) return E_INVALIDARG; NWindows::NCOM::CPropVariant propVariant; switch(propID) { case kpidSize: if (m_StreamInfo.HasUnpackSize()) propVariant = (UInt64)m_StreamInfo.UnpackSize; break; case kpidPackSize: propVariant = (UInt64)m_PackSize; break; case kpidMethod: { wchar_t s[64]; s[0] = '\0'; if (m_StreamInfo.IsThereFilter) { const wchar_t *f; if (m_StreamInfo.FilterMethod == 0) f = L"Copy"; else if (m_StreamInfo.FilterMethod == 1) f = L"BCJ"; else f = L"Unknown"; MyStrCat(s, f); MyStrCat(s, L" "); } MyStrCat(s, L"LZMA:"); DictSizeToString(m_StreamInfo.GetDicSize(), s); propVariant = s; break; } } propVariant.Detach(value); return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* openArchiveCallback */) { { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); if (res != S_OK) return S_FALSE; Byte b; RINOK(ReadStream_FALSE(inStream, &b, 1)); if (b != 0) return S_FALSE; UInt64 endPos; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); m_Stream = inStream; } return S_OK; } STDMETHODIMP CHandler::Close() { m_Stream.Release(); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN bool allFilesMode = (numItems == UInt32(-1)); if (!allFilesMode) { if (numItems == 0) return S_OK; if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); RINOK(extractCallback->SetTotal(m_PackSize)); UInt64 currentTotalPacked = 0; CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); { CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(); if(!testMode && !realOutStream) return S_OK; extractCallback->PrepareOperation(askMode); } CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); CDecoder decoder; RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); UInt64 streamPos = m_StreamStartPosition; Int32 opRes = NArchive::NExtract::NOperationResult::kOK; bool firstItem = true; for (;;) { CHeader st; HRESULT result = ReadStreamHeader(m_Stream, st); if (result != S_OK) { if (firstItem) return E_FAIL; break; } firstItem = false; lps->OutSize = outStreamSpec->GetSize(); lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); streamPos += st.GetHeaderSize(); UInt64 packProcessed; { result = decoder.Code( EXTERNAL_CODECS_VARS st, m_Stream, outStream, &packProcessed, progress); if (result == E_NOTIMPL) { opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; } if (result == S_FALSE) { opRes = NArchive::NExtract::NOperationResult::kDataError; break; } RINOK(result); } if (packProcessed == (UInt64)(Int64)-1) break; RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); currentTotalPacked += packProcessed; streamPos += packProcessed; } outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaHandler.h ================================================ // Lzma/Handler.h #ifndef __GZIP_HANDLER_H #define __GZIP_HANDLER_H #include "Common/MyCom.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #include "LzmaIn.h" namespace NArchive { namespace NLzma { // const UInt64 k_LZMA = 0x030101; class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(IInArchive) QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Open)(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); STDMETHOD(Close)(); STDMETHOD(GetNumberOfItems)(UInt32 *numItems); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); UString GetMethodString(); public: CHandler() { } private: CHeader m_StreamInfo; UInt64 m_StreamStartPosition; UInt64 m_PackSize; CMyComPtr<IInStream> m_Stream; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaIn.cpp ================================================ // Archive/LzmaIn.cpp #include "StdAfx.h" #include "LzmaIn.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace NLzma { static bool CheckDictSize(const Byte *p) { UInt32 dicSize = GetUi32(p); int i; for (i = 1; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return false; } HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) { Byte sig[5 + 9]; RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); const Byte kMaxProp0Val = 5 * 5 * 9 - 1; if (sig[0] > kMaxProp0Val) return S_FALSE; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i]; block.IsThereFilter = false; block.FilterMethod = 0; if (!CheckDictSize(sig + 1)) { if (sig[0] > 1 || sig[1] > kMaxProp0Val) return S_FALSE; block.IsThereFilter = true; block.FilterMethod = sig[0]; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i + 1]; if (!CheckDictSize(block.LzmaProps + 1)) return S_FALSE; RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); } UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); block.UnpackSize = GetUi64(sig + unpOffset); if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) return S_FALSE; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaIn.h ================================================ // Archive/LzmaIn.h #ifndef __ARCHIVE_LZMA_IN_H #define __ARCHIVE_LZMA_IN_H #include "LzmaItem.h" #include "../../IStream.h" namespace NArchive { namespace NLzma { HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/LzmaItem.h ================================================ // Archive/LzmaItem.h #ifndef __ARCHIVE_LZMA_ITEM_H #define __ARCHIVE_LZMA_ITEM_H #include "Common/Types.h" #include "../../../../C/CpuArch.h" namespace NArchive { namespace NLzma { struct CHeader { UInt64 UnpackSize; bool IsThereFilter; Byte FilterMethod; Byte LzmaProps[5]; UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Lzma/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Split/SplitHandler.cpp ================================================ // SplitHandler.cpp #include "StdAfx.h" #include "Common/ComTry.h" #include "Common/Defs.h" #include "Common/NewHandler.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/MultiStream.h" #include "SplitHandler.h" using namespace NWindows; using namespace NTime; namespace NArchive { namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO class CSeqName { public: UString _unchangedPart; UString _changedPart; bool _splitStyle; UString GetNextName() { UString newName; if (_splitStyle) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { c = 'a'; newName = c + newName; continue; } else if (c == 'Z') { c = 'A'; newName = c + newName; continue; } c++; if ((c == 'z' || c == 'Z') && i == 0) { _unchangedPart += c; wchar_t newChar = (c == 'z') ? L'a' : L'A'; newName.Empty(); numLetters++; for (int k = 0; k < numLetters; k++) newName += newChar; break; } newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } else { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } _changedPart = newName; return _unchangedPart + _changedPart; } }; STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); if (openArchiveCallback == 0) return S_FALSE; // try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback) != S_OK) return S_FALSE; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; _name = prop.bstrVal; } int dotPos = _name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { prefix = _name.Left(dotPos + 1); ext = _name.Mid(dotPos + 1); } else ext = _name; UString extBig = ext; extBig.MakeUpper(); CSeqName seqName; int numLetters = 2; bool splitStyle = false; if (extBig.Right(2) == L"AA") { splitStyle = true; while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != 'A') break; numLetters++; } } else if (ext.Right(2) == L"01") { while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Length()) return S_FALSE; } else return S_FALSE; _streams.Add(stream); seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); seqName._changedPart = ext.Right(numLetters); seqName._splitStyle = splitStyle; if (prefix.Length() < 1) _subName = L"file"; else _subName = prefix.Left(prefix.Length() - 1); _totalSize = 0; UInt64 size; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName = seqName.GetNextName(); CMyComPtr<IInStream> nextStream; HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } } /* catch(...) { return S_FALSE; } */ return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { _sizes.Clear(); _streams.Clear(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; } prop.Detach(value); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) { COM_TRY_BEGIN if (numItems != UInt32(-1)) { if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; extractCallback->SetTotal(_totalSize); /* CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) return E_FAIL; */ UInt64 currentTotalSize = 0; UInt64 currentItemSize; RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = 0; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->PrepareOperation(askMode)); if (testMode) { RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); return S_OK; } if (!testMode && (!realOutStream)) return S_OK; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); currentItemSize = copyCoderSpec->TotalSize; } realOutStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; for (int i = 0; i < _streams.Size(); i++) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Split/SplitHandler.h ================================================ // Split/Handler.h #ifndef __SPLIT_HANDLER_H #define __SPLIT_HANDLER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../IArchive.h" namespace NArchive { namespace NSplit { class CHandler: public IInArchive, public IInArchiveGetStream, // public IOutArchive, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); private: UString _subName; UString _name; CObjectVector<CMyComPtr<IInStream> > _streams; CRecordVector<UInt64> _sizes; UInt64 _totalSize; }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Split/SplitHandlerOut.cpp ================================================ // Split/OutHandler.cpp #include "StdAfx.h" #include "SplitHandler.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" using namespace NWindows; namespace NArchive { namespace NSplit { /* STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN if (numItems != 1) return E_INVALIDARG; UInt64 volumeSize = 0; CMyComPtr<IArchiveUpdateCallback2> callback2; updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&callback2); RINOK(callback2->GetVolumeSize(0, &volumeSize)); Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; UInt32 fileIndex = 0; RINOK(updateCallback->GetUpdateItemInfo(fileIndex, &newData, &newProperties, &indexInArchive)); if (newProperties != 0) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } } UInt64 newSize; bool thereIsCopyData = false; if (newData != 0) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; newSize = prop.uhVal.QuadPart; } else thereIsCopyData = true; UInt64 pos = 0; while(pos < newSize) { } return S_OK; COM_TRY_END } */ }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Split/SplitRegister.cpp ================================================ // SplitRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "SplitHandler.h" static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } /* #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } #else #define CreateArcOut 0 #endif */ static CArcInfo g_ArcInfo = { L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; REGISTER_ARC(Split) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/Split/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Archive/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwapRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderOpt.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # Begin Group "LZM" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaItem.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ LZM_OBJS = \ $O\LzmaArcRegister.obj \ $O\LzmaFiltersDecode.obj \ $O\LzmaHandler.obj \ $O\LzmaIn.obj \ SPLIT_OBJS = \ $O\SplitHandler.obj \ $O\SplitHandlerOut.obj \ $O\SplitRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(LZM_OBJS) \ $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp $(COMPL) $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } RINOK(WriteStream(outStream, _buffer, size)); _nowPos64 += size; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { size_t processedSize = kBufferSize - bufferPos; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } RINOK(WriteStream(_outStream, _buffer, _bufferPos)); _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; size_t processedSizeTemp = kBufferSize - _bufferPos; RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); _bufferPos = _bufferPos + (UInt32)processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if (_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } UInt32 ReadBytes(Byte *buf, UInt32 size) { if ((UInt32)(_bufferLimit - _buffer) >= size) { for (UInt32 i = 0; i < size; i++) buf[i] = _buffer[i]; _buffer += size; return size; } for (UInt32 i = 0; i < size; i++) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return i; buf[i] = *_buffer++; } return size; } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; if (processedSize != NULL) *processedSize = 0; if (size > _size) { size = (UInt32)_size; if (size == 0) { _overflow = true; return E_FAIL; } } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize != NULL) *processedSize = size; return result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size) { _size = size; _overflow = false; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "MethodProps.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProps = method.Props.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProps != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; HRESULT res = S_OK; try { for (int i = 0; i < numProps; i++) { const CProp &prop = method.Props[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "../../Common/MyVector.h" #include "../../Windows/PropVariant.h" #include "MethodId.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Props; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { memcpy(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(data, _dataPointer + _pos, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memcpy(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, (size_t)size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return (rem == size ? S_OK : E_FAIL); } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); WRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/Bcj2Coder.cpp ================================================ // Bcj2Coder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/Bcj2Coder.h ================================================ // Bcj2Coder.h #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "RangeCoderBit.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/Bcj2Register.cpp ================================================ // Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BcjCoder.cpp ================================================ // BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BcjCoder.h ================================================ // BcjCoder.h #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H extern "C" { #include "../../../C/Bra.h" } #include "BranchCoder.h" struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BcjRegister.cpp ================================================ // BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BranchCoder.h ================================================ // BranchCoder.h #ifndef __COMPRESS_BRANCH_CODER_H #define __COMPRESS_BRANCH_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BranchMisc.cpp ================================================ // BranchMisc.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Bra.h" } #include "BranchMisc.h" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BranchMisc.h ================================================ // BranchMisc.h #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) MyClassA(BC_ARMT, 0x07, 1) MyClassA(BC_PPC, 0x02, 5) MyClassA(BC_SPARC, 0x08, 5) MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMT) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/ByteSwap.h ================================================ // ByteSwap.h #ifndef __COMPRESS_BYTE_SWAP_H #define __COMPRESS_BYTE_SWAP_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPY_CODER_H #define __COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/CopyRegister.cpp ================================================ // CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaEncoder.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "LzmaUtil" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #include "LzmaBenchCon.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif extern "C" { #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/LzmaUtil/Lzma86Dec.h" #include "../../../../C/LzmaUtil/Lzma86Enc.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } static void ParseUInt32(const CParser &parser, int index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) IncorrectCommand(); } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictDefined = false; UInt32 dict = (UInt32)-1; if(parser[NKey::kDict].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dict); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; size_t inSize = (size_t)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; Byte *outBuffer = 0; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictDefined) dict = 1 << 23; int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictDefined) dict = 1 << 23; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = (BSTR)(const wchar_t *)mf; props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; int numProps = kNumPropsMax; if (!mcDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; decoderSpec->FinishStream = true; const UInt32 kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int MY_CDECL main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" } #include "../../../Common/MyCom.h" #ifdef BENCH_MT #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #else #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLzma::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLzma::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe LIBS = $(LIBS) user32.lib CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ LZMA_OPT_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra86.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ C_LZMAUTIL_OBJS = \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ OBJS = \ $O\StdAfx.obj \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(C_OBJS) \ $(C_LZMAUTIL_OBJS) \ $O\FileStreams.obj \ $O\FileIO.obj \ !include "../../../Build.mak" $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZMAUTIL_OBJS): ../../../../C/LzmaUtil/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaDecoder.o \ LzmaEncoder.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ Bra86.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ Lzma86Dec.o \ Lzma86Enc.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaDecoder.o: ../LzmaDecoder.cpp $(CXX) $(CFLAGS) ../LzmaDecoder.cpp LzmaEncoder.o: ../LzmaEncoder.cpp $(CXX) $(CFLAGS) ../LzmaEncoder.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c Bra86.o: ../../../../C/Bra86.c $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c LzFind.o: ../../../../C/LzFind.c $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c LzmaDec.o: ../../../../C/LzmaDec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c LzmaEnc.o: ../../../../C/LzmaEnc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c Lzma86Dec.o: ../../../../C/LzmaUtil/Lzma86Dec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Dec.c Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma86Enc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LzmaDecoder.cpp ================================================ // LzmaDecoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) { LzmaDec_Construct(&_state); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); MyFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; LzmaDec_Init(&_state); _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.dicPos; SizeT curSize = _state.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; } #endif }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LzmaDecoder.h ================================================ // LzmaDecoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H extern "C" { #include "../../../C/LzmaDec.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif bool FinishStream; CDecoder(); virtual ~CDecoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LzmaEncoder.cpp ================================================ // LzmaEncoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; // case SZ_ERROR_THREAD: return E_FAIL; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(void *object, void *data, size_t *size) { UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); *size = curSize; return (SRes)res; } static size_t MyWrite(void *object, const void *data, size_t size) { CSeqOutStream *p = (CSeqOutStream *)object; p->Res = WriteStream(p->RealStream, data, size); if (p->Res != 0) return 0; return size; } static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } static void SzFree(void *, void *address) { MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { _seqInStream.SeqInStream.Read = MyRead; _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) throw 1; } CEncoder::~CEncoder() { if (_encoder != 0) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; switch (propIDs[i]) { case NCoderPropID::kNumFastBytes: if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; case NCoderPropID::kMatchFinderCycles: if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; case NCoderPropID::kAlgorithm: if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; case NCoderPropID::kDictionarySize: if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; case NCoderPropID::kPosStateBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; case NCoderPropID::kLitPosBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; case NCoderPropID::kLitContextBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; case NCoderPropID::kMultiThread: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; case NCoderPropID::kMatchFinder: if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; default: return E_INVALIDARG; } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte props[LZMA_PROPS_SIZE]; size_t size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); return WriteStream(outStream, props, size); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _seqOutStream.RealStream = outStream; _seqOutStream.Res = S_OK; return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _seqOutStream.RealStream.Release(); return S_OK; } typedef struct _CCompressProgressImp { ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; } CCompressProgressImp; #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) { CCompressProgressImp *p = (CCompressProgressImp *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { CCompressProgressImp progressImp; progressImp.p.Progress = CompressProgress; progressImp.Progress = progress; progressImp.Res = SZ_OK; _seqInStream.RealStream = inStream; SetOutStream(outStream); SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); ReleaseOutStream(); if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) return _seqOutStream.Res; if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) return progressImp.Res; return SResToHRESULT(res); } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LzmaEncoder.h ================================================ // LzmaEncoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H extern "C" { #include "../../../C/LzmaEnc.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { struct CSeqInStream { ISeqInStream SeqInStream; ISequentialInStream *RealStream; }; struct CSeqOutStream { ISeqOutStream SeqOutStream; CMyComPtr<ISequentialOutStream> RealStream; HRESULT Res; }; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; CSeqInStream _seqInStream; CSeqOutStream _seqOutStream; public: CEncoder(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/LzmaRegister.cpp ================================================ // LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/RangeCoder.h ================================================ // Compress/RangeCoder.h #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) { Range >>= 1; Low += Range & (0 - ((value >> numBits) & 1)); if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/RangeCoderBit.h ================================================ // Compress/RangeCoderBit.h #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 4; const int kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/Compress/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kBlockSize, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define INTERFACE_IProgress(x) \ STDMETHOD(SetTotal)(UInt64 total) x; \ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ DECL_INTERFACE(IProgress, 0, 5) { INTERFACE_IProgress(PURE) }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_7ZIP_VERSION "7-Zip 4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/PropID.h ================================================ // PropID.h #ifndef __7ZIP_PROPID_H #define __7ZIP_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; UInt32 Attrib; bool isDir; bool AttribDefined; bool MTimeDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (NFile::NFind::FindFile(fullProcessedPath, fi)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.MTimeDefined) _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if (newData != NULL) *newData = BoolToInt(true); if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) *indexInArchive = (UInt32)-1; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: prop = dirItem.Name; break; case kpidIsDir: prop = dirItem.isDir(); break; case kpidSize: prop = dirItem.Size; break; case kpidAttrib: prop = dirItem.Attrib; break; case kpidCTime: prop = dirItem.CTime; break; case kpidATime: prop = dirItem.ATime; break; case kpidMTime: prop = dirItem.MTime; break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if (dirItem.isDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////////////////// // Main function int MY_CDECL main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; command.MakeLower(); UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.Compare("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem di; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(name, fi)) { PrintString(UString(L"Can't find file") + name); return 1; } di.Attrib = fi.Attrib; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Name = name; di.FullPath = name; dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.Compare("l") == 0) listCommand = true; else if (command.Compare("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, #ifndef _NO_CRYPTO kPassword, #endif kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, #ifndef _NO_CRYPTO { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, #endif { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for (int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for (int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for (int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); UStringVector archivePaths; { CDirItems dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } for (int i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) archivePaths.Add(dirItems.GetPhyPath(i)); } } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; int i; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if (parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if (options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if (options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO bool PasswordEnabled; UString Password; #endif bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcMTimeDefault = utcMTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDir) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) INTERFACE_IArchiveExtractCallback(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _encrypted; struct CProcessedFileInfo { FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attributes; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool IsDir; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcMTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), WriteMTime(true), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch(propID) { case kpidName: prop = _subArchiveName; break; } else switch(propID) { case kpidName: prop = _fileInfo.Name; break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; case kpidCTime: prop = _fileInfo.CTime; break; case kpidATime: prop = _fileInfo.ATime; break; case kpidMTime: prop = _fileInfo.MTime; break; } prop.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (ReOpenCallback) { CMyComPtr<ICryptoGetTextPassword> getTextPassword; ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" #ifdef _NO_CRYPTO #define INTERFACE_IOpenCallbackUI_Crypto(x) #else #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ #endif #define INTERFACE_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI { INTERFACE_IOpenCallbackUI(=0) }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L"~"; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" #include "../../Archive/IArchive.h" struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UInt32 Attrib; int PhyParent; int LogParent; CDirItem(): PhyParent(-1), LogParent(-1) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; public: CObjectVector<CDirItem> Items; int GetNumFolders() const { return Prefixes.Size(); } UString GetPhyPath(int index) const; UString GetLogPath(int index) const; int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; struct CArcItem { UInt64 Size; FILETIME MTime; UString Name; bool IsDir; bool SizeDefined; bool Censored; UInt32 IndexInServer; int TimeType; CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include <stdio.h> #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; di.Name = fi.Name; dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; int len = name.Length(); int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Length(); int totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; len -= name.Length(); memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; len -= s.Length(); memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } UString CDirItems::GetPhyPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } UString CDirItems::GetLogPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); for (;;) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParent, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; if (!NFind::FindFile(phyPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); UString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParentCur, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &curFolderName, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { const UString name2 = curFolderName + (wchar_t)kDirDelimiter; int parent = dirItems.AddPrefix(phyParent, logParent, name2); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fi.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); for (int ttt = 0; ; ttt++) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); const UString &name = fi.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", options.DefaultItemName); #ifdef _WIN32 outDir.TrimRight(); #endif if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.MTime, options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } res.TrimRight(); return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static const TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fi; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) if (!fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } #ifndef _SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int slashPos2 = arcPath.ReverseFind(L'.'); int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; for (int i = 0; i < Formats.Size(); i++) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) if (Formats[i].Name.CompareNoCase(arcType) == 0) return i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (int pos = 0; pos < arcType.Length();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) pos2 = arcType.Length(); const UString name = arcType.Mid(pos, pos2 - pos); int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = pos2 + 1; } return true; } #endif #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UInt32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) { result = defaultName; NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (arcTypeIndex >= 0) orderIndices.Add(arcTypeIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; Byte hash[1 << 16]; memset(hash, 0xFF, 1 << 16); Byte prevs[256]; if (orderIndices.Size() > 255) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < 2) continue; UInt32 v = sig[0] | ((UInt32)sig[1] << 8); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize--; for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[buf[pos] | ((UInt32)buf[pos + 1] << 8)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = buf[pos] | ((UInt32)buf[pos + 1] << 8); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + 1) if (TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif } for(int i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; RINOK(result); *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { if (formatIndices.Size() >= 3) return E_NOTIMPL; int arcTypeIndex = -1; if (formatIndices.Size() >= 1) arcTypeIndex = formatIndices[formatIndices.Size() - 1]; HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); if (formatIndices.Size() == 1) return S_OK; arcTypeIndex = -1; if (formatIndices.Size() >= 2) arcTypeIndex = formatIndices[formatIndices.Size() - 2]; HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || !getStream) return resSpec; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK || !subSeqStream) return resSpec; CMyComPtr<IInStream> subStream; result = subSeqStream.QueryInterface(IID_IInStream, &subStream); if (result != S_OK || !subStream) return resSpec; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return resSpec; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result != S_OK) return resSpec; return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, NULL, openCallback); int formatInfo; return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, formatIndices, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; SetCallback(fileName, NULL, openCallback, openCallbackNew); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; bool IsOpen; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCTime: case kpidATime: case kpidMTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttrib: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name[name.Length() - 1]; if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name = name.Left(name.Length() - 1); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/StdAfx.h ================================================ // stdafx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Time.h" #include "../../Common/FileStreams.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) { if (formatIndices.Size() > 1) return false; int arcTypeIndex = -1; if (formatIndices.Size() != 0) arcTypeIndex = formatIndices[0]; if (arcTypeIndex >= 0) MethodMode.FormatIndex = arcTypeIndex; else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; if (!arcInfo.UpdateEnabled) return false; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } /* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) { return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); } */ static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArcItem> &arcItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CDirItems &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! // CUpdateProduceCallbackImp upCallback(&arcItems, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); } UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); // check it: defaultItemName !!! if (ai.Name.IsEmpty()) ai.Name = defaultItemName; RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); { CPropVariant prop; RINOK(archive->GetProperty(i, kpidSize, &prop)); ai.SizeDefined = (prop.vt != VT_EMPTY); if (ai.SizeDefined) ai.Size = ConvertPropVariantToUInt64(prop); } { CPropVariant prop; RINOK(archive->GetProperty(i, kpidTimeType, &prop)); if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; switch(ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: break; default: return E_FAIL; } } } ai.IndexInServer = i; arcItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArcItem> &arcItems, CDirItems &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, arcItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) { return Callback->ScanProgress(numFolders, numFiles, path); } }; #ifdef _WIN32 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( ULONG_PTR ulUIParam, LPSTR lpszDelimChar, LPSTR lpszFilePaths, LPSTR lpszFileNames, ULONG ulReserved ); typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; #endif HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CDirItems dirItems; if (options.StdInMode) { CDirItem di; di.Name = options.StdInFileName; di.Size = (UInt64)(Int64)-1; di.Attrib = 0; NTime::GetCurUtcFileTime(di.MTime); di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArcItem> arcItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, arcItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArcItems(0), UpdatePairs(0), NewNames(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); } */ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData != NULL) *newData = BoolToInt(up.NewData); if (newProps != NULL) *newProps = BoolToInt(up.NewProps); if (indexInArchive != NULL) { *indexInArchive = (UInt32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = up.IsAnti; prop.Detach(value); return S_OK; } if (up.IsAnti) { switch(propID) { case kpidIsDir: case kpidPath: break; case kpidSize: prop = (UInt64)0; prop.Detach(value); return S_OK; default: prop.Detach(value); return S_OK; } } if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; } } else { if (propID == kpidPath) { if (up.NewNameIndex >= 0) { prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } if (up.ExistInArchive() && Archive) { UInt32 indexInArchive; if (ArcItems == 0) indexInArchive = up.ArcIndex; else indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if (up.IsAnti) { return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); } const CDirItem &di = DirItems->Items[up.DirIndex]; RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); if (di.IsDir()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; const CDirItems *DirItems; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (ai.SizeDefined) if (di.Size != ai.Size) pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback) { for (int i = 0; i < updatePairs.Size(); i++) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); // cout << "deleting"; */ if (callback) callback->ShowDeleteFile(pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; up2.NewData = up2.NewProps = false; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; break; } operationChain.Add(up2); } operationChain.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool IsAnti; int DirIndex; int ArcIndex; int NewNameIndex; bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback { virtual HRESULT ShowDeleteFile(int arcIndex) = 0; }; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; #endif UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "Windows/Error.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsDir, L"Folder" }, { kpidSize, L"Size" }, { kpidPackSize, L"Packed Size" }, { kpidAttrib, L"Attributes" }, { kpidCTime, L"Created" }, { kpidATime, L"Accessed" }, { kpidMTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubDirs, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" }, { kpidBit64, L"64-bit" }, { kpidBigEndian, L"Big-endian" }, { kpidCpu, L"CPU" }, { kpidPhySize, L"Physical Size" }, { kpidHeadersSize, L"Headers Size" }, { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, { kpidFreeSpace, L"Free Space" }, { kpidClusterSize, L"Cluster Size" } }; static const char kEmptyAttribChar = '.'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttribString(DWORD wa, bool isDir, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; wchar_t s[32]; ConvertUInt64ToString(propID, s); return s; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&prop.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidPath) { UString s; RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); prop = s; } else { RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (prop.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: prop = defaultItemName; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidMTime) { PrintTime(prop); } else if (fieldInfo.PropID == kpidAttrib) { if (prop.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = prop.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttribString(attributes, isFolder, s); g_StdOut << s; } else if (prop.vt == VT_BSTR) { if (techMode) g_StdOut << prop.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); } else { UString s = ConvertPropertyToString(prop, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant prop; if (archive->GetProperty(index, propID, &prop) != S_OK) throw "GetPropertyValue error"; if (prop.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(prop); return true; } HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) g_StdOut << "is not supported archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" #ifndef _NO_CRYPTO " -p{Password}: set Password\n" #endif " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) throw kUnsupportedArcTypeMessage; if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, formatIndices, options.ArchiveName)) throw kUnsupportedArcTypeMessage; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int MY_CDECL main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::Open_CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(Open_CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: INTERFACE_IOpenCallbackUI(;) CStdOutStream *OutStream; #ifndef _NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; UString Password; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) { return CheckBreak(); } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { #ifdef _NO_CRYPTO *passwordIsDefined = false; return StringToBstr(L"", password); #else if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif } /* HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) { // MT_LOCK if (StdOutMode) return S_OK; RINOK(Finilize()); m_PercentPrinter.PrintString("Deleting "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), #ifndef _NO_CRYPTO PasswordIsDefined(false), AskPassword(false), #endif StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRenameAll = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/7zip/UI/Console/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DWIN_LONG_PATH \ -DEXTERNAL_LZMA \ -DEXTERNAL_CODECS \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Registry.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Threads.obj \ !include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !include "../../Crc.mak" ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Build.mak ================================================ !IFDEF CPU !IFNDEF NO_BUFFEROVERFLOWU LIBS = $(LIBS) bufferoverflowU.lib !ENDIF !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gr -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope !ELSE CFLAGS = $(CFLAGS) -W3 !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF -OPT:ICF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if (_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while (pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for (int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for (int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "MyWindows.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for (int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { public: BSTR m_str; CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memcpy(res, m_str, byteLen); return res; } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifndef _WIN32 #include <ctype.h> #endif #ifndef _UNICODE #include "StringConvert.h" #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while ((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); // int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if (realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if (newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if (_capacity > 0) { for (int i = 0; i < _length; i++) newBuffer[i] = _chars[i]; delete []_chars; } _chars = newBuffer; _chars[_length] = 0; _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if (minBufLength >= _capacity) SetCapacity(minBufLength); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if (newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if (&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for (int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for (int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } void CBaseRecordVector::ClearAndFree() { Clear(); delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta = 1; if (_capacity >= 64) delta = _capacity / 4; else if (_capacity >= 8) delta = 8; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { // if (newCapacity <= _capacity) if (newCapacity == _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = NULL; if (newSize > 0) { p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); memcpy(p, _items, _itemSize * numRecordsToMove); } delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::ReserveDown() { Reserve(_size); } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void ClearAndFree(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); void ReserveDown(); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector(): CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while (--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector() {}; ~CObjectVector() { Clear(); }; CObjectVector(const CObjectVector &v) { *this = v; } CObjectVector& operator=(const CObjectVector &v) { Clear(); return (*this += v); } CObjectVector& operator+=(const CObjectVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for (int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for (int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if (c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while ((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if (c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if (numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { int numRequiredBytes = s.Length() * 2; BOOL defUsed; int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); #ifndef _WIN32_WCE if (numChars == 0) throw 282229; #endif dest.ReleaseBuffer(numChars); } return dest; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { bool defaultCharWasUsed; return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if (!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if (!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; UInt32 v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { if (end != NULL) *end = s; return result; } result <<= 4; result |= v; s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H extern "C" { #include "../../C/Types.h" } typedef int HRes; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; int numAdds; if (srcPos == srcLen) { *destLen = destPos; return True; } c = (Byte)src[srcPos++]; if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xC0) break; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { Byte c2; if (srcPos == srcLen) break; c2 = (Byte)src[srcPos++]; if (c2 < 0x80 || c2 >= 0xC0) break; value <<= 6; value |= (c2 - 0x80); } while (--numAdds != 0); if (value < 0x10000) { if (dest) dest[destPos] = (wchar_t)value; destPos++; } else { value -= 0x10000; if (value >= 0x100000) break; if (dest) { dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); } destPos += 2; } } *destLen = destPos; return False; } static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { unsigned numAdds; UInt32 value; if (srcPos == srcLen) { *destLen = destPos; return True; } value = src[srcPos++]; if (value < 0x80) { if (dest) dest[destPos] = (char)value; destPos++; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00 || srcPos == srcLen) break; c2 = src[srcPos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; if (dest) dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); destPos++; do { numAdds--; if (dest) dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); destPos++; } while (numAdds != 0); } *destLen = destPos; return False; } bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src.Length()); wchar_t *p = dest.GetBuffer((int)destLen); Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; Utf16_To_Utf8(NULL, &destLen, src, src.Length()); char *p = dest.GetBuffer((int)destLen); Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if (CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if (!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for (int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if (string.IsEmpty()) { if (i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if (errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA fd; _handle = ::FindFirstFile(wildcard, &fd); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW fd; _handle = ::FindFirstFileW(wildcard, &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for (UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for (UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } }}} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); }}} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if (hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) { if (c != 0) *s++ = c; char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(0, st.wYear, s, 4); s = UIntToStringSpec('-', st.wMonth, s, 2); s = UIntToStringSpec('-', st.wDay, s, 2); if (includeTime) { s = UIntToStringSpec(' ', st.wHour, s, 2); s = UIntToStringSpec(':', st.wMinute, s, 2); if (includeSeconds) UIntToStringSpec(':', st.wSecond, s, 2); } return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &prop) { switch (prop.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return prop.bstrVal; case VT_UI1: return ConvertUInt64ToString(prop.bVal); case VT_UI2: return ConvertUInt64ToString(prop.uiVal); case VT_UI4: return ConvertUInt64ToString(prop.ulVal); case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); // case VT_I1: return ConvertInt64ToString(prop.cVal); case VT_I2: return ConvertInt64ToString(prop.iVal); case VT_I4: return ConvertInt64ToString(prop.lVal); case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) { switch (prop.vt) { case VT_UI1: return prop.bVal; case VT_UI2: return prop.uiVal; case VT_UI4: return prop.ulVal; case VT_UI8: return (UInt64)prop.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 operator HANDLE() { return thread.handle; } void Attach(HANDLE handle) { thread.handle = handle; } HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Time.cpp ================================================ // Windows/Time.cpp #include "StdAfx.h" #include "Time.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &fileTime)); } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { dosTime = (fileTime.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) { resSeconds = 0; if (year < 1601 || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; UInt32 numYears = year - 1601; UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += day - 1; resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } void GetCurUtcFileTime(FILETIME &ft) { SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); } }} ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); }} #endif ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/Methods.txt ================================================ 7-Zip method IDs (4.65) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - PPC (Big Endian) 03 - Alpha 01 - Alpha 04 - IA64 01 - IA64 05 - ARM 01 - ARM 06 - M68 05 - M68 (Big Endian) 07 - ARM Thumb 01 - ARMT 08 - SPARC 05 - SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-4.0-realtek/lzma/lzma.txt ================================================ LZMA SDK 4.65 ------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK Contents ----------------- LZMA SDK includes: - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory C++/7zip/Compress/LZMA_Alone and call make to recompile it: make -f makefile.gcc clean all In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, you can use LIB = -lm -static Files --------------------- lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C/ - C files 7zCrc*.* - CRC code Alloc.* - Memory allocation functions Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code LzFind.* - Match finder for LZ (LZMA) encoders LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding LzHash.h - Additional file for LZ match finder LzmaDec.* - LZMA decoding LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). Archive - files related to archiving 7z - 7z ANSI-C Decoder CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + Types.h LzmaUtil/LzmaUtil.c is example application that uses these files. Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); For full code example, look at C/LzmaUtil/LzmaUtil.c code. How To compress data -------------------- Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Check C/LzmaUtil/LzmaUtil.c as example, When to use: file->file decompressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) LZMA Defines ------------ _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: operator new(size_t size) { void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } If you use MSCV that throws exception for "new" operator, you can compile without "NewHandler.cpp". So standard exception will be used. Actually some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.0-realtek/lzma_wrapper.c ================================================ /* * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_wrapper.c */ #include <LzmaLib.h> #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) int lzma_compress(void **strm, char *dest, char *src, int size,int block_size, int *error) { unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; size_t props_size = LZMA_PROPS_SIZE, outlen = block_size - LZMA_HEADER_SIZE; int res; res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d, &props_size, 5, block_size, 3, 0, 2, 32, 1); if(res == SZ_ERROR_OUTPUT_EOF) { /* * Output buffer overflow. Return out of buffer space error */ return 0; } if(res != SZ_OK) { /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } /* * Fill in the 8 byte little endian uncompressed size field in the * LZMA header. 8 bytes is excessively large for squashfs but * this is the standard LZMA header and which is expected by the kernel * code */ d[LZMA_PROPS_SIZE] = size & 255; d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; d[LZMA_PROPS_SIZE + 4] = 0; d[LZMA_PROPS_SIZE + 5] = 0; d[LZMA_PROPS_SIZE + 6] = 0; d[LZMA_PROPS_SIZE + 7] = 0; /* * Success, return the compressed size. Outlen returned by the LZMA * compressor does not include the LZMA header space */ return outlen + LZMA_HEADER_SIZE; } int lzma_uncompress(char *dest, char *src, int size, int block_size, int *error) { unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; size_t outlen, inlen = size - LZMA_HEADER_SIZE; int res; outlen = s[LZMA_PROPS_SIZE] | (s[LZMA_PROPS_SIZE + 1] << 8) | (s[LZMA_PROPS_SIZE + 2] << 16) | (s[LZMA_PROPS_SIZE + 3] << 24); res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen, s, LZMA_PROPS_SIZE); *error = res; return res == SZ_OK ? outlen : -1; } ================================================ FILE: src/others/squashfs-4.0-realtek/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #include <sys/wait.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "global.h" #include "sort.h" #include "pseudo.h" #include "compressor.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) /* offset of data in compressed metadata blocks (allowing room for * compressed size */ #define BLOCK_OFFSET 2 int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0; int silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned int id_count = 0; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char *name; struct inode_info inode; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is * cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* in memory uid tables */ #define ID_ENTRIES 256 #define ID_HASH(id) (id & (ID_ENTRIES - 1)) #define ISA_UID 1 #define ISA_GID 2 struct id { unsigned int id; int index; char flags; struct id *next; }; struct id *id_hash_table[ID_ENTRIES]; struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS]; unsigned int uid_count = 0, guid_count = 0; unsigned int sid_count = 0, suid_count = 0, sguid_count = 0; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; struct pseudo *pseudo = NULL; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; int reader_buffer_size; int fragment_buffer_size; /* compression operations structure */ static struct compressor *comp; char *comp_name = COMP_DEFAULT; char *read_from_disk(long long start, unsigned int avail_bytes); void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo); void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); long long generic_write_table(int length, char *buffer, int uncompressed); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } #define GET_FREELIST 1 struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ #ifdef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else #endif if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else #ifndef GET_FREELIST if(cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } #endif /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found * getting a new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \ + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes); directory_cache_bytes = sdirectory_cache_bytes; inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; id_count = sid_count; longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } int mangle2(void **strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { int error, c_byte = 0; if(!uncompressed) { c_byte = comp->compress(strm, d, s, size, block_size, &error); if(c_byte == -1) BAD_ERROR("mangle2:: %s compress failed with error " "code %d\n", comp->name, error); } if(c_byte == 0 || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return c_byte; } int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { static void *stream = NULL; return mangle2(&stream, d, s, size, block_size, uncompressed, data_block); } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { inode_table = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(inode_table == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; data_cache = realloc(data_cache, cache_size + realloc_size); if(data_cache == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *) (data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } int read_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) goto bytes_read; else if(errno != EINTR) { ERROR("Read failed because %s\n", strerror(errno)); return -1; } else res = 0; } } bytes_read: return count; } void read_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_destination: reading from position 0x%llx, bytes %d\n", byte, bytes); pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(read_bytes(fd, buff, bytes) < bytes) BAD_ERROR("Read on destination failed\n"); pthread_mutex_unlock(&pos_mutex); } int write_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write failed because %s\n", strerror(errno)); return -1; } res = 0; } } return 0; } void write_destination(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(interrupted < 2) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write_bytes(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed\n"); if(interrupted < 2) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { inode_table = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(inode_table == NULL) { BAD_ERROR("Out of memory in inode table " "reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (inode_table + inode_bytes), 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += avail_bytes + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } write_destination(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(directory_table == NULL) { BAD_ERROR("Out of memory in directory table " "reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += avail_bytes + BLOCK_OFFSET; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_destination(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } long long write_id_table() { unsigned int id_bytes = SQUASHFS_ID_BYTES(id_count); char buffer[id_bytes]; unsigned int *p = (unsigned int *) buffer; int i; TRACE("write_id_table: ids %d, id_bytes %d\n", id_count, id_bytes); for(i = 0; i < id_count; i++, p++) { TRACE("write_id_table: id index %d, id %d", i, id_table[i]->id); SQUASHFS_SWAP_INTS(&id_table[i]->id, p, 1); } return generic_write_table(id_bytes, buffer, 1); } struct id *get_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = id_hash_table[hash]; for(; entry; entry = entry->next) if(entry->id == id) break; return entry; } struct id *create_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = malloc(sizeof(struct id)); if(entry == NULL) BAD_ERROR("Out of memory in create_id\n"); entry->id = id; entry->index = id_count ++; entry->flags = 0; entry->next = id_hash_table[hash]; id_hash_table[hash] = entry; id_table[entry->index] = entry; return entry; } unsigned int get_uid(unsigned int uid) { struct id *entry = get_id(uid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of uids!\n"); entry = create_id(uid); } if((entry->flags & ISA_UID) == 0) { entry->flags |= ISA_UID; uid_count ++; } return entry->index; } unsigned int get_guid(unsigned int guid) { struct id *entry = get_id(guid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of gids!\n"); entry = create_id(guid); } if((entry->flags & ISA_GID) == 0) { entry->flags |= ISA_GID; guid_count ++; } return entry->index; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in, unsigned int sparse) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((unsigned int) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((unsigned int) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("File inode, file_size %lld, start_block 0x%llx, blocks " "%d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(sparse && sparse >= byte_size) sparse = byte_size - 1; reg->sparse = sparse; SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); TRACE("Long file inode, file_size %lld, start_block 0x%llx, " "blocks %d, fragment %d, offset %d, size %d, nlink %d" "\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inodep); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { SQUASHFS_SWAP_DIR_INDEX(&index[i].index, (squashfs_dir_index *) p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block " "0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_DIR_INODE_HEADER(dir, (squashfs_dir_inode_header *) inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, " "offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); SQUASHFS_SWAP_DEV_INODE_HEADER(dev, (squashfs_dev_inode_header *) inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inodep); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, (squashfs_ipc_inode_header *) inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan3_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ..." "\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE); if(buff == NULL) { BAD_ERROR("Out of memory reallocating directory buffer" "\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < -32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) { dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index)); if(dir->index == NULL) BAD_ERROR("Out of memory in " "directory index table " "reallocation!\n"); } dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); SQUASHFS_SWAP_DIR_ENTRY(&idir, idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; directory_data_cache = realloc(directory_data_cache, directory_cache_size + realloc_size); if(directory_data_cache == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { directory_table = realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(directory_table == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) (directory_table + directory_bytes), 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0); else create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL, 0); #ifdef SQUASHFS_TRACE { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header dirh; SQUASHFS_SWAP_DIR_HEADER((squashfs_dir_header *) dirp, &dirh); count = dirh.count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh.start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; SQUASHFS_SWAP_DIR_ENTRY(idirp, &idir); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type " "%d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { squashfs_fragment_entry *disk_fragment; int size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int error, res; char *data; if(compressed_buffer) data = compressed_buffer->data; else data = read_from_disk(start_block, size); res = comp->uncompress(buffer->data, data, size, block_size, &error); if(res == -1) BAD_ERROR("%s uncompress failed with error code %d\n", comp->name, error); } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else read_destination(fd, start_block, size, buffer->data); cache_block_put(compressed_buffer); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, entry->buffer); TRACE("fragment_locked writing fragment %d, compressed size %d" "\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } int add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) return FALSE; entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); return TRUE; } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { fragment_table = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry)); if(fragment_table == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); if((ffrg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, char *buffer, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; #ifdef SQUASHFS_TRACE long long obytes = bytes; #endif for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); SQUASHFS_SWAP_SHORTS(&c_byte, (unsigned short *) cbuffer, 1); list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_destination(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; length -= avail_bytes; } SQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks); write_destination(fd, bytes, sizeof(list), (char *) list); start_bytes = bytes; bytes += sizeof(list); TRACE("total uncompressed %d compressed %lld\n", inode_count * sizeof(squashfs_inode), bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); char buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, " "size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } return generic_write_table(frag_bytes, buffer, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer); return read_from_file_buffer; } char read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk2(long long start, unsigned int avail_bytes) { read_destination(fd, start, avail_bytes, read_from_file_buffer2); return read_from_file_buffer2; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } if((frg = malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr; if((dupl_ptr = malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long target_start, dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; target_start = *start; for(block = 0; block < blocks; block ++) { int size = SQUASHFS_COMPRESSED_SIZE_BLOCK ((*block_list)[block]); struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(size == 0) continue; target_buffer = cache_lookup(writer_buffer, target_start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(target_start, size); dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else dup_data = read_from_disk2(dup_start, size); res = memcmp(target_data, dup_data, size); cache_block_put(target_buffer); cache_block_put(dup_buffer); if(res != 0) break; target_start += size; dup_start += size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start " "0x%llx, size %lld, checksum " "0x%x, fragment %d, size %d, " "offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } static int seq = 0; void reader_read_process(struct dir_ent *dir_ent) { struct file_buffer *prev_buffer = NULL, *file_buffer; int status, res, byte, count = 0; int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; long long bytes = 0; while(1) { file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; byte = read_bytes(file, file_buffer->data, block_size); if(byte == -1) goto read_err; file_buffer->size = byte; file_buffer->file_size = -1; file_buffer->block = count ++; file_buffer->error = FALSE; file_buffer->fragment = FALSE; bytes += byte; if(byte == 0) break; /* * Update estimated_uncompressed block count. This is done * on every block rather than waiting for all blocks to be * read incase write_file_process() is running in parallel * with this. Otherwise cur uncompressed block count may * get ahead of the total uncompressed block count. */ estimated_uncompressed ++; if(prev_buffer) queue_put(from_reader, prev_buffer); prev_buffer = file_buffer; } /* * Update inode file size now that the size of the dynamic pseudo file * is known. This is needed for the -info option. */ dir_ent->inode->buf.st_size = bytes; res = waitpid(child, &status, 0); if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) goto read_err; if(prev_buffer == NULL) prev_buffer = file_buffer; else { cache_block_put(file_buffer); seq --; } prev_buffer->file_size = bytes; prev_buffer->fragment = !no_fragments && (count == 2 || always_use_fragments) && (byte < block_size); queue_put(from_reader, prev_buffer); return; read_err: if(prev_buffer) { cache_block_put(file_buffer); seq --; file_buffer = prev_buffer; } file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; if((file = open(dir_ent->pathname, O_RDONLY)) == -1) goto read_err; do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; file_buffer->fragment = (file_buffer->block == frag_block); bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { char buffer; if(read_bytes(file, &buffer, 1) == 1) goto restat; } queue_put(from_reader, file_buffer); close(file); return; read_err: file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; read_err2: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } goto read_err2; } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; if(dir_ent->inode->pseudo_file) { reader_read_process(dir_ent); continue; } switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? (void *) &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write_bytes(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { void *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer; if(sparse_files && all_zero(file_buffer)) { file_buffer->c_byte = 0; queue_put(from_deflate, file_buffer); } else if(file_buffer->fragment) { file_buffer->c_byte = file_buffer->size; queue_put(from_deflate, file_buffer); } else { write_buffer = cache_get(writer_buffer, 0, 0); write_buffer->c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK (write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } } void *frag_deflator(void *arg) { void *stream = NULL; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, write_buffer); pthread_mutex_unlock(&fragment_mutex); TRACE("Writing fragment %lld, uncompressed size %d, " "compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; static int tty = -1; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); if(dir_ent->inode->nlink == 1) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, size, 0, 0, NULL, fragment, NULL, 0); return; } int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *duplicate_file) { long long read_size, file_bytes, start; struct fragment *fragment; unsigned int *block_list = NULL; int block = 0, status; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; lock_fragments(); file_bytes = 0; start = bytes; while (1) { read_size = read_buffer->file_size; if(read_buffer->fragment && read_buffer->c_byte) fragment_buffer = read_buffer; else { block_list = realloc(block_list, (block + 1) * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list" "\n"); block_list[block ++] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(read_size != -1) break; read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, block, block_list, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, block, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { long long file_bytes, start; struct fragment *fragment; unsigned int *block_list; int block, status; int blocks = (read_size + block_size - 1) >> block_log; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { int block, thresh; long long file_bytes, dup_start, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer **buffer_list; int status, num_locked_fragments; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; buffer_list = malloc(blocks * sizeof(struct file_buffer *)); if(buffer_list == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = dup_start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); if(block < thresh) { buffer_list[block] = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block] = read_buffer; } else { buffer_list[block] = NULL; sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block]) queue_put(to_writer, buffer_list[block]); fragment = get_and_fill_fragment(fragment_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block]); bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because" " %s\n", strerror(errno)); } } unlock_fragments(); cache_block_put(fragment_buffer); free(buffer_list); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; if(dir_ent->inode->nlink == 1 && read_size < (1LL << 32) && dup_start < (1LL << 32) && sparse == 0) create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, 0); else create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks]); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == -1) status = write_file_process(inode, dir_ent, read_buffer, duplicate_file); else if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(read_buffer->fragment && read_buffer->c_byte) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, " "attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation" "\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->root_entry = FALSE; inode->pseudo_file = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) { dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *)); if(dir->list == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); } if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count++]->our_dir = dir; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) continue; else return dir_info->list[current_count]; return NULL; } struct dir_ent *scan2_lookup(struct dir_info *dir, char *name) { int i; for(i = 0; i < dir->count; i++) if(strcmp(dir->list[i]->name, name) == 0) return dir->list[i]; return NULL; } struct dir_ent *scan3_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) add_dir(dir_info->list[current_count]->inode->inode, dir_info->list[current_count]->inode->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->inode->type, dir); else return dir_info->list[current_count]; return NULL; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct dir_info *dir) { dir->current_count = 0; } void scan3_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; dir_scan2(dir_info, pseudo); if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* *dummy top level directory, if multiple sources specified on * command line */ memset(&buf, 0, sizeof(buf)); buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; } else if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_info->dir_ent = dir_ent; if(sorted) generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan3(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; struct pathnames *new; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring" "\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { sub_dir = dir_scan1(filename, new, scan1_readdir); if(sub_dir == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), dir); } scan1_freedir(dir); error: return dir; } struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo) { struct dir_info *sub_dir; struct dir_ent *dir_ent; struct pseudo_entry *pseudo_ent; struct stat buf; static int pseudo_ino = 1; if(dir == NULL && (dir = scan1_opendir("")) == NULL) return NULL; while((dir_ent = scan2_readdir(dir)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *name = dir_ent->name; if((buf->st_mode & S_IFMT) == S_IFDIR) dir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo)); } while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { dir_ent = scan2_lookup(dir, pseudo_ent->name); if(pseudo_ent->dev->type == 's') { struct stat *buf; if(dir_ent == NULL) { ERROR("Pseudo set file \"%s\" does not exist " "in source filesystem. Ignoring\n", pseudo_ent->pathname); continue; } if(dir_ent->inode->root_entry) { ERROR("Pseudo set file \"%s\" is a pre-existing" " file in the filesystem being appended" " to. It cannot be modified. " "Ignoring!\n", pseudo_ent->pathname); continue; } buf = &dir_ent->inode->buf; buf->st_mode = (buf->st_mode & S_IFMT) | pseudo_ent->dev->mode; buf->st_uid = pseudo_ent->dev->uid; buf->st_gid = pseudo_ent->dev->gid; continue; } if(dir_ent) { ERROR("Pseudo file \"%s\" exists in source filesystem " "\"%s\"\n", pseudo_ent->pathname, dir_ent->pathname); ERROR("Ignoring, exclude it (-e/-ef) to override\n"); continue; } if(pseudo_ent->dev->type == 'd') { sub_dir = dir_scan2(NULL, pseudo_ent->pseudo); if(sub_dir == NULL) { ERROR("Could not create pseudo directory \"%s\"" ", skipping...\n", pseudo_ent->pathname); continue; } dir->directory_count ++; } else sub_dir = NULL; memset(&buf, 0, sizeof(buf)); buf.st_mode = pseudo_ent->dev->mode; buf.st_uid = pseudo_ent->dev->uid; buf.st_gid = pseudo_ent->dev->gid; buf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor); buf.st_mtime = time(NULL); buf.st_ino = pseudo_ino ++; if(pseudo_ent->dev->type == 'f') { #ifdef USE_TMP_FILE struct stat buf2; int res = stat(pseudo_ent->dev->filename, &buf2); if(res == -1) { ERROR("Stat on pseudo file \"%s\" failed, " "skipping...", pseudo_ent->pathname); continue; } buf.st_size = buf2.st_size; add_dir_entry(pseudo_ent->name, pseudo_ent->dev->filename, sub_dir, lookup_inode(&buf), dir); #else struct inode_info *inode = lookup_inode(&buf); inode->pseudo_id = pseudo_ent->dev->pseudo_id; inode->pseudo_file = TRUE; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, inode, dir); #endif } else add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, lookup_inode(&buf), dir); } scan2_freedir(dir); sort_directory(dir); return dir; } void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan3_init_dir(&dir); while((dir_ent = scan3_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld " "bytes %s\n", filename, (long long) buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan3(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("character device %s inode 0x%llx" "\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("fifo %s inode 0x%llx\n",dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("unix domain socket %s inode " "0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, " "mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed " "size %lld bytes LINK" "\n", filename, (long long) buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode " "0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan3_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) { \ exclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \ * sizeof(struct exclude_info)); \ if(exclude_paths == NULL) \ BAD_ERROR("Out of memory in exclude dir/file table\n"); \ } \ exclude_paths[exclude].st_dev = buf.st_dev; \ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, " "ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because " "%s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { old_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1)); if(old_root_entry == NULL) BAD_ERROR("Out of memory in old root directory entries " "reallocation\n"); old_root_entry[old_root_entries].name = strdup(name); old_root_entry[old_root_entries].inode.inode = inode; old_root_entry[old_root_entries].inode.inode_number = inode_number; old_root_entry[old_root_entries].inode.type = type; old_root_entry[old_root_entries++].inode.root_entry = TRUE; } void initialise_threads() { int i; sigset_t sigmask, old_mask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((2 + processors * 2) * sizeof(pthread_t))) == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); if(inode_count == sinode_count) goto skip_inode_hash_table; inode_lookup_table = realloc(inode_lookup_table, lookup_bytes); if(inode_lookup_table == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; SQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, (char *) inode_lookup_table, 0); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing exclude which subsumes * the exclude currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist * from more specific excludes, delete as they're * subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with " "-wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories * in the filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(squashfs_super_block *sBlk) { int recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "write_recovery_data\n"); read_destination(fd, sBlk->inode_table_start, bytes, metadata); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(recoverfd == -1) BAD_ERROR("Failed to create recovery file, because %s. " "Aborting\n", strerror(errno)); if(write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, sBlk, sizeof(squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; squashfs_super_block orig_sBlk, sBlk; char *metadata; int res; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; if((recoverfd = open(recovery_file, O_RDONLY)) == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); if((fd = open(destination_file, O_RDWR)) == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < RECOVER_ID_SIZE) BAD_ERROR("Recovery file appears to be truncated\n"); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); res = read_bytes(recoverfd, &sBlk, sizeof(squashfs_super_block)); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < sizeof(squashfs_super_block)) BAD_ERROR("Recovery file appears to be truncated\n"); read_destination(fd, 0, sizeof(squashfs_super_block), (char *) &orig_sBlk); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to " "match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; if((metadata = malloc(bytes)) == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "read_recovery_data\n"); res = read_bytes(recoverfd, metadata, bytes); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_destination(fd, 0, sizeof(squashfs_super_block), (char *) &sBlk); write_destination(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 4.1-CVS (2009/09/20)\n");\ printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int nopad = FALSE, keep_as_directory = FALSE; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; int s_minor = SQUASHFS_MINOR; pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-comp") == 0) { if(++i == argc) { ERROR("%s: -comp missing compression type\n", argv[0]); exit(1); } comp_name = argv[i]; } else if(strcmp(argv[i], "-pf") == 0) { if(++i == argc) { ERROR("%s: -pf missing filename\n", argv[0]); exit(1); } if(read_pseudo_file(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-p") == 0) { if(++i == argc) { ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } if(read_pseudo_def(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte " "or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 " "megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or " "not between 4096 and 1Mbyte\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range" "\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or " "unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range" "\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or " "unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] " "[-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nFilesystem build options:\n"); ERROR("-comp <comp>\t\tselect <comp> compression\n"); ERROR("\t\t\tCompressors available:\n"); display_compressors("\t\t\t", COMP_DEFAULT); ERROR("-b <block_size>\t\tset data block to " "<block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-no-exports\t\tdon't make the filesystem " "exportable via NFS\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for " "files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate " "checking\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " "of 4K\n"); ERROR("-keep-as-directory\tif one source directory is " "specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, " "rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("\nFilesystem filter options:\n"); ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n"); ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n"); ERROR("-sort <sort_file>\tsort files according to " "priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. " "Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files." " One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards " "(globbing) to be used in\n\t\t\texclude " "dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to " "be used in exclude\n\t\t\tdirs/files\n"); ERROR("\nFilesystem append options:\n"); ERROR("-noappend\t\tdo not append to existing " "filesystem\n"); ERROR("-root-becomes <name>\twhen appending source " "files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in " "the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new " "source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("\nMksquashfs runtime options:\n"); ERROR("-version\t\tprint version, licence and " "copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data " "using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery " "file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-progress\t\tdon't display the progress " "bar\n"); ERROR("-processors <number>\tUse <number> processors." " By default will use number of\n"); ERROR("\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> " "Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> " "Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fagment queue to " "<size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\nMiscellaneous options:\n"); ERROR("-root-owned\t\talternative name for -all-root" "\n"); ERROR("-noInodeCompression\talternative name for -noI" "\n"); ERROR("-noDataCompression\talternative name for -noD" "\n"); ERROR("-noFragmentCompression\talternative name for " "-noF\n"); exit(1); } } reader_buffer_size = readb_mbytes << (20 - block_log); writer_buffer_size = writeb_mbytes << (20 - block_log); fragment_buffer_size = fragmentb_mbytes << (20 - block_log); for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" " "because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(fd == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as " "destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR); if(fd == -1) { perror("Could not open regular file for " "writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* process the exclude files - must be done afer destination file has * been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { comp = read_super(fd, &sBlk, argv[source + 1]); if(comp == NULL) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } block_log = slog(block_size = sBlk.block_size); s_minor = sBlk.s_minor; noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); } else { comp = lookup_compressor(comp_name); if(!comp->supported) { ERROR("FATAL_ERROR: Compressor \"%s\" is not " "supported!\n", comp_name); ERROR("Compressors available:\n"); display_compressors("", COMP_DEFAULT); EXIT_MKSQUASHFS(); } } initialise_threads(); if(delete) { printf("Creating %d.%d filesystem on %s, block size %d.\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %d.%d filesystem on %s, block " "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " "-always-use-fragments,\n-exportable and -comp options " "ignored\n"); printf("\nIf appending is not wanted, please re-run with " "-noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = malloc(scache_bytes); sdirectory_data_cache = malloc(sdirectory_cache_bytes); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; sid_count = id_count; write_recovery_data(&sBlk); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_destination(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* * set the filesystem state up to be able to append to the * original filesystem. The filesystem state differs depending * on whether we're appending to the original root directory, or * if the original root directory becomes a sub-directory * (root-becomes specified on command line, here root_name != * NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = s_minor; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, no_fragments, always_use_fragments, duplicate_checking, exportable); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(interrupted < 2) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.no_ids = id_count; sBlk.id_table_start = write_id_table(); sBlk.bytes_used = bytes; sBlk.compression = comp->id; /* Xattrs are not currently supported */ sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk); write_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_destination(fd, bytes, 4096 - i, temp); } close(fd); delete_pseudo_files(); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, comp->name, block_size); printf("\t%s data, %s metadata, %s fragments\n", noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of ids (unique uids + gids) %d\n", id_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_UID) { struct passwd *user = getpwuid(id_table[i]->id); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, id_table[i]->id); } } printf("Number of gids %d\n", guid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_GID) { struct group *group = getgrgid(id_table[i]->id); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, id_table[i]->id); } } return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/mksquashfs.h ================================================ #ifndef MKSQUASHFS_H #define MKSQUASHFS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(s, d, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(s, d, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) swap_le64_num(s, d, n) #define SWAP_LE16(s, d, field) swap_le16(&((s)->field), &((d)->field)) #define SWAP_LE32(s, d, field) swap_le32(&((s)->field), &((d)->field)) #define SWAP_LE64(s, d, field) swap_le64(&((s)->field), &((d)->field)) #define SWAP_LES16(s, d, field) swap_le16((unsigned short *) &((s)->field), \ (unsigned short *) &((d)->field)) #else #define SQUASHFS_MEMCPY(s, d, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(s, d, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(s, d, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \ memcpy(d, s, n * sizeof(long long)) #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/pseudo.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.c */ #include <pwd.h> #include <grp.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include "pseudo.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); #define TRUE 1 #define FALSE 0 struct pseudo_dev **pseudo_file = NULL; int pseudo_count = 0; static void dump_pseudo(struct pseudo *pseudo, char *string) { int i; char path[1024]; for(i = 0; i < pseudo->names; i++) { struct pseudo_entry *entry = &pseudo->name[i]; if(string) strcat(strcat(strcpy(path, string), "/"), entry->name); else strcpy(path, entry->name); if(entry->pseudo == NULL) ERROR("%s %c %o %d %d %d %d\n", path, entry->dev->type, entry->dev->mode, entry->dev->uid, entry->dev->gid, entry->dev->major, entry->dev->minor); else dump_pseudo(entry->pseudo, path); } } static char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } /* * Add pseudo device target to the set of pseudo devices. Pseudo_dev * describes the pseudo device attributes. */ struct pseudo *add_pseudo(struct pseudo *pseudo, struct pseudo_dev *pseudo_dev, char *target, char *alltarget) { char targname[1024]; int i; target = get_component(target, targname); if(pseudo == NULL) { if((pseudo = malloc(sizeof(struct pseudo))) == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->names = 0; pseudo->count = 0; pseudo->name = NULL; } for(i = 0; i < pseudo->names; i++) if(strcmp(pseudo->name[i].name, targname) == 0) break; if(i == pseudo->names) { /* allocate new name entry */ pseudo->names ++; pseudo->name = realloc(pseudo->name, (i + 1) * sizeof(struct pseudo_entry)); if(pseudo->name == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->name[i].name = strdup(targname); if(target[0] == '\0') { /* at leaf pathname component */ pseudo->name[i].pseudo = NULL; pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else { /* recurse adding child components */ pseudo->name[i].dev = NULL; pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); } } else { /* existing matching entry */ if(pseudo->name[i].pseudo == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing pseudo file. */ if(target[0] != '\0') { /* entry must exist as a 'd' type pseudo file */ if(pseudo->name[i].dev->type == 'd') /* recurse adding child components */ pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); else ERROR("%s already exists as a non " "directory. Ignoring %s!\n", targname, alltarget); } else if(memcmp(pseudo_dev, pseudo->name[i].dev, sizeof(struct pseudo_dev)) != 0) ERROR("%s already exists as a different pseudo " "definition. Ignoring!\n", alltarget); else ERROR("%s already exists as an identical " "pseudo definition!\n", alltarget); } else { /* sub-directory exists which means this can only be a * 'd' type pseudo file */ if(target[0] == '\0') { if(pseudo->name[i].dev == NULL && pseudo_dev->type == 'd') { pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else ERROR("%s already exists as a " "directory. Ignoring %s!\n", targname, alltarget); } else /* recurse adding child components */ add_pseudo(pseudo->name[i].pseudo, pseudo_dev, target, alltarget); } } return pseudo; } /* * Find subdirectory in pseudo directory referenced by pseudo, matching * filename. If filename doesn't exist or if filename is a leaf file * return NULL */ struct pseudo *pseudo_subdir(char *filename, struct pseudo *pseudo) { int i; if(pseudo == NULL) return NULL; for(i = 0; i < pseudo->names; i++) if(strcmp(filename, pseudo->name[i].name) == 0) return pseudo->name[i].pseudo; return NULL; } struct pseudo_entry *pseudo_readdir(struct pseudo *pseudo) { if(pseudo == NULL) return NULL; while(pseudo->count < pseudo->names) { if(pseudo->name[pseudo->count].dev != NULL) return &pseudo->name[pseudo->count++]; else pseudo->count++; } return NULL; } int exec_file(char *command, struct pseudo_dev *dev) { int child, res; static pid_t pid = -1; int pipefd[2]; #ifdef USE_TMP_FILE char filename[1024]; int status; static int number = 0; #endif if(pid == -1) pid = getpid(); #ifdef USE_TMP_FILE sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(pipefd[1] == -1) { printf("open failed\n"); return -1; } #else res = pipe(pipefd); if(res == -1) { printf("pipe failed\n"); return -1; } #endif child = fork(); if(child == -1) { printf("fork failed\n"); goto failed; } if(child == 0) { close(STDOUT_FILENO); res = dup(pipefd[1]); if(res == -1) { printf("dup failed\n"); exit(EXIT_FAILURE); } execl("/bin/sh", "sh", "-c", command, (char *) NULL); printf("execl failed\n"); exit(EXIT_FAILURE); } #ifdef USE_TMP_FILE res = waitpid(child, &status, 0); close(pipefd[1]); if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { dev->filename = strdup(filename); return 0; } failed: unlink(filename); return -1; #else close(pipefd[1]); dev->fd = pipefd[0]; dev->child = child; return 0; failed: return -1; #endif } void add_pseudo_file(struct pseudo_dev *dev) { pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * sizeof(struct pseudo_dev *)); if(pseudo_file == NULL) BAD_ERROR("Failed to realloc pseudo_file\n"); dev->pseudo_id = pseudo_count; pseudo_file[pseudo_count ++] = dev; } void delete_pseudo_files() { #ifdef USE_TMP_FILE int i; for(i = 0; i < pseudo_count; i++) unlink(pseudo_file[i]->filename); #endif } struct pseudo_dev *get_pseudo_file(int pseudo_id) { return pseudo_file[pseudo_id]; } int read_pseudo_def(struct pseudo **pseudo, char *def) { int n, bytes; unsigned int major = 0, minor = 0, mode; char filename[2048], type, suid[100], sgid[100], *ptr; long long uid, gid; struct pseudo_dev *dev; n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, sgid, &bytes); if(n < 5) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } switch(type) { case 'b': case 'c': n = sscanf(def + bytes, "%u %u", &major, &minor); if(n < 2) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } if(major > 0xfff) { ERROR("Major %d out of range\n", major); goto error; } if(minor > 0xfffff) { ERROR("Minor %d out of range\n", minor); goto error; } case 'f': if(def[bytes] == '\0') { ERROR("Not enough arguments in pseudo file " "definition\n"); goto error; } break; case 'd': case 'm': break; default: ERROR("Unsupported type %c\n", type); goto error; } if(mode > 0777) { ERROR("Mode %o out of range\n", mode); goto error; } uid = strtoll(suid, &ptr, 10); if(*ptr == '\0') { if(uid < 0 || uid > ((1LL << 32) - 1)) { ERROR("Uid %s out of range\n", suid); goto error; } } else { struct passwd *pwuid = getpwnam(suid); if(pwuid) uid = pwuid->pw_uid; else { ERROR("Uid %s invalid uid or unknown user\n", suid); goto error; } } gid = strtoll(sgid, &ptr, 10); if(*ptr == '\0') { if(gid < 0 || gid > ((1LL << 32) - 1)) { ERROR("Gid %s out of range\n", sgid); goto error; } } else { struct group *grgid = getgrnam(sgid); if(grgid) gid = grgid->gr_gid; else { ERROR("Gid %s invalid uid or unknown user\n", sgid); goto error; } } switch(type) { case 'b': mode |= S_IFBLK; break; case 'c': mode |= S_IFCHR; break; case 'd': mode |= S_IFDIR; break; case 'f': mode |= S_IFREG; break; } dev = malloc(sizeof(struct pseudo_dev)); if(dev == NULL) BAD_ERROR("Failed to create pseudo_dev\n"); dev->type = type; dev->mode = mode; dev->uid = uid; dev->gid = gid; dev->major = major; dev->minor = minor; if(type == 'f') { int res; printf("Executing dynamic pseudo file\n"); printf("\t\"%s\"\n", def); res = exec_file(def + bytes, dev); if(res == -1) { ERROR("Failed to execute dynamic pseudo file definition" " \"%s\"\n", def); return FALSE; } add_pseudo_file(dev); } *pseudo = add_pseudo(*pseudo, dev, filename, filename); return TRUE; error: ERROR("Bad pseudo file definition \"%s\"\n", def); return FALSE; } int read_pseudo_file(struct pseudo **pseudo, char *filename) { FILE *fd; char line[2048]; int res = TRUE; fd = fopen(filename, "r"); if(fd == NULL) { ERROR("Could not open pseudo device file \"%s\" because %s\n", filename, strerror(errno)); return FALSE; } while(fscanf(fd, "%2047[^\n]\n", line) > 0) { res = read_pseudo_def(pseudo, line); if(res == FALSE) break; }; fclose(fd); return res; } ================================================ FILE: src/others/squashfs-4.0-realtek/pseudo.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.h */ struct pseudo_dev { char type; unsigned int mode; unsigned int uid; unsigned int gid; unsigned int major; unsigned int minor; int pseudo_id; int fd; int child; #ifdef USE_TMP_FILE char *filename; #endif }; struct pseudo_entry { char *name; char *pathname; struct pseudo *pseudo; struct pseudo_dev *dev; }; struct pseudo { int names; int count; struct pseudo_entry *name; }; extern int read_pseudo_def(struct pseudo **, char *); extern int read_pseudo_file(struct pseudo **, char *); extern struct pseudo *pseudo_subdir(char *, struct pseudo *); extern struct pseudo_entry *pseudo_readdir(struct pseudo *); extern struct pseudo_dev *get_pseudo_file(int); extern void delete_pseudo_files(); ================================================ FILE: src/others/squashfs-4.0-realtek/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_destination(int, long long, int, char *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); extern void *create_id(unsigned int); extern unsigned int get_uid(unsigned int); extern unsigned int get_guid(unsigned int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "global.h" #include "compressor.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) static struct compressor *comp; int read_block(int fd, long long start, long long *next, void *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; read_destination(fd, start, 2, (char *)&c_byte); SQUASHFS_INSWAP_SHORTS(&c_byte, 1); if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_destination(fd, start + offset, c_byte, buffer); res = comp->uncompress(block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); return 0; } if(next) *next = start + offset + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_destination(fd, start + offset, c_byte, block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, unsigned int *id_table) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start " "0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx " "containing root inode\n", start); *root_inode_block = bytes; } if(size - bytes < SQUASHFS_METADATA_SIZE) { *inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE); if(*inode_table == NULL) return FALSE; } TRACE("scan_inode_table: reading block 0x%llx\n", start); byte = read_block(fd, start, &start, *inode_table + bytes, sBlk); if(byte == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain * the last directory start block index. This is used when calculating * the total uncompressed directory size. The directory bytes in the * last * block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, (squashfs_base_inode_header *) (*inode_table + bytes)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, (squashfs_dir_inode_header *) (*inode_table + bytes)); directory_start_block = dir_inode->dir.start_block; } else { SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, (squashfs_ldir_inode_header *) (*inode_table + bytes)); directory_start_block = dir_inode->ldir.start_block; } get_uid(id_table[dir_inode->base.uid]); get_guid(id_table[dir_inode->base.guid]); for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { SQUASHFS_SWAP_REG_INODE_HEADER(&inode, (squashfs_reg_inode_header *) cur_ptr); TRACE("scan_inode_table: processing inode @ byte position " "0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); get_uid(id_table[inode.uid]); get_guid(id_table[inode.guid]); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, " "file_size %d, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, (unsigned int *) cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, (squashfs_lreg_inode_header *) cur_ptr); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular " "file, file_size %lld, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, (unsigned int *) cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, (squashfs_symlink_inode_header *) cur_ptr); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, (squashfs_dir_inode_header *) cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, (squashfs_ldir_inode_header *) cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; SQUASHFS_SWAP_DIR_INDEX(&index, (squashfs_dir_index *) cur_ptr); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in " "scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source) { read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); SQUASHFS_INSWAP_SUPER_BLOCK(sBlk); if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) ERROR("Pre 4.0 big-endian filesystem on %s, appending" " to this is unsupported\n", source); else ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 4) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem." " Appending\nto SQUASHFS %d.%d filesystems is " "not supported. Please convert it to a " "SQUASHFS 4 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later " "filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } /* Check the compression type */ comp = lookup_compressor_id(sBlk->compression); if(!comp->supported) { ERROR("Filesystem on %s uses %s compression, this is" "unsupported by this version\n", source, comp->name); display_compressors("", ""); goto failed_mount; } printf("Found a valid %sSQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); printf("\tCompression used %s\n", comp->name); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of ids %d\n", sBlk->no_ids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); printf("\n"); return comp; failed_mount: return NULL; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1)); if(directory_table == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so " "far %d\n", start, bytes); last_start_block = start; byte = read_block(fd, start, &start, directory_table + bytes, sBlk); if(byte == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, (squashfs_dir_header *) (directory_table + bytes)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position " "0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, (squashfs_dir_entry *) (directory_table + bytes)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, " "inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } unsigned int *read_id_table(int fd, squashfs_super_block *sBlk) { int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids); long long index[indexes]; int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids); unsigned int *id_table; int i; id_table = malloc(bytes); if(id_table == NULL) { ERROR("Failed to allocate id table\n"); return NULL; } read_destination(fd, sBlk->id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), (char *) index); SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) id_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read id table block %d, from 0x%llx, length %d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read id table block %d, from 0x%llx, " "length %d\n", i, index[i], length); free(id_table); return NULL; } } SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); for(i = 0; i < sBlk->no_ids; i++) { TRACE("Adding id %d to id tables\n", id_table[i]); create_id(id_table[i]); } return id_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; *fragment_table = malloc(sBlk->fragments * sizeof(squashfs_fragment_entry)); if(*fragment_table == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } read_destination(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == 0) { ERROR("Failed to read fragment table block %d, from " "0x%llx, length %d\n", i, fragment_table_index[i], length); free(*fragment_table); return 0; } } for(i = 0; i < sBlk->fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]); return 1; } int read_inode_lookup_table(int fd, squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; *inode_lookup_table = malloc(lookup_bytes); if(*inode_lookup_table == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } read_destination(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), (char *) index); SQUASHFS_INSWAP_LONG_LONGS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read inode lookup table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read inode lookup table block %d, " "from 0x%llx, length %d\n", i, index[i], length); free(*inode_lookup_table); return 0; } } SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start; long long end = sBlk->directory_table_start; long long root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode); unsigned int root_inode_block, files; squashfs_inode_header inode; unsigned int *id_table; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; id_table = read_id_table(fd, sBlk); if(id_table == NULL) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count, id_table)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry); if(directory_table == NULL) { ERROR("read_filesystem: Could not read root directory" "\n"); goto error; } root_inode_start -= start; *cinode_table = malloc(root_inode_start); if(*cinode_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem inode table\n"); goto error; } read_destination(fd, start, root_inode_start, *cinode_table); *cdirectory_table = malloc(*last_directory_block); if(*cdirectory_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem directory table\n"); goto error; } read_destination(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); *data_cache = malloc(root_inode_offset + *root_inode_size); if(*data_cache == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); *directory_data_cache = malloc(*inode_dir_offset + *inode_dir_file_size); if(*directory_data_cache == NULL) { ERROR("read_filesystem: failed to alloc directory " "cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/read_fs.h ================================================ #ifndef READ_FS_H #define READ_FS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(d, s, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(d, s, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) swap_le64_num(s, d, n) #define SWAP_LE16(d, s, field) swap_le16(&((s)->field), &((d)->field)) #define SWAP_LE32(d, s, field) swap_le32(&((s)->field), &((d)->field)) #define SWAP_LE64(d, s, field) swap_le64(&((s)->field), &((d)->field)) #define SWAP_LES16(d, s, field) swap_le16((unsigned short *) &((s)->field), \ (unsigned short *) &((d)->field)) #else #define SQUASHFS_MEMCPY(d, s, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(d, s, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(d, s, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) \ memcpy(d, s, n * sizeof(long long)) #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino " "%llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is " "supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry"); ERROR(" should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to " "$PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source " "directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory " "test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more " "than one source entry! Please use an absolute path." "\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of " "-32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s" "\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes " "LINK\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-4.0-realtek/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; }; struct inode_info { struct stat buf; struct inode_info *next; squashfs_inode inode; unsigned int inode_number; unsigned int nlink; int pseudo_id; char type; char read; char root_entry; char pseudo_file; }; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/squashfs_compat.h ================================================ #ifndef SQUASHFS_COMPAT #define SQUASHFS_COMPAT /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_compat.h */ /* * definitions for structures on disk - layout 3.x */ #define SQUASHFS_CHECK 2 #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 struct squashfs_super_block_3 { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index_3 { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER_3 \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; } __attribute__ ((packed)); struct squashfs_ipc_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index_3 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_3 { struct squashfs_base_inode_header_3 base; struct squashfs_dev_inode_header_3 dev; struct squashfs_symlink_inode_header_3 symlink; struct squashfs_reg_inode_header_3 reg; struct squashfs_lreg_inode_header_3 lreg; struct squashfs_dir_inode_header_3 dir; struct squashfs_ldir_inode_header_3 ldir; struct squashfs_ipc_inode_header_3 ipc; }; struct squashfs_dir_entry_3 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header_3 { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry_3 { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); typedef struct squashfs_super_block_3 squashfs_super_block_3; typedef struct squashfs_dir_index_3 squashfs_dir_index_3; typedef struct squashfs_base_inode_header_3 squashfs_base_inode_header_3; typedef struct squashfs_ipc_inode_header_3 squashfs_ipc_inode_header_3; typedef struct squashfs_dev_inode_header_3 squashfs_dev_inode_header_3; typedef struct squashfs_symlink_inode_header_3 squashfs_symlink_inode_header_3; typedef struct squashfs_reg_inode_header_3 squashfs_reg_inode_header_3; typedef struct squashfs_lreg_inode_header_3 squashfs_lreg_inode_header_3; typedef struct squashfs_dir_inode_header_3 squashfs_dir_inode_header_3; typedef struct squashfs_ldir_inode_header_3 squashfs_ldir_inode_header_3; typedef struct squashfs_dir_entry_3 squashfs_dir_entry_3; typedef struct squashfs_dir_header_3 squashfs_dir_header_3; typedef struct squashfs_fragment_entry_3 squashfs_fragment_entry_3; typedef union squashfs_inode_header_3 squashfs_inode_header_3; /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block_3));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER_3(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ipc_inode_header_3))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dev_inode_header_3)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_symlink_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_reg_inode_header_3));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_lreg_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ldir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_3));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_3));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_3));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_INODE_T_3(s, d) SQUASHFS_SWAP_LONG_LONGS_3(s, d, 1) #define SQUASHFS_SWAP_SHORTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_FRAGMENT_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_3));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_3(A) ((A) * sizeof(struct squashfs_fragment_entry_3)) #define SQUASHFS_FRAGMENT_INDEX_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_3(A) ((SQUASHFS_FRAGMENT_BYTES_3(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_3(A) (SQUASHFS_FRAGMENT_INDEXES_3(A) *\ sizeof(long long)) /* * definitions for structures on disk - layout 1.x */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; typedef union squashfs_inode_header_1 squashfs_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } /* * definitions for structures on disk - layout 2.x */ struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; typedef union squashfs_inode_header_2 squashfs_inode_header_2; #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS_3(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) ((A) * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif ================================================ FILE: src/others/squashfs-4.0-realtek/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 4 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_IDS 65536 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_MKFLAGS(noi, nod, nof, no_frag, always_frag, \ duplicate_checking, exportable) (noi | (nod << 1) | \ (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6) | (exportable << 7)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 #define SQUASHFS_LSYMLINK_TYPE 10 #define SQUASHFS_LBLKDEV_TYPE 11 #define SQUASHFS_LCHRDEV_TYPE 12 #define SQUASHFS_LFIFO_TYPE 13 #define SQUASHFS_LSOCKET_TYPE 14 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* uid lookup table defines */ #define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int)) #define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ sizeof(long long)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; #define ZLIB_COMPRESSION 1 #define LZMA_COMPRESSION 2 struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time /* time of filesystem creation */; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode_t root_inode; long long bytes_used; long long id_table_start; long long xattr_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; }; struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned int size; unsigned char name[0]; }; #define SQUASHFS_BASE_INODE_HEADER \ unsigned short inode_type; \ unsigned short mode; \ unsigned short uid; \ unsigned short guid; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; }; struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; }; struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int rdev; }; struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int symlink_size; char symlink[0]; }; struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned int block_list[0]; }; struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; long long file_size; long long sparse; unsigned int nlink; unsigned int fragment; unsigned int offset; unsigned int xattr; unsigned int block_list[0]; }; struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int start_block; unsigned int nlink; unsigned short file_size; unsigned short offset; unsigned int parent_inode; }; struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size; unsigned int start_block; unsigned int parent_inode; unsigned short i_count; unsigned short offset; unsigned int xattr; struct squashfs_dir_index index[0]; }; union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned short offset; short inode_number; unsigned short type; unsigned short size; char name[0]; }; struct squashfs_dir_header { unsigned int count; unsigned int start_block; unsigned int inode_number; }; struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; }; #endif ================================================ FILE: src/others/squashfs-4.0-realtek/squashfs_swap.h ================================================ #ifndef SQUASHFS_SWAP_H #define SQUASHFS_SWAP_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_swap.h */ /* * macros to convert each stucture from big endian to little endian */ #if __BYTE_ORDER == __BIG_ENDIAN extern void swap_le16(unsigned short *, unsigned short *); extern void swap_le32(unsigned int *, unsigned int *); extern void swap_le64(long long *, long long *); extern void swap_le16_num(unsigned short *, unsigned short *, int); extern void swap_le32_num(unsigned int *, unsigned int *, int); extern void swap_le64_num(long long *, long long *, int); extern unsigned short inswap_le16(unsigned short); extern unsigned int inswap_le32(unsigned int); extern long long inswap_le64(long long); extern void inswap_le16_num(unsigned short *, int); extern void inswap_le32_num(unsigned int *, int); extern void inswap_le64_num(long long *, int); #define _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, s_magic);\ SWAP_FUNC##32(s, d, inodes);\ SWAP_FUNC##32(s, d, mkfs_time);\ SWAP_FUNC##32(s, d, block_size);\ SWAP_FUNC##32(s, d, fragments);\ SWAP_FUNC##16(s, d, compression);\ SWAP_FUNC##16(s, d, block_log);\ SWAP_FUNC##16(s, d, flags);\ SWAP_FUNC##16(s, d, no_ids);\ SWAP_FUNC##16(s, d, s_major);\ SWAP_FUNC##16(s, d, s_minor);\ SWAP_FUNC##64(s, d, root_inode);\ SWAP_FUNC##64(s, d, bytes_used);\ SWAP_FUNC##64(s, d, id_table_start);\ SWAP_FUNC##64(s, d, xattr_table_start);\ SWAP_FUNC##64(s, d, inode_table_start);\ SWAP_FUNC##64(s, d, directory_table_start);\ SWAP_FUNC##64(s, d, fragment_table_start);\ SWAP_FUNC##64(s, d, lookup_table_start);\ } #define _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, index);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, size);\ } #define _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ } #define _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ } #define _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, rdev);\ } #define _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, symlink_size);\ } #define _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, fragment);\ SWAP_FUNC##32(s, d, offset);\ SWAP_FUNC##32(s, d, file_size);\ } #define _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##64(s, d, start_block);\ SWAP_FUNC##64(s, d, file_size);\ SWAP_FUNC##64(s, d, sparse);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, fragment);\ SWAP_FUNC##32(s, d, offset);\ SWAP_FUNC##32(s, d, xattr);\ } #define _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##16(s, d, file_size);\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##32(s, d, parent_inode);\ } #define _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, inode_type);\ SWAP_FUNC##16(s, d, mode);\ SWAP_FUNC##16(s, d, uid);\ SWAP_FUNC##16(s, d, guid);\ SWAP_FUNC##32(s, d, mtime);\ SWAP_FUNC##32(s, d, inode_number);\ SWAP_FUNC##32(s, d, nlink);\ SWAP_FUNC##32(s, d, file_size);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, parent_inode);\ SWAP_FUNC##16(s, d, i_count);\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##32(s, d, xattr);\ } #define _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC##16(s, d, offset);\ SWAP_FUNC##S16(s, d, inode_number);\ SWAP_FUNC##16(s, d, type);\ SWAP_FUNC##16(s, d, size);\ } #define _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC##32(s, d, count);\ SWAP_FUNC##32(s, d, start_block);\ SWAP_FUNC##32(s, d, inode_number);\ } #define _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC##64(s, d, start_block);\ SWAP_FUNC##32(s, d, size);\ } #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_LE) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_INSWAP_SUPER_BLOCK(s) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INDEX(s) \ _SQUASHFS_SWAP_DIR_INDEX(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_ENTRY(s) \ _SQUASHFS_SWAP_DIR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_HEADER(s) \ _SQUASHFS_SWAP_DIR_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, s, INSWAP_LE) #define INSWAP_LE16(s, d, field) (s)->field = inswap_le16((s)->field) #define INSWAP_LE32(s, d, field) (s)->field = inswap_le32((s)->field) #define INSWAP_LE64(s, d, field) (s)->field = inswap_le64((s)->field) #define INSWAP_LES16(s, d, field) \ (s)->field = (short) inswap_le16((unsigned short) (s)->field) #define SQUASHFS_INSWAP_INODE_T(s) s = inswap_le64(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) inswap_le16_num(s, n) #define SQUASHFS_INSWAP_INTS(s, n) inswap_le32_num(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) inswap_le64_num(s, n) #else #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_INSWAP_SUPER_BLOCK(s) #define SQUASHFS_INSWAP_DIR_INDEX(s) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_ENTRY(s) #define SQUASHFS_INSWAP_DIR_HEADER(s) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) #define SQUASHFS_INSWAP_INODE_T(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) #define SQUASHFS_INSWAP_INTS(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) #endif #endif ================================================ FILE: src/others/squashfs-4.0-realtek/swap.c ================================================ /* * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * swap.c */ #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #if __BYTE_ORDER == __BIG_ENDIAN void swap_le16(unsigned short *src, unsigned short *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[1]; d[1] = s[0]; } void swap_le32(unsigned int *src, unsigned int *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } void swap_le64(long long *src, long long *dest) { unsigned char *s = (unsigned char *) src; unsigned char *d = (unsigned char *) dest; d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; d[3] = s[4]; d[4] = s[3]; d[5] = s[2]; d[6] = s[1]; d[7] = s[0]; } unsigned short inswap_le16(unsigned short num) { return (num >> 8) | ((num & 0xff) << 8); } unsigned int inswap_le32(unsigned int num) { return (num >> 24) | ((num & 0xff0000) >> 8) | ((num & 0xff00) << 8) | ((num & 0xff) << 24); } long long inswap_le64(long long n) { unsigned long long num = n; return (num >> 56) | ((num & 0xff000000000000LL) >> 40) | ((num & 0xff0000000000LL) >> 24) | ((num & 0xff00000000LL) >> 8) | ((num & 0xff000000) << 8) | ((num & 0xff0000) << 24) | ((num & 0xff00) << 40) | ((num & 0xff) << 56); } #define SWAP_LE_NUM(BITS, TYPE) \ void swap_le##BITS##_num(TYPE *s, TYPE *d, int n) \ {\ int i;\ for(i = 0; i < n; i++, s++, d++)\ swap_le##BITS(s, d);\ } SWAP_LE_NUM(16, unsigned short) SWAP_LE_NUM(32, unsigned int) SWAP_LE_NUM(64, long long) #define INSWAP_LE_NUM(BITS, TYPE) \ void inswap_le##BITS##_num(TYPE *s, int n) \ {\ int i;\ for(i = 0; i < n; i++)\ s[i] = inswap_le##BITS(s[i]);\ } INSWAP_LE_NUM(16, unsigned short) INSWAP_LE_NUM(32, unsigned int) INSWAP_LE_NUM(64, long long) #endif ================================================ FILE: src/others/squashfs-4.0-realtek/unsquash-1.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-1.c */ #include "unsquashfs.h" #include "squashfs_compat.h" void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; TRACE("read_block_list: blocks %d\n", blocks); for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS_3((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } int read_fragment_table_1() { TRACE("read_fragment_table\n"); return TRUE; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_1 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; i.sparse = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: ERROR("Unknown inode type %d in read_inode_header_1!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_1(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(((*i) = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_1() { int res; TRACE("read_uids_guids: no_uids %d, no_guids %d\n", sBlk.no_uids, sBlk.no_guids); uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int)); if(uid_table == NULL) { ERROR("read_uids_guids: failed to allocate uid/gid table\n"); return FALSE; } guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; res = read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) suid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } SQUASHFS_SWAP_INTS_3(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else { res = read_bytes(sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), (char *) uid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } } return TRUE; } ================================================ FILE: src/others/squashfs-4.0-realtek/unsquash-2.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-2.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_2 *fragment_table; void read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) { TRACE("read_block_list: blocks %d\n", blocks); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } int read_fragment_table_2() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return TRUE; fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry_2)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else { res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } return TRUE; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_2 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode_header_2!\n", header.base.inode_type); return NULL; } return &i; } ================================================ FILE: src/others/squashfs-4.0-realtek/unsquash-3.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-3.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_3 *fragment_table; int read_fragment_table_3() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return TRUE; if((fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry_3))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.fragments), (char *) sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index, sfragment_table_index, indexes); } else { res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_3 sfragment; for(i = 0; i < sBlk.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_3)); } } return TRUE; } void read_fragment_3(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_3 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_3(unsigned int start_block, unsigned int offset) { static squashfs_inode_header_3 header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } if(swap) { squashfs_base_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_3(&header.base, &sinode, sizeof(squashfs_base_inode_header_3)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_3 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_3(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_3 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_3(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_3 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header_3 *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_3 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_3), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_3 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_3(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_3 dirh; char buffer[sizeof(squashfs_dir_entry_3) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry_3 *dire = (squashfs_dir_entry_3 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_3 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_3(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_3 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_3(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } ================================================ FILE: src/others/squashfs-4.0-realtek/unsquash-4.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-4.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "read_fs.h" static struct squashfs_fragment_entry *fragment_table; static unsigned int *id_table; int read_fragment_table_4() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.fragments, indexes, sBlk.fragment_table_start); if(sBlk.fragments == 0) return TRUE; if((fragment_table = malloc(sBlk.fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); res = read_bytes(sBlk.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.fragments), (char *) fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment table " "index\n"); return FALSE; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < sBlk.fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]); return TRUE; } void read_fragment_4(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_4(unsigned int start_block, unsigned int offset) { static squashfs_inode_header header; long long start = sBlk.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) { ERROR("read_inode: inode table block %lld not found\n", start); return NULL; } SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, (squashfs_base_inode_header *) block_ptr); i.uid = (uid_t) id_table[header.base.uid]; i.gid = (uid_t) id_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header *inode = &header.dir; SQUASHFS_SWAP_DIR_INODE_HEADER(inode, (squashfs_dir_inode_header *) block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header *inode = &header.ldir; SQUASHFS_SWAP_LDIR_INODE_HEADER(inode, (squashfs_ldir_inode_header *) block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header *inode = &header.reg; SQUASHFS_SWAP_REG_INODE_HEADER(inode, (squashfs_reg_inode_header *) block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header *inode = &header.lreg; SQUASHFS_SWAP_LREG_INODE_HEADER(inode, (squashfs_lreg_inode_header *) block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.block_size - 1) >> sBlk.block_log : inode->file_size >> sBlk.block_log; i.start = inode->start_block; i.sparse = inode->sparse != 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { squashfs_symlink_inode_header *inode = &header.symlink; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inode, (squashfs_symlink_inode_header *) block_ptr); i.symlink = malloc(inode->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header), inode->symlink_size); i.symlink[inode->symlink_size] = '\0'; i.data = inode->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { squashfs_dev_inode_header *inode = &header.dev; SQUASHFS_SWAP_DEV_INODE_HEADER(inode, (squashfs_dev_inode_header *) block_ptr); i.data = inode->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: case SQUASHFS_LFIFO_TYPE: case SQUASHFS_LSOCKET_TYPE: i.data = 0; break; default: ERROR("Unknown inode type %d in read_inode!\n", header.base.inode_type); return NULL; } return &i; } struct dir *squashfs_opendir_4(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if((*i = s_ops.read_inode(block_start, offset)) == NULL) { ERROR("squashfs_opendir: failed to read directory inode %d\n", block_start); return NULL; } start = sBlk.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += (*i)->offset; size = (*i)->data + bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->dirs = NULL; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, (squashfs_dir_header *) (directory_table + bytes)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, (squashfs_dir_entry *) (directory_table + bytes)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) { ERROR("squashfs_opendir: realloc " "failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_4() { int res, i, indexes = SQUASHFS_ID_BLOCKS(sBlk.no_ids); long long id_index_table[indexes]; TRACE("read_uids_guids: no_ids %d\n", sBlk.no_ids); id_table = malloc(SQUASHFS_ID_BYTES(sBlk.no_ids)); if(id_table == NULL) { ERROR("read_uids_guids: failed to allocate id table\n"); return FALSE; } res = read_bytes(sBlk.id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk.no_ids), (char *) id_index_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read id index table\n"); return FALSE; } SQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes); for(i = 0; i < indexes; i++) { res = read_block(id_index_table[i], NULL, ((char *) id_table) + i * SQUASHFS_METADATA_SIZE); if(res == FALSE) { ERROR("read_uids_guids: failed to read id table block" "\n"); return FALSE; } } SQUASHFS_INSWAP_INTS(id_table, sBlk.no_ids); return TRUE; } ================================================ FILE: src/others/squashfs-4.0-realtek/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "squashfs_compat.h" #include "read_fs.h" #include "compressor.h" #include <sys/sysinfo.h> struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; struct super_block sBlk; squashfs_operations s_ops; struct compressor *comp; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; int use_regex = FALSE; char **created_inode; int root_process; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int inode_number = 1; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) return NULL; if((queue->data = malloc(sizeof(void *) * (size + 1))) == NULL) { free(queue); return NULL; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) return NULL; cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* * Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for * reading off disk and decompression. The cache grows until max_blocks * is reached, once this occurs existing discarded blocks on the free * list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* *found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* * not in the cache * * first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) goto failed; entry->data = malloc(cache->buffer_size); if(entry->data == NULL) { free(entry); goto failed; } entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* * try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* * initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* * queue to read thread to read and ultimately (via the * decompress threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; failed: pthread_mutex_unlock(&cache->mutex); return NULL; } void cache_block_ready(struct cache_entry *entry, int error) { /* * mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* * if the wait_pending flag is set, one or more threads may be waiting * on this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* * wait for this cache entry to become ready, when reading and (if * necessary) decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* * finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains * accessible via the hash table it can be found getting a new lease of * life before it is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* * if the wait_free flag is set, one or more threads may be * waiting on this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } if((user = getpwuid(inode->uid)) == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; if((group = getgrgid(inode->gid)) == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } int add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], long long start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; int res, count; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) { ERROR("Read on filesystem failed because EOF\n"); return FALSE; } else if(errno != EINTR) { ERROR("Read on filesystem failed because %s\n", strerror(errno)); return FALSE; } else res = 0; } } return TRUE; } int read_block(long long start, long long *next, char *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; res = comp->uncompress(block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } if(next) *next = start + offset + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: ERROR("read_block: failed to read block @0x%llx\n", start); return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int error, res; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) goto failed; res = comp->uncompress(block, data, c_byte, block_size, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } return res; } else { if(read_bytes(start, c_byte, block) == FALSE) goto failed; return c_byte; } failed: ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, c_byte); return FALSE; } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory " "in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); res = read_block(start, &start, inode_table + bytes); if(res == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read " "block \n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int set_mode) { struct utimbuf times = { time, time }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids " "on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } int write_bytes(int fd, char *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write on output file failed because " "%s\n", strerror(errno)); return -1; } res = 0; } } return 0; } int lseek_broken = FALSE; char *zero_data = NULL; int write_block(int file_fd, char *buffer, int size, int hole, int sparse) { off_t off = hole; if(hole) { if(sparse && lseek_broken == FALSE) { int error = lseek(file_fd, off, SEEK_CUR); if(error == -1) /* failed to seek beyond end of file */ lseek_broken = TRUE; } if((sparse == FALSE || lseek_broken) && zero_data == NULL) { if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc " "zero data block\n"); memset(zero_data, 0, block_size); } if(sparse == FALSE || lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write_bytes(file_fd, zero_data, avail_bytes) == -1) goto failure; } } } if(write_bytes(file_fd, buffer, size) == -1) goto failure; return TRUE; failure: return FALSE; } int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); if(file_fd == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } if((block_list = malloc(inode->blocks * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); if((file = malloc(sizeof(struct squashfs_file))) == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* * the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are * queued separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); file->sparse = inode->sparse; queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); if(block->buffer == NULL) EXIT_UNSQUASH("write_file: cache_get failed\n"); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, " "because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, " "blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink " "%s, because %s\n", pathname, strerror(errno)); break; } if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change " "uid and gids on %s, because " "%s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create " "%s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s " "device %s, because you're not " "superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, " "because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of " "memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); res = read_block(start, &start, directory_table + bytes); if(res == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to " "read block\n"); bytes += res; } } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { if((paths = malloc(sizeof(struct pathname))) == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* * allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* * at leaf pathname component */ paths->name[i].paths = NULL; else /* * recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* * existing matching entry */ if(paths->name[i].paths == NULL) { /* * No sub-directory which means this is the leaf * component of a pre-existing extract which subsumes * the extract currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* * at leaf pathname component and child components exist * from more specific extracts, delete as they're * subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* * recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* * match on a leaf component, any subdirectories * will implicitly match, therefore return an * empty new search set */ goto empty_set; if(match) /* * match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* * no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* * one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* * found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } int pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("pre_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); return TRUE; } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { if((i = s_ops.read_inode(start_block, offset)) == NULL) { ERROR("failed to read header\n"); continue; } if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } if(i->type == SQUASHFS_SYMLINK_TYPE || i->type == SQUASHFS_LSYMLINK_TYPE) free(i->symlink); } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, force); squashfs_closedir(dir); dir_count ++; return TRUE; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s_major == 4 ? "" : swap ? "little endian " : "big endian ", sBlk.s_major, sBlk.s_minor, source); #else printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s_major == 4 ? "" : swap ? "big endian " : "little endian ", sBlk.s_major, sBlk.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); if(sBlk.s_major == 4) printf("Compression %s\n", comp->name); printf("Block size %d\n", sBlk.block_size); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags) ? "un" : ""); if(sBlk.s_major > 1 && !SQUASHFS_NO_FRAGMENTS(sBlk.flags)) printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags) ? "un" : ""); printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.flags) ? "" : "not "); if(sBlk.s_major > 1) { printf("Fragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk.flags) ? "not " : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags) ? "" : "not "); } else printf("Fragments are not supported by the filesystem\n"); if(sBlk.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); else printf("Duplicates are removed\n"); if(sBlk.s_major > 1) printf("Number of fragments %d\n", sBlk.fragments); printf("Number of inodes %d\n", sBlk.inodes); if(sBlk.s_major == 4) printf("Number of ids %d\n", sBlk.no_ids); else { printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); } TRACE("sBlk.inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk.directory_table_start 0x%llx\n", sBlk.directory_table_start); if(sBlk.s_major == 4) TRACE("sBlk.id_table_start 0x%llx\n", sBlk.id_table_start); else { TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); } if(sBlk.s_major > 1) TRACE("sBlk.fragment_table_start 0x%llx\n\n", sBlk.fragment_table_start); } int read_super(char *source) { squashfs_super_block_3 sBlk_3; squashfs_super_block sBlk_4; /* * Try to read a Squashfs 4 superblock */ read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_4); swap = sBlk_4.s_magic != SQUASHFS_MAGIC; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && sBlk_4.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir_4; s_ops.read_fragment = read_fragment_4; s_ops.read_fragment_table = read_fragment_table_4; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_4; s_ops.read_uids_guids = read_uids_guids_4; memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); /* * Check the compression type */ comp = lookup_compressor_id(sBlk.compression); if(!comp->supported) { ERROR("Filesystem uses %s compression, this is " "unsupported by this version\n", comp->name); ERROR("Decompressors available:\n"); display_compressors("", ""); goto failed_mount; } return TRUE; } /* * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock * (compatible with 1 and 2 filesystems) */ read_bytes(SQUASHFS_START, sizeof(squashfs_super_block_3), (char *) &sBlk_3); /* * Check it is a SQUASHFS superblock */ swap = 0; if(sBlk_3.s_magic != SQUASHFS_MAGIC) { if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block_3 sblk; ERROR("Reading a different endian SQUASHFS filesystem " "on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } sBlk.s_magic = sBlk_3.s_magic; sBlk.inodes = sBlk_3.inodes; sBlk.mkfs_time = sBlk_3.mkfs_time; sBlk.block_size = sBlk_3.block_size; sBlk.fragments = sBlk_3.fragments; sBlk.block_log = sBlk_3.block_log; sBlk.flags = sBlk_3.flags; sBlk.s_major = sBlk_3.s_major; sBlk.s_minor = sBlk_3.s_minor; sBlk.root_inode = sBlk_3.root_inode; sBlk.bytes_used = sBlk_3.bytes_used; sBlk.inode_table_start = sBlk_3.inode_table_start; sBlk.directory_table_start = sBlk_3.directory_table_start; sBlk.fragment_table_start = sBlk_3.fragment_table_start; sBlk.lookup_table_start = sBlk_3.lookup_table_start; sBlk.no_uids = sBlk_3.no_uids; sBlk.no_guids = sBlk_3.no_guids; sBlk.uid_start = sBlk_3.uid_start; sBlk.guid_start = sBlk_3.guid_start; /* Check the MAJOR & MINOR versions */ if(sBlk.s_major == 1 || sBlk.s_major == 2) { sBlk.bytes_used = sBlk_3.bytes_used_2; sBlk.uid_start = sBlk_3.uid_start_2; sBlk.guid_start = sBlk_3.guid_start_2; sBlk.inode_table_start = sBlk_3.inode_table_start_2; sBlk.directory_table_start = sBlk_3.directory_table_start_2; if(sBlk.s_major == 1) { sBlk.block_size = sBlk_3.block_size_1; sBlk.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; s_ops.read_uids_guids = read_uids_guids_1; } else { sBlk.fragment_table_start = sBlk_3.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_2; s_ops.read_uids_guids = read_uids_guids_1; } } else if(sBlk.s_major == 3) { s_ops.squashfs_opendir = squashfs_opendir_3; s_ops.read_fragment = read_fragment_3; s_ops.read_fragment_table = read_fragment_table_3; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_3; s_ops.read_uids_guids = read_uids_guids_1; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s_major, sBlk.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } /* * 1.x, 2.x and 3.x filesystems use gzip compression. Gzip is always * suppported. */ comp = lookup_compressor("gzip"); return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; if((fd = fopen(filename, "r")) == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* * reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_bytes(entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* * queue successfully read block to the deflate * thread(s) for further processing */ queue_put(to_deflate, entry); else /* * block has either been successfully read and is * uncompressed, or an error has occurred, clear pending * flag, set error appropriately, and wake up any * threads waiting on this buffer */ cache_block_ready(entry, !res); } } /* * writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; int hole = 0; int failed = FALSE; int error; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed) continue; error = write_block(file_fd, block->buffer->data + block->offset, block->size, hole, file->sparse); if(error == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* * corner case for hole extending to end of file */ if(file->sparse == FALSE || lseek(file_fd, hole, SEEK_CUR) == -1) { /* * for files which we don't want to write * sparsely, or for broken lseeks which cannot * seek beyond end of file, write_block will do * the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole, file->sparse) == FALSE) { ERROR("writer: failed to write sparse " "data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data " "block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* * decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; while(1) { struct cache_entry *entry = queue_get(to_deflate); int error, res; res = comp->uncompress(tmp, entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, &error); if(res == -1) ERROR("%s uncompress failed with error code %d\n", comp->name, error); else memcpy(entry->data, tmp, res); /* * block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res == -1); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = get_nprocs(); #endif } if((thread = malloc((3 + processors) * sizeof(pthread_t))) == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits = floor(log10(max)) + 1; int used = max_digits * 2 + 11; int hashes = (current * (columns - used)) / max; int spaces = columns - used - hashes; static int tty = -1; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 4.1-CVS (2009/08/30)\n");\ printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\ "\n\n");\ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,"\ "\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,"\ "\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ "\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(lsonly || info) progress = FALSE; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or " "files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and " "copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " "default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress " "bar\n"); ERROR("\t-p[rocessors] <number>\tuse <number> " "processors. By default will use\n"); ERROR("\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are " "unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are " "unsquashed with file\n"); ERROR("\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" "\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file " "attributes (like\n"); ERROR("\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then " "overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " "information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or " "files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to " "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to " "<size> Mbytes. Default %d\n\t\t\t\t Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX " "regular expressions\n"); ERROR("\t\t\t\trather than use the default shell " "wildcard\n\t\t\t\texpansion (globbing)\n"); ERROR("\nDecompressors available:\n"); display_compressors("", ""); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } block_size = sBlk.block_size; block_log = sBlk.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate data\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); if(s_ops.read_uids_guids() == FALSE) EXIT_UNSQUASH("failed to uid/gid table\n"); if(s_ops.read_fragment_table() == FALSE) EXIT_UNSQUASH("failed to read fragment table\n"); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); inode_number = 1; printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-4.0-realtek/unsquashfs.h ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.h */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "global.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) /* * Unified superblock containing fields for all superblocks */ struct super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode_t root_inode; long long bytes_used; long long id_table_start; long long xattr_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; /* fields only used by squashfs 3 and earlier layouts */ unsigned int no_uids; unsigned int no_guids; long long uid_start; long long guid_start; }; struct hash_table_entry { long long start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char *symlink; time_t time; int type; uid_t uid; char sparse; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); int (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); int (*read_uids_guids)(); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; struct dir_ent *dirs; }; struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; char sparse; }; struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 /* globals */ extern struct super_block sBlk; extern squashfs_operations s_ops; extern int swap; extern char *inode_table, *directory_table; extern struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; extern unsigned int *uid_table, *guid_table; extern pthread_mutex_t screen_mutex; extern int progress_enabled; extern int inode_number; extern int lookup_type[]; /* unsquashfs.c */ extern int lookup_entry(struct hash_table_entry **, long long); extern int read_bytes(long long, int, char *); extern int read_block(long long, long long *, char *); /* unsquash-1.c */ extern void read_block_list_1(unsigned int *, char *, int); extern int read_fragment_table_1(); extern struct inode *read_inode_1(unsigned int, unsigned int); extern struct dir *squashfs_opendir_1(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_1(); /* unsquash-2.c */ extern void read_block_list_2(unsigned int *, char *, int); extern int read_fragment_table_2(); extern void read_fragment_2(unsigned int, long long *, int *); extern struct inode *read_inode_2(unsigned int, unsigned int); /* unsquash-3.c */ extern int read_fragment_table_3(); extern void read_fragment_3(unsigned int, long long *, int *); extern struct inode *read_inode_3(unsigned int, unsigned int); extern struct dir *squashfs_opendir_3(unsigned int, unsigned int, struct inode **); /* unsquash-4.c */ extern int read_fragment_table_4(); extern void read_fragment_4(unsigned int, long long *, int *); extern struct inode *read_inode_4(unsigned int, unsigned int); extern struct dir *squashfs_opendir_4(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_4(); ================================================ FILE: src/others/squashfs-4.2/ACKNOWLEDGEMENTS ================================================ ACKNOWLEDGEMENTS Thanks to everyone who have download squashfs. I appreciate people using it, and any feedback you have. The following have provided useful feedback, which has guided some of the extra features in squashfs. This is a randomly ordered (roughly in chronological order) list, which is updated when I remember... Acknowledgements for Squashfs 4.2 --------------------------------- Thanks to Lasse Collin (http://tukaani.org/xz/) for mainlining XZ decompression support. Acknowledgements for Squashfs 4.1 --------------------------------- Thanks to Chan Jeong <chan.jeong@lge.com> and LG for the patches to support LZO compression. Acknowledgements for Squashfs 4.0 --------------------------------- Thanks to Tim Bird and CELF (Consumer Electronics Linux Forum) for helping fund mainstreaming of Squashfs into the 2.6.29 kernel and the changes to the Squashfs tools to support the new 4.0 file system layout. Acknowledgements for Squashfs-3.3 ------------------------------------ Peter Korsgaard and others sent patches updating Squashfs to changes in the VFS interface for 2.6.22/2.6.23/2.6.24-rc1. Peter also sent some small patches for the Squashfs kernel code. Vito Di Leo sent a patch extending Mksquashfs to support regex filters. While his patched worked, it unfortunately made it easy to make Mksquashfs perform unpredictably with poorly choosen regex expressions. It, however, encouraged myself to add support for wildcard pattern matching and regex filters in a different way. Acknowledgements for Squashfs-3.2-r2 ------------------------------------ Junjiro Okajima discovered a couple of SMP issues, thanks. Junjiro Okajima and Tomas Matejicek have produced some good LZMA patches for Squashfs. Acknowledgements for Squashfs-3.2 --------------------------------- Peter Korsgaard sent a patch updating Squashfs to changes in the VFS interface in Linux 2.6.20. Acknowledgements for Squashfs-3.1 --------------------------------- Kenneth Duda and Ed Swierk of Arastra Inc. identified numerous bugs with Squashfs, and provided patches which were the basis for some of the fixes. In particular they identified the fragment rounding bug, the NFS bug, the initrd bug, and helped identify the 4K stack overflow bug. Scott James Remnant (Ubuntu) also identified the fragment rounding bug, and he also provided a patch. Ming Zhang identified the Lseek bug in Mksquashfs. His tests on the performance of Mksquashfs on SMP systems encouraged the rewrite of Mksquashfs. Peter Korsgaard, Daniel Olivera and Zilvinas Valinskas noticed Squashfs 3.0 didn't compile on Linux-2.6.18-rc[1-4] due to changes in the Linux VFS interfaces, and provided patches. Tomas Matejicek (SLAX) suggested the -force option on Unsquashfs, and noticed Unsquashfs didn't return the correct exit status. Yann Le Doare reported a kernel oops and provided a Qemu image that led to the identification of the simultaneously accessing multiply mounted Squashfs filesystems bug. Older acknowledgements ---------------------- Mark Robson - pointed out early on that initrds didn't work Adam Warner - pointed out that greater than 2GB filesystems didn't work. John Sutton - raised the problem when archiving the entire filesystem (/) there was no way to prevent /proc being archived. This prompted exclude files. Martin Mueller (LinuxTV) - noticed that the filesystem length in the superblock doesn't match the output filesystem length. This is due to padding to a 4K boundary. This prompted the addition of the -nopad option. He also reported a problem where 32K block filesystems hung when used as initrds. Arkadiusz Patyk (Polish Linux Distribution - PLD) reported a problem where 32K block filesystems hung when used as a root filesystem mounted as a loopback device. Joe Blow emailed me that I'd forgotten to put anything in the README about mounting the squashfs filesystem. David Fox (Lindows) noticed that the exit codes returned by Mksquashfs were wrong. He also noticed that a lot of time was spent in the duplicate scan routine. Cameron Rich complained that Squashfs did not support FIFOs or sockets. Steve Chadsey and Thomas Weissmuller noticed that files larger than the available memory could not be compressed by Mksquashfs. "Ptwahyu" and "Hoan" (I have no full names and I don't like giving people's email addresses), noticed that Mksquashfs 1.3 SEGV'd occasionally. Even though I had already noticed this bug, it is useful to be informed by other people. Don Elwell, Murray Jensen and Cameron Rich, have all sent in patches. Thanks, I have not had time to do anything about them yet... Drew Scott Daniels has been a good advocate for Squashfs. Erik Andersen has made some nice suggestions, unfortunately, I have not had time to implement anything. Artemiy I. Pavlov has written a useful LDP mini-howto for Squashfs (http://linuxdoc.artemio.net/squashfs). Yves Combe reported the Apple G5 bug, when using Squashfs for his PPC Knoppix-mib livecd project. Jaco Greeff (mklivecd project, and maintainer of the Mandrake squashfs-tools package) suggested the new mksquashfs -ef option, and the standalone build for mksquashfs. Mike Schaudies made a donation. Arkadiusz Patyk from the Polish Linux Distribution reported that Squashfs didn't work on amd64 machines. He gave me an account on a PLD amd64 machine which allowed myself to track down these bugs. Miles Roper, Peter Kjellerstedt and Willy Tarreau reported that release 2.1 did not compile with gcc < 3.x. Marcel J.E. Mol reported lack of kernel memory issues when using Squashfs on small memory embedded systems. This prompted the addition of the embedded system kernel configuration options. Era Scarecrow noticed that Mksquashfs had not been updated to reflect that smaller than 4K blocks are no longer supported. Kenichi Shima reported the Kconfig file had not been updated to 2.2. Aaron Ten Clay made a donation! Tomas Matejicek (SLAX) made a donation! ================================================ FILE: src/others/squashfs-4.2/CHANGES ================================================ SQUASHFS CHANGE LOG 4.2 28 FEB 2011 XZ compression, and compression options support 1. Filesystem improvements: 1.1 Added XZ compression 1.2 Added compression options support 2. Miscellaneous improvements/bug fixes 1.1 Add missing NO_XATTR filesystem flag to indicate no-xattrs option was specified and no xattrs should be stored when appending. 1.2 Add suppport in Unquashfs -stat option for displaying NO_XATTR flag. 1.3 Remove checkdata entry from Unsquashfs -stat option if a 4.0 filesystem - checkdata is no longer supported. 1.4 Fix appending bug when appending to an empty filesystem - this would be incorrectly treated as an error. 1.5 Use glibc sys/xattr.h include rather than using attr/xattr.h which isn't present by default on some distributions. 1.6 Unsquashfs, fix block calculation error with regular files when file size is between 2^32-block_size+1 and 2^32-1. 1.7 Unsquashfs, fix sparse file writing when holes are larger than 2^31-1. 1.8 Add external CFLAGS and LDFLAGS support to Makefile, and allow build options to be specified on command line. Also don't over-write passed in CFLAGS definition. 4.1 19 SEPT 2010 Major filesystem and tools improvements 1. Filesystem improvements: 1.1 Extended attribute support 1.2 New compression framework 1.3 Support for LZO compression 1.4 Support for LZMA compression (not yet in mainline) 2. Mksquashfs improvements: 1.1 Enhanced pseudo file support 1.2 New options for choosing compression algorithm used 1.3 New options for controlling extended attributes 1.4 Fix misalignment issues with memcpy etc. seen on ARM 1.5 Fix floating point error in progress_bar when max == 0 1.6 Removed use of get_nproc() call unavailable in ulibc 1.7 Reorganised help text 3. Unsquashfs improvements: 1.1 New options for controlling extended attributes 1.2 Fix misalignment issues with memcpy etc. seen on ARM 1.3 Fix floating point error in progress_bar when max == 0 1.4 Removed use of get_nproc() call unavailable in ulibc 4.0 5 APR 2009 Major filesystems improvements 1. Kernel code improvements: 1.1 Fixed little endian layout adopted. All swapping macros removed, and in-line swapping added for big-endian architectures. 1.2 Kernel code substantially improved and restructured. 1.3 Kernel code split into separate files along functional lines. 1.4 Vmalloc usage removed, and code changed to use separately allocated 4K buffers 2. Unsquashfs improvements: 2.1 Support for 4.0 filesystems added. 2.2 Swapping macros rewritten. 2.3 Unsquashfs code restructured and split into separate files. 3. Mksquashfs improvements: 3.1 Swapping macros rewritten. Fixed little-endian layout allows code to be optimised and only added at compile time for big endian systems. 3.2 Support for pseudo files added. 3.4 26 AUG 2008 Performance improvements to Unsquashfs, Mksquashfs and the kernel code. Plus many small bug fixes. 1. Kernel code improvements: 1.1 Internal Squashfs kernel metadata and fragment cache implementations have been merged and optimised. Spinlocks are now used, locks are held for smaller periods and wakeups have been minimised. Small race condition fixed where if two or more processes tried to read the same cache block simultaneously they would both read and decompress it. 10-20%+ speed improvement has been seen on tests. 1.2 NFS export code rewritten following VFS changes in linux-2.6.24. 1.3 New patches for linux-2.6.25, linux-2.6.26, and linux-2.6.27. Fixed patch for linux-2.6.24. 1.4 Fixed small buffer_head leak in squashfs_read_data when handling badly corrupted filesystems. 1.5 Fixed bug in get_dir_index_using_offset. 2. Unsquashfs improvements: 2.1 Unsquashfs has been parallelised. Filesystem reading, writing and decompression is now multi-threaded. Up to 40% speed improvement seen on tests. 2.2 Unsquashfs now has a progress bar. Use -no-progress to disable it. 2.3 Fixed small bug where unistd.h wasn't being included on some distributions, leading to lseek being used rather than lseek64 - which meant on these distributions Unsquashfs couldn't unsquash filesystems larger than 4GB. 3. Mksquashfs improvements: 3.1 Removed some small remaining parallelisation bottlenecks. Depending on source filesystem, up to 10%+ speed improvement. 3.2 Progress bar improved, and moved to separate thread. 3.3 Sparse file handling bug in Mksquashfs 3.3 fixed. 3.4 Two rare appending restore bugs fixed (when ^C hit twice). 3.3 1 NOV 2007 Increase in block size, sparse file support, Mksquashfs and Unsquashfs extended to use pattern matching in exclude/extract files, plus many more improvements and bug fixes. 1. Filesystem improvements: 1.1. Maximum block size has been increased to 1Mbyte, and the default block size has been increased to 128 Kbytes. This improves compression. 1.2. Sparse files are now supported. Sparse files are files which have large areas of unallocated data commonly called holes. These files are now detected by Squashfs and stored more efficiently. This improves compression and read performance for sparse files. 2. Mksquashfs improvements: 2.1. Exclude files have been extended to use wildcard pattern matching and regular expressions. Support has also been added for non-anchored excludes, which means it is now possible to specify excludes which match anywhere in the filesystem (i.e. leaf files), rather than always having to specify exclude files starting from the root directory (anchored excludes). 2.2. Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). 3. Unsquashfs improvements: 3.1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. 3.2. Extract files have been extended to use wildcard pattern matching and regular expressions. 3.3. Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). 3.4. A -stat option has been added which displays the filesystem superblock information. 3.5. Unsquashfs now supports 1.x filesystems. 4. Miscellaneous improvements/bug fixes: 4.1. Squashfs kernel code improved to use SetPageError in squashfs_readpage() if I/O error occurs. 4.2. Fixed Squashfs kernel code bug preventing file seeking beyond 2GB. 4.3. Mksquashfs now detects file size changes between first phase directory scan and second phase filesystem create. It also deals better with file I/O errors. 3.2-r2 15 JAN 2007 Kernel patch update and progress bar bug fix 1. Kernel patches 2.6.19/2.6.20 have been updated to use const structures and mutexes rather than older semaphores. 2. Minor SMP bug fixes. 3. Progress bar broken on x86-64. Fixed. 3.2 2 JAN 2007 NFS support, improvements to the Squashfs-tools, major bug fixes, lots of small improvements/bug fixes, and new kernel patches. Improvements: 1. Squashfs filesystems can now be exported via NFS. 2. Unsquashfs now supports 2.x filesystems. 3. Mksquashfs now displays a progress bar. 4. Squashfs kernel code has been hardened against accidently or maliciously corrupted Squashfs filesystems. Bug fixes: 5. Race condition occurring on S390 in readpage() fixed. 6. Odd behaviour of MIPS memcpy in read_data() routine worked-around. 7. Missing cache_flush in Squashfs symlink_readpage() added. 3.1-r2 30 AUG 2006 Mksquashfs -sort bug fix A code optimisation after testing unfortunately broke sorting in Mksquashfs. This has been fixed. 3.1 19 AUG 2006 This release has some major improvements to the squashfs-tools, a couple of major bug fixes, lots of small improvements/bug fixes, and new kernel patches. 1. Mksquashfs has been rewritten to be multi-threaded. It has the following improvements 1.1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 1.2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 1.3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 1.4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 1.5 The use of swap memory was found to significantly impact performance. The amount of memory used to cache files is now a command line option, by default this is 512 Mbytes. 2. Unsquashfs has the following improvements 2.1 Unsquashfs now allows you to specify the filename or the directory within the Squashfs filesystem that is to be extracted, rather than always extracting the entire filesystem. 2.2 A new -force option has been added which forces Unsquashfs to output to the destination directory even if files and directories already exist in the destination directory. This allows you to update an already existing directory tree, or to Unsquashfs to a partially filled directory tree. Without the -force option Unsquashfs will refuse to output. 3. The following major bug fixes have been made 3.1 A fragment table rounding bug has been fixed in Mksquashfs. Previously if the number of fragments in the filesystem were a multiple of 512, Mksquashfs would generate an incorrect filesystem. 3.2 A rare SMP bug which occurred when simultaneously acccessing multiply mounted Squashfs filesystems has been fixed. 4. Miscellaneous improvements/bug fixes 4.1 Kernel code stack usage has been reduced. This is to ensure Squashfs works with 4K stacks. 4.2 Readdir (Squashfs kernel code) has been fixed to always return 0, rather than the number of directories read. Squashfs should now interact better with NFS. 4.3 Lseek bug in Mksquashfs when appending to larger than 4GB filesystems fixed. 4.4 Squashfs 2.x initrds can now been mounted. 4.5 Unsquashfs exit status fixed. 4.6 New patches for linux-2.6.18 and linux-2.4.33. 3.0 15 MAR 2006 Major filesystem improvements 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). 2.2-r2 8 SEPT 2005 Second release of 2.2, this release fixes a couple of small bugs, a couple of small documentation mistakes, and adds a patch for kernel 2.6.13. 1. Mksquashfs now deletes the output filesystem image file if an error occurs whilst generating the filesystem. Previously on error the image file was left empty or partially written. 2. Updated mksquashfs so that it doesn't allow you to generate filesystems with block sizes smaller than 4K. Squashfs hasn't supported block sizes less than 4K since 2.0-alpha. 3. Mksquashfs now ignores missing files/directories in sort files. This was the original behaviour before 2.2. 4. Fixed small mistake in fs/Kconfig where the version was still listed as 2.0. 5. Updated ACKNOWLEDGEMENTS file. 2.2 3 JUL 2005 This release has some small improvements, bug fixes and patches for new kernels. 1. Sort routine re-worked and debugged from release 2.1. It now allows you to give Mkisofs style sort files and checks for filenames that don't match anything. Sort priority has also been changed to conform to Mkisofs usage, highest priority files are now placed at the start of the filesystem (this means they will be on the inside of a CD or DVD). 2. New Configure options for embedded systems (memory constrained systems). See INSTALL file for further details. 3. Directory index bug fixed where chars were treated as signed on some architectures. A file would not be found in the rare case that the filename started with a chracter greater than 127. 4. Bug introduced into the read_data() routine when sped up to use data block queueing fixed. If the second or later block resulted in an I/O error this was not checked. 5. Append bug introduced in 2.1 fixed. The code to compute the new compressed and uncompressed directory parts after appending was wrong. 6. Metadata block length read routine altered to not perform a misaligned short read. This was to fix reading on an ARM7 running uCLinux without a misaligned read interrupt handler. 7. Checkdata bug introduced in 2.1 fixed. 2.1-r2 15 DEC 2004 Code changed so it can be compiled with gcc 2.x 1. In some of the code added for release 2.1 I unknowingly used some gcc extensions only supported by 3.x compilers. I have received a couple of reports that the 2.1 release doesn't build on 2.x and so people are clearly still using gcc 2.x. The code has been rewritten to remove these extensions. 2.1 10 DEC 2004 Significantly improved directory handling plus numerous other smaller improvements 1. Fast indexed directories implemented. These speed up directory operations (ls, file lookup etc.) significantly for directories larger than 8 KB. 2. All directories are now sorted in alphabetical order. This again speeds up directory operations, and in some cases it also results in a small compression improvement (greater data similarity between files with alphabetically similar names). 3. Maximum directory size increased from 512 KB to 128 MB. 4. Duplicate fragment checking and appending optimised in mksquashfs, depending on filesystem, this is now up to 25% faster. 5. Mksquashfs help information reformatted and reorganised. 6. The Squashfs version and release date is now printed at kernel boot-time or module insertion. This addition will hopefully help to reduce the growing problem where the Squashfs version supported by a kernel is unknown and the kernel source is unavailable. 7. New PERFORMANCE.README file. 8. New -2.0 mksquashfs option. 9. CHANGES file reorganised. 10. README file reorganised, clarified and updated to include the 2.0 mksquashfs options. 11. New patch for Linux 2.6.9. 12. New patch for Linux 2.4.28. 2.0r2 29 AUG 2004 Workaround for kernel bug in kernels 2.6.8 and newer added 1. New patch for kernel 2.6.8.1. This includes a workaround for a kernel bug introduced in 2.6.7bk14, which is present in all later versions of the kernel. If you're using a 2.6.8 kernel or later then you must use this 2.6.8.1 patch. If you've experienced hangs or oopses using Squashfs with a 2.6.8 or later kernel then you've hit this bug, and this patch will fix it. It is worth mentioning that this kernel bug potentially affects other filesystems. If you receive odd results with other filesystems you may be experiencing this bug with that filesystem. I submitted a patch but this has not yet gone into the kernel, hopefully the bug will be fixed in later kernels. 2.0 13 JULY 2004 A couple of new options, and some bug fixes 1. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 2. Initrds are now supported for kernels 2.6.x. 3. amd64 bug fixes. If you use an amd64, please read the README-AMD64 file. 4. Check-data and gid bug fixes. With 2.0-alpha when mounting 1.x filesystems in certain cases file gids were corrupted. 5. New patch for Linux 2.6.7. 2.0-ALPHA 21 MAY 2004 Filesystem changes and compression improvements 1. Squashfs 2.0 has added the concept of fragment blocks. Files smaller than the file block size and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K (in the ALPHA version of Squashfs 2.0). 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 6. Numerous small bug fixes have been made. 1.3r3 18 JAN 2004 Third release of 1.3, this adds a new mksquashfs option, some bug fixes, and extra patches for new kernels 1. New mksquashfs -ef exclude option. This option reads the exclude dirs/files from an exclude file, one exclude dir/file per line. This avoids the command line size limit when using the -e exclude option, 2. When appending to existing filesystems, if mksquashfs experiences a fatal error (e.g. out of space when adding to the destination), the original filesystem is restored, 3. Mksquashfs now builds standalone, without the kernel needing to be patched. 4. Bug fix in the kernel squashfs filesystem, where the pages being filled were not kmapped. This seems to only have caused problems on an Apple G5, 5. New patch for Linux 2.4.24, 6. New patch for Linux 2.6.1, this replaces the patch for 2.6.0-test7. 1.3r2 14 OCT 2003 Second release of 1.3, bug fixes and extra patches for new kernels 1. Bug fix in routine that adds files to the filesystem being generated in mksquashfs. This bug was introduced in 1.3 (not enough testing...) when I rewrote it to handle files larger than available memory. This bug caused a SEGV, so if you've ever got that, it is now fixed, 2. Long running bug where ls -s and du reported wrong block size fixed. I'm pretty sure this used to work many kernel versions ago (2.4.7) but it broke somewhere along the line since then, 3. New patch for Linux 2.4.22, 4. New patch for 2.6.0-test7, this replaces the patch for 2.6.0-test1. 1.3 29 JUL 2003 FIFO/Socket support added plus optimisations and improvements 1. FIFOs and Socket inodes are now supported, 2. Mksquashfs can now compress files larger than available memory, 3. File duplicate check routine optimised, 4. Exit codes fixed in Mksquashfs, 5. Patch for Linux 2.4.21, 6. Patch for Linux 2.6.0-test1. Hopefully, this will work for the next few releases of 2.6.0-testx, otherwise, I'll be releasing a lot of updates to the 2.6.0 patch... 1.2 13 MAR 2003 Append feature and new mksquashfs options added Mksquashfs can now add to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. See the README file for usage changes. 1.1b 16 JAN 2003 Bug fix release Fixed readpage deadlock bug. This was a rare deadlock bug that happened when pushing pages into the page cache when using greater than 4K blocks. I never got this bug when I tested the filesystem, but two people emailed me on the same day about the problem! I fixed it by using a page cache function that wasn't there when I originally did the work, which was nice :-) 1.1 8 JAN 2003 Added features 1. Kernel squashfs can now mount different byte order filesystems. 2. Additional features added to mksquashfs. Mksquashfs now supports exclude files and multiple source files/directories can be specified. A nopad option has also been added, which informs mksquashfs not to pad filesystems to a multiple of 4K. See README for mksquashfs usage changes. 3. Greater than 2GB filesystems bug fix. Filesystems greater than 2GB can now be created. 1.0c 14 NOV 2002 Bug fix release Fixed bugs with initrds and device nodes 1.0 23 OCT 2002 Initial release ================================================ FILE: src/others/squashfs-4.2/COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) 19yy <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: src/others/squashfs-4.2/DONATIONS ================================================ Help sponsor Squashfs development! Maintaining and improving Squashfs is a lot of work, but Squashfs is one of the only widely used Linux file systems that has no company backing. Squashfs development is funded soley by the author, partially supported by donations from companies and individuals that want to improve Squashfs for themselves and others. Mainlining of Squashfs only became possible when CELF (Consumer Electronics Linux Forum) offered to contribute to the costs, which allowed the author to work full-time on the project. There's lots of exciting new improvements to Squashfs in the pipeline, and if your company is a serious user of Squashfs, please consider accelerating development of Squashfs by donating. Donatations can be made from the Squashfs sourceforge homepage, or if you prefer by contacting the author privately. ================================================ FILE: src/others/squashfs-4.2/INSTALL ================================================ INSTALLING SQUASHFS The squashfs4.2.tar.gz file contains the squashfs-tools directory containing mksquashfs and unsquashfs. 1. Kernel support ----------------- This release is for 2.6.29 and newer kernels. Kernel patching is not necessary. Extended attribute support requires 2.6.35 or newer. File systems with extended attributes can be mounted on 2.6.29 and newer kernels (the extended attributes will be ignored with a warning). LZO compression support requires 2.6.36 or newer kernels. XZ compression support requires 2.6.38 or newer kernels. 2. Building squashfs tools -------------------------- The squashfs-tools directory contains the mksquashfs and unsquashfs programs. These can be made by typing make (or make install to install in /usr/local/bin). By default the tools are built with GZIP compression and extended attribute support. Read the Makefile in squashfs-tools/ for instructions on building LZO and XZ compression support, and for instructions on disabling GZIP and extended attribute support if desired. ================================================ FILE: src/others/squashfs-4.2/Makefile ================================================ all: make -C squashfs-tools cp squashfs-tools/unsquashfs . cp squashfs-tools/mksquashfs . clean: make -C squashfs-tools clean rm -f unsquashfs mksquashfs ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-2.0 ================================================ NOTE: This the original README for version 2.0. It is retained as it contains information about the fragment design. A description of the new 2.0 mksquashfs options has been added to the main README file, and that file should now be consulted for these. SQUASHFS 2.0 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to the final release of Squashfs version 2.0! A lot of changes to the filesystem have been made under the bonnet (hood). Squashfs 2.0 uses fragment blocks and larger blocks (64K) to improve compression ratio by about 5 - 20% over Squashfs 1.0 depending on the files being compressed. Using fragment blocks allows Squashfs 2.0 to achieve better compression than cloop and similar compression to tgz files while retaining the I/O efficiency of a compressed filesystem. Detailed changes: 1. Squashfs 2.0 has added the concept of fragment blocks (see later discussion). Files smaller than the file block size (64K in Squashfs 2.0) and optionally the remainder of files that do not fit fully into a block (i.e. the last 32K in a 96K file) are packed into shared fragments and compressed together. This achieves on average 5 - 20% better compression than Squashfs 1.x. 2. The maximum block size has been increased to 64K. 3. The maximum number of UIDs has been increased to 256 (from 48 in 1.x). 4. The maximum number of GIDs has been increased to 256 (from 15 in 1.x). 5. New mksquashfs -all-root, -root-owned, -force-uid, and -force-gid options. These allow the uids/gids of files in the generated filesystem to be specified, overriding the uids/gids in the source filesystem. 6. Initrds are now supported for kernels 2.6.x. 7. Removal of sleep_on() function call in 2.6.x patch, to allow Squashfs to work on the Fedora rc2 kernel. 8. AMD64, check-data and gid bug fixes. 9. Numerous small bug fixes have been made. 10. New patch for Linux 2.6.7. New Squashfs 2.0 options ------------------------ -noF or -noFragmentCompression Do not compress the fragments. Added for compatibility with noI and noD, probably not that useful. -no-fragments Do not use fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 2.0 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. -always-use-fragments By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. -no-duplicates Do not detect duplicate files. -all-root -root-owned These options (both do exactly the same thing), force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. -force-uid uid This option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. -force-gid gid This option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. Compression improvements example -------------------------------- The following is the compression results obtained compressing the 2.6.6 linux kernel source using CRAMFS, Cloop (with iso filesystem), Squashfs 1.3 and Squashfs 2.0 (results generated using big-endian filesystems). In decreasing order of size: CRAMFS 62791680 bytes (59.9M) Squashfs 1.x 51351552 bytes (48.9M) Cloop 46118681 bytes (44.0M) Squashfs 2.0 45604854 bytes (43.5M) The Squashfs 1.x filesystem is 12.6% larger than the new 2.0 filesystem. The cloop filesystem is 1.1% larger than the Squashfs 2.0 filesystem. Fragment blocks in Squashfs 2.0 ------------------------------- Squashfs like all other compressed filesystems compresses files individually on a block by block basis. This is performed to allow mounting and de-compression of files on a block by block basis without requiring the entire filesystem to be decompressed. This is in contrast to data-based compression schemes which compress without understanding the underlying filesystem (i.e. cloop and tgz files) and which, therefore, do not compress files individually. Each approach has advantages and disadvantages, data-based systems have better compression because compression is always performed at the maximum block size (64K in cloop) irrespective of the size of each file (which could be less than the block size). Compressed filesystems tend to be faster at I/O because they understand the filesystem and therefore employ better caching stategies and read less un-needed data from the filesystem. Fragment blocks in Squashfs 2.0 solves this problem by packing files (and optionally the ends of files) which are smaller than the block size into shared blocks, which are compressed together. For example five files each of 10K will be packed into one shared fragment of 50K and compressed together, rather than being compressed in five 10K blocks. This scheme produces a hybrid filesystem, retaining the I/O efficiency of a compressed filesystem, while obtaining the compression efficiency of data-based schemes by compressing small files together. Squashfs 1.x and Squashfs 2.0 compatibility ------------------------------------------- Appending to Squashfs 1.x filesystems is not supported. If you wish to append to 1.x filesystems, then either use the original mksquashfs, or convert them to Squashfs 2.0 by mounting the filesystem and running the 2.0 mksquashfs on the mounted filesystem. Mounting Squashfs 1.x filesystems IS supported by the 2.0 kernel patch. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-2.1 ================================================ SQUASHFS 2.1 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher (plougher@users.sourceforge.net) Released under the GPL licence (version 2 or later). Welcome to Squashfs version 2.1-r2. Squashfs 2.1 introduces indexed directories which considerably speed up directory lookup (ls, find etc.) for directories which are greater than 8K in size. All directories are now also sorted alphabetically which further speeds up directory lookup. Many smaller improvements have also been made to this release, please see the CHANGES file entry for detailed changes. 1. DIRECTORY SPEED IMPROVEMENT EXAMPLES --------------------------------------- To give an indication of the directory speed improvements a number of test results are shown here. There is in addition a new PERFORMANCE.README file which gives details of I/O and lookup performance for Squashfs 2.1 against the Zisofs, Cloop and CRAMFS filesystems. example 1: Filesystems generated from a single directory of 72,784 files (2.6 MB directory size). Each file is 10 bytes in size (the test is directory lookup and so the file size isn't an issue). The ext3 uncompressed directory size is 288 MB (presumably because of one file per block). Zisofs compressed size 153.50 MB Cloop (isofs) compressed size 1.74 MB Squashfs2.1 compressed size 612 KB (0.60 MB) Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 35 minutes 7.895 seconds (User 7.868 secs, Sys 34 mins 5.621 secs) Cloop 35 minutes 12.765 seconds (User 7.771 secs, Sys 34 mins 3.869 secs) Squashfs2.1 19 seconds (User 5.119 secs, Sys 14.547 secs) example 2: Filesystems were generated from the Ubuntu Warty livecd (original uncompressed size on ext3 is 1.4 GB). Zisofs compressed size 589.81 MB Cloop (isofs) compressed size 471.19 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB Time taken to perform "ls -lR --color=always | cat > /dev/null" on filesystems mounted on hard disk. Zisofs 49.875 seconds (User time 2.589 secs, Sys 11.194 secs) Cloop 20.797 seconds (User time 2.706 secs, Sys 13.496 secs) Squashfs2.0 16.556 seconds (User time 2.424 secs, Sys 10.371 secs) Squashfs2.1 10.143 seconds (User time 2.475 secs, Sys 4.440 secs) NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 2. NEW MKSQUASHFS OPTIONS ------------------------- There is only one extra option "-2.0". This tells mksquashfs to generate a filesystem which is mountable with Squashfs version 2.0. 3. APPENDING AND MOUNTING SQUASHFS 2.0 FILESYSTEMS -------------------------------------------------- Mounting 2.0 filesystems is supported by Squashfs 2.1. In addition mksquashfs v2.1 can append to 2.0 filesystems, although the generated filesystem will still be a 2.0 filesystem. 4. DONATIONS ------------ If you find Squashfs useful then please consider making a donation, particularly if you use Squashfs in a commercial product. Please consider giving something back especially if you're making money from it. Off the Squashfs subject somewhat I'm currently looking for another job doing Linux kernel or filesystems work. If you know of any such work that can be performed from the UK then please get in touch. Thanks. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-3.0 ================================================ SQUASHFS 3.0 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to the first release of Squashfs version 3.0. Squashfs 3.0 has the the following improvements to 2.x. 1. Filesystems are no longer limited to 4 GB. In theory 2^64 or 4 exabytes is now supported. 2. Files are no longer limited to 4 GB. In theory the maximum file size is 4 exabytes. 3. Metadata (inode table and directory tables) are no longer restricted to 16 Mbytes. 4. Hardlinks are now suppported. 5. Nlink counts are now supported. 6. Readdir now returns '.' and '..' entries. 7. Special support for files larger than 256 MB has been added to the Squashfs kernel code for faster read access. 8. Inode numbers are now stored within the inode rather than being computed from inode location on disk (this is not so much an improvement, but a change forced by the previously listed improvements). There is a new Unsquashfs utility (in squashfs-tools) than can be used to decompress a filesystem without mounting it. Squashfs 3.0 supports 2.x filesystems. Support for 1.x filesystems will be added in the future. 1. UNSQUASHFS ------------- Unsquashfs has the following options: SYNTAX: unsquashfs [-ls | -dest] filesystem -version print version, licence and copyright information -info print files as they are unsquashed -ls list filesystem only -dest <pathname> unsquash to <pathname>, default "squashfs-root" The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-info" option forces Unsquashfs to print each file as it is decompressed. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. Unsquashfs can decompress 3.0 filesystems. Support for 2.x and 1.x filesystems will be added in the future. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-3.1 ================================================ SQUASHFS 3.1 - A squashed read-only filesystem for Linux Copyright 2002-2006 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.1-r2. Squashfs 3.1 has major improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- Mksquashfs has been rewritten and it is now multi-threaded. It offers the following improvements: 1. Parallel compression. By default as many compression and fragment compression threads are created as there are available processors. This significantly speeds up performance on SMP systems. 2. File input and filesystem output is peformed in parallel on separate threads to maximise I/O performance. Even on single processor systems this speeds up performance by at least 10%. 3. Appending has been significantly improved, and files within the filesystem being appended to are no longer scanned and checksummed. This significantly improves append time for large filesystems. 4. File duplicate checking has been optimised, and split into two separate phases. Only files which are considered possible duplicates after the first phase are checksummed and cached in memory. 5. The use of swap memory was found to significantly impact performance. The amount of memory used to cache the file is now a command line option, by default this is 512 Mbytes. 1.1 NEW COMMAND LINE OPTIONS ---------------------------- The new Mksquashfs program has a couple of extra command line options which can be used to control the new features: -processors <processors> This specifies the number of processors used by Mksquashfs. By default this is the number of available processors. -read_queue <size in Mbytes> This specifies the size of the file input queue used by the reader thread. This defaults to 64 Mbytes. -write_queue <size in Mbytes> This specifies the size of the filesystem output queue used by the writer thread. It also specifies the maximum cache used in file duplicate detection (the output queue is shared between these tasks). This defaults to 512 Mbytes. 1.2 PERFORMANCE RESULTS ----------------------- The following results give an indication of the speed improvements. Two example filesystems were tested, a liveCD filesystem (about 1.8 Gbytes uncompressed), and my home directory consisting largely of text files (about 1.3 Gbytes uncompressed). Tests were run on a single core and a dual core system. Dual Core (AMDx2 3800+) system: Source directories on ext3. LiveCD, old mksquashfs: real 11m48.401s user 9m27.056s sys 0m15.281s LiveCD, new par_mksquashfs: real 4m8.736s user 7m11.771s sys 0m27.749s "Home", old mksquashfs: real 4m34.360s user 3m54.007s sys 0m32.155s "Home", new par_mksquashfs: real 1m27.381s user 2m7.304s sys 0m17.234s Single Core PowerBook (PowerPC G4 1.5 GHz Ubuntu Linux) Source directories on ext3. LiveCD, old mksquashs: real 11m38.472s user 9m6.137s sys 0m23.799s LiveCD, par_mksquashfs: real 10m5.572s user 8m59.921s sys 0m16.145s "Home", old mksquashfs: real 3m42.298s user 2m49.478s sys 0m13.675s "Home", new par_mksquashfs: real 3m9.178s user 2m50.699s sys 0m9.069s I'll be interested in any performance results obtained, especially from SMP machines larger than my dual-core AMD box, as this will give an indication of the scalability of the code. Obviously, I'm also interested in any problems, deadlocks, low performance etc. 2. UNSQUASHFS ------------- Unsquashfs now allows you to specify the filename or directory that is to be extracted from the Squashfs filesystem, rather than always extracting the entire filesystem. It also has a new "-force" option, and all options can be specified in a short form (-i rather than -info). The Unsquashfs usage info is now: SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract] -v[ersion] print version, licence and copyright information -i[nfo] print files as they are unsquashed -l[s] list filesystem only -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -f[orce] if file already exists then overwrite To extract a subset of the filesystem, the filename or directory tree that is to be extracted can now be specified on the command line. The file/directory should be specified using the full path to the file/directory as it appears within the Squashfs filesystem. The file/directory will also be extracted to that position within the specified destination directory. The new "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-3.2 ================================================ SQUASHFS 3.2 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.org.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 3.2. Squashfs 3.2 has support for NFS exporting, some improvements to the Squashfs tools (Mksquashfs and Unsquashfs), some major bug fixes, new kernel patches, and various other smaller improvements and bug fixes. Please see the CHANGES file for a detailed list. 1. MKSQUASHFS ------------- New command line options: -no-exports Squashfs now supports NFS exports. By default the additional information necessary is added to the filesystem by Mksquashfs. If you do not wish this extra information, then this option can be specified. This will save a couple of bytes per file, and the filesystem will be identical to Squashfs 3.1. -no-progress Mksquashfs by default now displays a progress bar. This option disables it. 2. UNSQUASHFS ------------- Unsquashfs now supports Squashfs 2.x filesystems. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-3.3 ================================================ SQUASHFS 3.3 - A squashed read-only filesystem for Linux Copyright 2002-2007 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to another release of Squashfs. This is the 22nd release in just over five years of work. Squashfs 3.3 has lots of nice improvements, both to the filesystem itself (bigger blocks, and sparse files), but also to the Squashfs-tools Mksquashfs and Unsquashfs. As usual the CHANGES file has a detailed list of all the improvements. Following is a description of the changes to the Squashfs tools, usage guides to the new options, and a summary of the new options. 1. MKSQUASHFS - EXTENDED EXCLUDE FILE HANDLING ---------------------------------------------- 1. Extended wildcard pattern matching now supported in exclude files Enabled by specifying -wildcards option Supports both anchored and non-anchored exclude files. 1.1 Anchored excludes Similar to existing exclude files except with wildcards. Exclude file matches from root of source directories. Examples: 1. mksquashfs example image.sqsh -wildcards -e 'test/*.gz' Exclude all files matching "*.gz" in the top level directory "test". 2. mksquashfs example image.sqsh -wildcards -e '*/[Tt]est/example*' Exclude all files beginning with "example" inside directories called "Test" or "test", that occur inside any top level directory. Using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e 'test/!(*data*).gz' Exclude all files matching "*.gz" in top level directory "test", except those with "data" in the name. 1.2 Non-anchored excludes By default excludes match from the top level directory, but it is often useful to exclude a file matching anywhere in the source directories. For this non-anchored excludes can be used, specified by pre-fixing the exclude with "...". Examples: 1. mksquashfs example image.sqsh -wildcards -e '... *.gz' Exclude files matching "*.gz" anywhere in the source directories. For example this will match "example.gz", "test/example.gz", and "test/test/example.gz". 2. mksquashfs example image.sqsh -wildcards -e '... [Tt]est/*.gz' Exclude files matching "*.gz" inside directories called "Test" or "test" that occur anywhere in the source directories. Again, using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e '... !(*data*).gz' Exclude all files matching "*.gz" anywhere in the source directories, except those with "data" in the name. 2. Regular expression pattern matching now supported in exclude files Enabled by specifying -regex option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. Supports both anchored and non-anchored exclude files. 2. MKSQUASHFS - NEW RECOVERY FILE FEATURE ----------------------------------------- Recovery files are now created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). The recovery files are called squashfs_recovery_xxx_yyy, where "xxx" is the name of the filesystem being appended to, and "yyy" is a number to guarantee filename uniqueness (the PID of the parent Mksquashfs process). Normally if Mksquashfs exits correctly the recovery file is deleted to avoid cluttering the filesystem. If Mksquashfs aborts, the "-recover" option can be used to recover the filesystem, giving the previously created recovery file as a parameter, i.e. mksquashfs dummy image.sqsh -recover squashfs_recovery_image.sqsh_1234 The writing of the recovery file can be disabled by specifying the "-no-recovery" option. 3. UNSQUASHFS - EXTENDED EXTRACT FILE HANDLING ---------------------------------------------- 1. Multiple extract files can now be specified on the command line, and the files/directories to be extracted can now also be given in a file. To specify a file containing the extract files use the "-e[f]" option. 2. Extended wildcard pattern matching now supported in extract files Enabled by default. Similar to existing extract files except with wildcards. Examples: 1. unsquashfs image.sqsh 'test/*.gz' Extract all files matching "*.gz" in the top level directory "test". 2. unsquashfs image.sqsh '[Tt]est/example*' Extract all files beginning with "example" inside top level directories called "Test" or "test". Using extended wildcards, negative matching is also possible. 3. unsquashfs image.sqsh 'test/!(*data*).gz' Extract all files matching "*.gz" in top level directory "test", except those with "data" in the name. 3. Regular expression pattern matching now supported in extract files Enabled by specifying -r[egex] option. Identical behaviour to wild card pattern matching, except patterns are considered to be regular expressions. 4. UNSQUASHFS - EXTENDED FILENAME PRINTING ------------------------------------------ Filename printing has been enhanced and Unquashfs can now display filenames with file attributes ('ls -l' style output). New options: -ll[s] list filesystem with file attributes, but don't unsquash -li[nfo] print files as they are unsquashed with file attributes 5. UNSQUASHFS - MISCELLANEOUS OPTIONS ------------------------------------- -s[tat] Display the filesystem superblock information. This is useful to discover the filesystem version, byte ordering, whether it has an NFS export table, and what options were used to compress the filesystem. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-4.0 ================================================ SQUASHFS 4.0 - A squashed read-only filesystem for Linux Copyright 2002-2009 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs 4.0. This is an initial tools only release to support users of the 2.6.29 kernel, following the mainlining of Squashfs earlier this year. Later releases will probably contain kernel patches supporting 4.0 layouts for earlier kernels. New Mksquashfs options ---------------------- Mksquashfs now supports pseudo files, these allow fake directories, character and block devices to be specified and added to the Squashfs filesystem being built, rather than requiring them to be present in the source directories. This, for example, allows device nodes to be added to the filesystem without requiring root access. Two options are supported, -p allows one pseudo file to be specified on the command line, and -pf allows a pseudo file to be specified containing a list of pseduo definitions, one per line. Pseudo device nodes are specified using 7 arguments Filename type mode uid gid major minor Where type is either b - for block devices, and c - for character devices mode is the octal mode specifier, similar to that expected by chmod. Uid and gid can be either specified as a decimal number, or by name. For example: /dev/chr_dev c 666 root root 100 1 /dev/blk_dev b 444 0 0 200 200 Directories are specified using 5 arguments Filename type mode uid gid Where type is d. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-4.1 ================================================ SQUASHFS 4.1 - A squashed read-only filesystem for Linux Copyright 2002-2010 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs 4.1. This is a tools only release, support for Squashfs file systems is in mainline (2.6.29 and later). New features in Squashfs-tools 4.1 ---------------------------------- 1. Support for extended attributes 2. Support for LZMA and LZO compression 3. New pseudo file features Compatiblity ------------ Mksquashfs 4.1 generates 4.0 filesystems. These filesystems are fully compatible/interchangable with filesystems generated by Mksquashfs 4.0 and are mountable on 2.6.29 and later kernels. Extended attributes (xattrs) ---------------------------- Squashfs file systems now have extended attribute support. The extended attribute implementation has the following features: 1. Layout can store up to 2^48 bytes of compressed xattr data. 2. Number of xattrs per inode unlimited. 3. Total size of xattr data per inode 2^48 bytes of compressed data. 4. Up to 4 Gbytes of data per xattr value. 5. Inline and out-of-line xattr values supported for higher performance in xattr scanning (listxattr & getxattr), and to allow xattr value de-duplication. 6. Both whole inode xattr duplicate detection and individual xattr value duplicate detection supported. These can obviously nest, file C's xattrs can be a complete duplicate of file B, and file B's xattrs can be a partial duplicate of file A. 7. Xattr name prefix types stored, allowing the redundant "user.", "trusted." etc. characters to be eliminated and more concisely stored. 8. Support for files, directories, symbolic links, device nodes, fifos and sockets. Extended attribute support is in 2.6.35 and later kernels. File systems with extended attributes can be mounted on 2.6.29 and later kernels, the extended attributes will be ignored with a warning. LZMA and LZO compression ------------------------ Squashfs now supports LZMA and LZO compression. LZO support is in 2.6.36 and newer kernels. LZMA is not yet in mainline. New Mksquashfs options ---------------------- -comp <comp> Select <comp> compression. The compression algorithms supported by the build of Mksquashfs can be found by typing mksquashfs without any arguments. The compressors available are displayed at the end of the help message, e.g. Compressors available: gzip (default) lzma lzo The default compression used when -comp isn't specified on the command line is indicated by "(default)". -no-xattrs Don't store extended attributes -xattrs Store extended attributes The default behaviour of Mksquashfs with respect to extended attribute storage is build time selectable. The Mksquashfs help message indicates whether extended attributes are stored or not, e.g. -no-xattrs don't store extended attributes -xattrs store extended attributes (default) shows that extended attributes are stored by default, and can be disabled by the -no-xattrs option. -no-xattrs don't store extended attributes (default) -xattrs store extended attributes shows that extended attributes are not stored by default, storage can be enabled by the -xattrs option. -noX -noXattrCompression Don't compress extended attributes New Unsquashfs options ---------------------- -n[o-xattrs] Don't extract xattrs in filesystem -x[attrs] Extract xattrs in filesystem The default behaviour of Unsquashfs with respect to extended attributes is build time selectable. The Unsquashfs help message indicates whether extended attributes are stored or not, e.g. -no[-xattrs] don't extract xattrs in file system -x[attrs] extract xattrs in file system (default) shows that xattrs are extracted by default. -no[-xattrs] don't extract xattrs in file system (default) -x[attrs] extract xattrs in file system shows that xattrs are not extracted by default. New pseudo file support ----------------------- Mksquashfs supports pseudo files, these allow fake files, directories, character and block devices to be specified and added to the Squashfs filesystem being built, rather than requiring them to be present in the source directories. This, for example, allows device nodes to be added to the filesystem without requiring root access. Mksquashfs 4.1 adds support for "dynamic pseudo files" and a modify operation. Dynamic pseudo files allow files to be dynamically created when Mksquashfs is run, their contents being the result of running a command or piece of shell script. The modifiy operation allows the mode/uid/gid of an existing file in the source filesystem to be modified. Two Mksquashfs options are supported, -p allows one pseudo file to be specified on the command line, and -pf allows a pseudo file to be specified containing a list of pseduo definitions, one per line. Pseudo operations ----------------- 1. Creating a dynamic file -------------------------- Pseudo definition Filename f mode uid gid command mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. command can be an executable or a piece of shell script, and it is executed by running "/bin/sh -c command". The stdout becomes the contents of "Filename". Examples: Running a basic command ----------------------- /somedir/dmesg f 444 root root dmesg creates a file "/somedir/dmesg" containing the output from dmesg. Executing shell script ---------------------- RELEASE f 444 root root \ if [ ! -e /tmp/ver ]; then \ echo 0 > /tmp/ver; \ fi; \ ver=`cat /tmp/ver`; \ ver=$((ver +1)); \ echo $ver > /tmp/ver; \ echo -n `cat /tmp/release`; \ echo "-dev #"$ver `date` "Build host" `hostname` Creates a file RELEASE containing the release name, date, build host, and an incrementing version number. The incrementing version is a side-effect of executing the shell script, and ensures every time Mksquashfs is run a new version number is used without requiring any other shell scripting. The above example also shows that commands can be split across multiple lines using "\". Obviously as the script will be presented to the shell as a single line, a semicolon is need to separate individual shell commands within the shell script. Reading from a device (or fifo/named socket) -------------------------------------------- input f 444 root root dd if=/dev/sda1 bs=1024 count=10 Copies 10K from the device /dev/sda1 into the file input. Ordinarily Mksquashfs given a device, fifo, or named socket will place that special file within the Squashfs filesystem, the above allows input from these special files to be captured and placed in the Squashfs filesystem. 2. Creating a block or character device --------------------------------------- Pseudo definition Filename type mode uid gid major minor Where type is either b - for block devices, and c - for character devices mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: /dev/chr_dev c 666 root root 100 1 /dev/blk_dev b 666 0 0 200 200 creates a character device "/dev/chr_dev" with major:minor 100:1 and a block device "/dev/blk_dev" with major:minor 200:200, both with root uid/gid and a mode of rw-rw-rw. 3. Creating a directory ----------------------- Pseudo definition Filename d mode uid gid mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: /pseudo_dir d 666 root root creates a directory "/pseudo_dir" with root uid/gid and mode of rw-rw-rw. 4. Modifying attributes of an existing file ------------------------------------------- Pseudo definition Filename m mode uid gid mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: dmesg m 666 root root Changes the attributes of the file "dmesg" in the filesystem to have root uid/gid and a mode of rw-rw-rw, overriding the attributes obtained from the source filesystem. ================================================ FILE: src/others/squashfs-4.2/OLD-READMEs/README-AMD64 ================================================ Information for amd64 users --------------------------- All releases of Squashfs prior to 2.0 generate incorrect filesystems on amd64 machines. Filesystems created on amd64 machines work correctly on amd64 machines, but cannot be mounted on non-amd64 machines. Likewise, filesystems created on non-amd64 machines cannot be mounted on amd64 machines. This bug is caused by the different size of the "time_t" definition used in SquashFS filesystem structures. This bug is fixed in releases 2.0 and newer. However, all amd64 filesystems generated by previous releases will not be mountable on amd64 machines with newer releases. If you have amd64 filesystems generated with mksquashfs version 2.0-alpha or older, it is important that you recreate the filesystem. This can be performed by mounting the filesystem using a kernel with the original patch (i.e. a 2.0-alpha or older patch) and running the NEW (i.e. this release) mksquashfs tool to create a new SquashFS filesystem. ================================================ FILE: src/others/squashfs-4.2/PERFORMANCE.README ================================================ GENERAL INFORMATION ON PERFORMANCE TESTS ---------------------------------------- The following performance tests were based on two file sets: the liveCD filesystem from the Ubuntu liveCD (Warty release), and the liveCD filesystem from the Damn Small Linux liveCD (release 0.8.4). The Ubuntu liveCD filesystem was used to test filesystem performance from CDROM and hard disk for Zisofs, Cloop, Squashfs 2.0 and Squashfs2.1. CRAMFS filesystem performance could not be tested for this filesystem bacause it exceeds the maximum supported size of CRAMFS. To test CRAMFS performance against Squashfs, the liveCD filesystem from Damn Small Linux was used. NOTE: the usual warnings apply to these results, they are provided for illustrative purposes only, and due to different hardware and/or file data, you may obtain different results. As such the results are provided "as is" without any warranty (either express or implied) and you assume all risks as to their quality and accuracy. 1. Ubuntu liveCD performance tests ext3 uncompressed size 1.4 GB Zisofs compressed size 589.81 MB Cloop compressed size 471.89 MB Squashfs2.0 compressed size 448.58 MB Squashfs2.1 compressed size 448.58 MB 1.1 Performance tests from CDROM 1.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM Zisofs 49.88 seconds (User 2.60 secs, Sys 11.19 secs) Cloop 20.80 seconds (User 2.71 secs, Sys 13.50 secs) Squashfs2.0 16.56 seconds (User 2.42 secs, Sys 10.37 secs) Squashfs2.1 10.14 seconds (User 2.48 secs, Sys 4.44 secs) 1.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM Zisofs 27 minutes 28.54 seconds (User 3.00 secs, Sys 1 min 4.80 secs) Cloop 5 minutes 55.72 seconds (User 2.90 secs, Sys 3 min 37.90 secs) Squashfs2.0 5 minutes 20.87 seconds (User 2.33 secs, Sys 56.98 secs) Squashfs2.1 5 minutes 15.46 seconds (user 2.28 secs, Sys 51.12 secs) 1.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM Zisofs 101 minutes 29.65 seconds (User 5.33 secs, Sys 1 min 17.20 secs) Cloop 35 minutes 27.51 seconds (user 5.93 secs, Sys 4 mins 30.23 secs) Squashfs2.0 21 minutes 53.05 seconds (user 5.71 secs, Sys 2 mins 36.59 secs) Squashfs2.1 21 minutes 46.99 seconds (User 5.80 secs, Sys 2 mins 31.88 secs) 1.2 Performance tests from Hard disk 1.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 17.29 seconds (User 2.62 secs, Sys 11.08 secs) Cloop 16.46 seconds (User 2.63 secs, Sys 13.41 secs) Squashfs2.0 13.75 seconds (User 2.44 secs, Sys 11.00 secs) Squashfs2.1 6.94 seconds (User 2.44 secs, Sys 4.48 secs) 1.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk Zisofs 1 minute 21.47 seconds (User 2.73 secs, Sys 54.44 secs) Cloop 1 minute 34.06 seconds (user 2.85 secs, Sys 1 min 12.13 secs) Squashfs2.0 1 minute 21.22 seconds (User 2.42 secs, Sys 56.21 secs) Squashfs2.1 1 minute 15.46 seconds (User 2.36 secs, Sys 49.78 secs) 1.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk Zisofs 11 minutes 13.64 seconds (User 5.08 secs, Sys 52.62 secs) Cloop 5 minutes 37.93 seconds (user 6 secs, Sys 2 mins 22.38 secs) Squashfs2.0 5 minutes 7.11 seconds (user 5.63 secs, Sys 2 mins 35.23 secs) Squashfs2.1 5 minutes 1.87 seconds (User 5.71 secs, Sys 2 mins 29.98 secs) 2. Damn Small Linux liveCD performance tests ext3 uncompressed size 126 MB CRAMFS compressed size 52.19 MB Squashfs2.0 compressed size 46.52 MB Squashfs2.1 compressed size 46.52 MB 2.1 Performance tests from CDROM 2.1.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 10.85 seconds (User 0.39 secs, Sys 0.98 secs) Squashfs2.0 2.97 seconds (User 0.36 secs, Sys 2.15 secs) Squashfs2.1 2.43 seconds (User 0.40 secs, Sys 1.42 secs) 2.1.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from CDROM CRAMFS 55.38 seconds (User 0.34 secs, Sys 6.98 secs) Squashfs2.0 35.99 seconds (User 0.30 secs, Sys 6.35 secs) Squashfs2.1 33.83 seconds (User 0.26 secs, Sys 5.56 secs) 2.1.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from CDROM CRAMFS 3 minutes 1.68 seconds (User 0.54 secs, Sys 9.51 secs) Squashfs2.0 1 minute 39.45 seconds (User 0.57 secs, Sys 13.14 secs) Squashfs2.1 1 minute 38.41 seconds (User 0.58 secs, Sys 13.08 secs) 2.2 Performance tests from Hard disk 2.2.1 Directory Lookup performance Time taken to perform "ls -lR --color=alawys | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 1.77 seconds (User 0.53 secs, Sys 1.21 secs) Squashfs2.0 2.67 seconds (User 0.41 secs, Sys 2.25 secs) Squashfs2.1 1.87 seconds (User 0.41 secs, Sys 1.46 secs) 2.2.2 Sequential I/O performance Time taken to perform "tar cf - | cat > /dev/null" on filesystem mounted from Hard disk CRAMFS 6.80 seconds (User 0.36 secs, Sys 6.02 secs) Squashfs2.0 7.23 seconds (User 0.29 secs, Sys 6.62 secs) Squashfs2.1 6.53 seconds (User 0.31 secs, Sys 5.82 secs) 2.2.3 Random I/O performance Random access pattern generated by "find /mnt -type f -printf "%s %p\n" | sort -g | awk '{ printf $2 }' > /tmp/sort Time taken to perform "cpio -o --quiet -H newc < /tmp/sort > /dev/null" on filesystem mounted from Hard disk CRAMFS 28.55 seconds (User 0.49 secs, Sys 6.49 secs) Squashfs2.0 25.44 seconds (User 0.58 secs, Sys 13.17 secs) Squashfs2.1 24.72 seconds (User 0.56 secs, Sys 13.15 secs) ================================================ FILE: src/others/squashfs-4.2/README ================================================ SQUASHFS 4.2 - A squashed read-only filesystem for Linux Copyright 2002-2011 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs version 4.2. Please read the README-4.2 and CHANGES files for details of changes. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 1Mbytes (default block size 128K). Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. 1. SQUASHFS OVERVIEW -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. In theory files up to 2^64 bytes are supported. In theory filesystems can be up to 2^64 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 1Mbyte (the default size is 128K). Using 128K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 1.1 Extended attributes (xattrs) -------------------------------- Squashfs filesystems now have extended attribute support. The extended attribute implementation has the following features: 1. Layout can store up to 2^48 bytes of compressed xattr data. 2. Number of xattrs per inode unlimited. 3. Total size of xattr data per inode 2^48 bytes of compressed data. 4. Up to 4 Gbytes of data per xattr value. 5. Inline and out-of-line xattr values supported for higher performance in xattr scanning (listxattr & getxattr), and to allow xattr value de-duplication. 6. Both whole inode xattr duplicate detection and individual xattr value duplicate detection supported. These can obviously nest, file C's xattrs can be a complete duplicate of file B, and file B's xattrs can be a partial duplicate of file A. 7. Xattr name prefix types stored, allowing the redundant "user.", "trusted." etc. characters to be eliminated and more concisely stored. 8. Support for files, directories, symbolic links, device nodes, fifos and sockets. Extended attribute support is in 2.6.35 and later kernels. Filesystems with extended attributes can be mounted on 2.6.29 and later kernels, the extended attributes will be ignored with a warning. 2. USING SQUASHFS ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 3. MKSQUASHFS ------------- 3.1 Mksquashfs options and overview. ------------------------------------ As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. SYNTAX:./mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Filesystem build options: -comp <comp> select <comp> compression Compressors available: gzip (default) lzo xz -b <block_size> set data block to <block_size>. Default 131072 bytes -no-exports don't make the filesystem exportable via NFS -no-sparse don't detect sparse files -no-xattrs don't store extended attributes -xattrs store extended attributes (default) -noI do not compress inode table -noD do not compress data blocks -noF do not compress fragment blocks -noX do not compress extended attributes -no-fragments do not use fragments -always-use-fragments use fragment blocks for files larger than block size -no-duplicates do not perform duplicate checking -all-root make all files owned by root -force-uid uid set all file uids to uid -force-gid gid set all file gids to gid -nopad do not pad filesystem to a multiple of 4K -keep-as-directory if one source directory is specified, create a root directory containing that directory, rather than the contents of the directory Filesystem filter options: -p <pseudo-definition> Add pseudo file definition -pf <pseudo-file> Add list of pseudo file definitions -sort <sort_file> sort files according to priorities in <sort_file>. One file or dir with priority per line. Priority -32768 to 32767, default priority 0 -ef <exclude_file> list of exclude dirs/files. One per line -wildcards Allow extended shell wildcards (globbing) to be used in exclude dirs/files -regex Allow POSIX regular expressions to be used in exclude dirs/files Filesystem append options: -noappend do not append to existing filesystem -root-becomes <name> when appending source files/directories, make the original root become a subdirectory in the new root called <name>, rather than adding the new source items to the original root Mksquashfs runtime options: -version print version, licence and copyright message -recover <name> recover filesystem data using recovery file <name> -no-recovery don't generate a recovery file -info print files written to filesystem -no-progress don't display the progress bar -processors <number> Use <number> processors. By default will use number of processors available -read-queue <size> Set input queue to <size> Mbytes. Default 64 Mbytes -write-queue <size> Set output queue to <size> Mbytes. Default 512 Mbytes -fragment-queue <size> Set fragment queue to <size> Mbytes. Default 64 Mbytes Miscellaneous options: -root-owned alternative name for -all-root -noInodeCompression alternative name for -noI -noDataCompression alternative name for -noD -noFragmentCompression alternative name for -noF -noXattrCompression alternative name for -noX Compressors available and compressor specific options: gzip (no options) (default) lzo (no options) xz -Xbcj filter1,filter2,...,filterN Compress using filter1,filter2,...,filterN in turn (in addition to no filter), and choose the best compression. Available filters: x86, arm, armthumb, powerpc, sparc, ia64 -Xdict-size <dict-size> Use <dict-size> as the XZ dictionary size. The dictionary size can be specified as a percentage of the block size, or as an absolute value. The dictionary size must be less than or equal to the block size and 8192 bytes or larger. It must also be storable in the xz header as either 2^n or as 2^n+2^(n+1). Example dict-sizes are 75%, 50%, 37.5%, 25%, or 32K, 16K, 8K etc. Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. 3.2 Changing compression algorithm and compression specific options ------------------------------------------------------------------- By default Mksquashfs will compress using the gzip compression algorithm. This algorithm offers a good trade-off between compression ratio, and memory and time taken to decompress. Squashfs also supports LZO and XZ (LZMA2) compression. LZO offers worse compression ratio than gzip, but is faster to decompress. XZ offers better compression ratio than gzip, but at the expense of greater memory and time to decompress (and significantly more time to compress). If you're not building the squashfs-tools and kernel from source, then the tools and kernel may or may not have been built with support for LZO or XZ compression. The compression algorithms supported by the build of Mksquashfs can be found by typing mksquashfs without any arguments. The compressors available are displayed at the end of the help message, e.g. Compressors available and compressor specific options: gzip (no options) (default) lzo (no options) xz -Xbcj filter1,filter2,...,filterN Compress using filter1,filter2,...,filterN in turn (in addition to no filter), and choose the best compression. Available filters: x86, arm, armthumb, powerpc, sparc, ia64 -Xdict-size <dict-size> Use <dict-size> as the XZ dictionary size. The dictionary size can be specified as a percentage of the block size, or as an absolute value. The dictionary size must be less than or equal to the block size and 8192 bytes or larger. It must also be storable in the xz header as either 2^n or as 2^n+2^(n+1). Example dict-sizes are 75%, 50%, 37.5%, 25%, or 32K, 16K, 8K etc. If the compressor offers compression specific options then these options are also displayed (.i.e. in the above XZ is shown with two compression specific options). 3.3 Changing global compression defaults used in mksquashfs ----------------------------------------------------------- There are a large number of options that can be used to control the compression in mksquashfs. By and large the defaults are the most optimum settings and should only be changed in exceptional circumstances! The -noI, -noD and -noF options (also -noInodeCompression, -noDataCompression and -noFragmentCompression) can be used to force mksquashfs to not compress inodes/directories, data and fragments respectively. Giving all options generates an uncompressed filesystem. The -no-fragments tells mksquashfs to not generate fragment blocks, and rather generate a filesystem similar to a Squashfs 1.x filesystem. It will of course still be a Squashfs 3.1 filesystem but without fragments, and so it won't be mountable on a Squashfs 1.x system. The -always-use-fragments option tells mksquashfs to always generate fragments for files irrespective of the file length. By default only small files less than the block size are packed into fragment blocks. The ends of files which do not fit fully into a block, are NOT by default packed into fragments. To illustrate this, a 100K file has an initial 64K block and a 36K remainder. This 36K remainder is not packed into a fragment by default. This is because to do so leads to a 10 - 20% drop in sequential I/O performance, as a disk head seek is needed to seek to the initial file data and another disk seek is need to seek to the fragment block. Specify this option if you want file remainders to be packed into fragment blocks. Doing so may increase the compression obtained BUT at the expense of I/O speed. The -no-duplicates option tells mksquashfs to not check the files being added to the filesystem for duplicates. This can result in quicker filesystem generation and appending although obviously compression will suffer badly if there is a lot of duplicate files. The -b option allows the block size to be selected, both "K" and "M" postfixes are supported, this can be either 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K or 1M bytes. 3.4 Specifying the UIDs/GIDs used in the filesystem --------------------------------------------------- By default files in the generated filesystem inherit the UID and GID ownership of the original file. However, mksquashfs provides a number of options which can be used to override the ownership. The options -all-root and -root-owned (both do exactly the same thing) force all file uids/gids in the generated Squashfs filesystem to be root. This allows root owned filesystems to be built without root access on the host machine. The "-force-uid uid" option forces all files in the generated Squashfs filesystem to be owned by the specified uid. The uid can be specified either by name (i.e. "root") or by number. The "-force-gid gid" option forces all files in the generated Squashfs filesystem to be group owned by the specified gid. The gid can be specified either by name (i.e. "root") or by number. 3.5 Excluding files from the filesystem --------------------------------------- The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. Two styles of exclude file matching are supported: basic exclude matching, and extended wildcard matching. Basic exclude matching is a legacy feature retained for backwards compatibility with earlier versions of Mksquashfs. Extended wildcard matching should be used in preference. 3.5.1 Basic exclude matching Each exclude file is treated as an exact match of a file/directory in the source directories. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. 3.5.2 Extended exclude file handling Extended exclude file matching treats each exclude file as a wildcard or regex expression. To enable wildcard matching specify the -wildcards option, and to enable regex matching specify the -regex option. In most cases the -wildcards option should be used rather than -regex because wildcard matching behaviour is significantly easier to understand! In addition to wildcards/regex expressions, exclude files can be "anchored" or "non-anchored". An anchored exclude is one which matches from the root of the directory and nowhere else, a non-anchored exclude matches anywhere. For example given the directory hierarchy "a/b/c/a/b", the anchored exclude "a/b" will match "a/b" at the root of the directory hierarchy, but it will not match the "/a/b" sub-directory within directory "c", whereas a non-anchored exclude would. A couple of examples should make this clearer. Anchored excludes 1. mksquashfs example image.sqsh -wildcards -e 'test/*.gz' Exclude all files matching "*.gz" in the top level directory "test". 2. mksquashfs example image.sqsh -wildcards -e '*/[Tt]est/example*' Exclude all files beginning with "example" inside directories called "Test" or "test", that occur inside any top level directory. Using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e 'test/!(*data*).gz' Exclude all files matching "*.gz" in top level directory "test", except those with "data" in the name. Non-anchored excludes By default excludes match from the top level directory, but it is often useful to exclude a file matching anywhere in the source directories. For this non-anchored excludes can be used, specified by pre-fixing the exclude with "...". Examples: 1. mksquashfs example image.sqsh -wildcards -e '... *.gz' Exclude files matching "*.gz" anywhere in the source directories. For example this will match "example.gz", "test/example.gz", and "test/test/example.gz". 2. mksquashfs example image.sqsh -wildcards -e '... [Tt]est/*.gz' Exclude files matching "*.gz" inside directories called "Test" or "test" that occur anywhere in the source directories. Again, using extended wildcards, negative matching is also possible. 3. mksquashfs example image.sqsh -wildcards -e '... !(*data*).gz' Exclude all files matching "*.gz" anywhere in the source directories, except those with "data" in the name. 3.5.3 Exclude files summary The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. 3.6 Appending to squashfs filesystems ------------------------------------- Running squashfs with the destination directory containing an existing filesystem will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3.7 Appending recovery file feature ----------------------------------- Recovery files are created when appending to existing Squashfs filesystems. This allows the original filesystem to be recovered if Mksquashfs aborts unexpectedly (i.e. power failure). The recovery files are called squashfs_recovery_xxx_yyy, where "xxx" is the name of the filesystem being appended to, and "yyy" is a number to guarantee filename uniqueness (the PID of the parent Mksquashfs process). Normally if Mksquashfs exits correctly the recovery file is deleted to avoid cluttering the filesystem. If Mksquashfs aborts, the "-recover" option can be used to recover the filesystem, giving the previously created recovery file as a parameter, i.e. mksquashfs dummy image.sqsh -recover squashfs_recovery_image.sqsh_1234 The writing of the recovery file can be disabled by specifying the "-no-recovery" option. 3.8 Pseudo file support ----------------------- Mksquashfs supports pseudo files, these allow fake files, directories, character and block devices to be specified and added to the Squashfs filesystem being built, rather than requiring them to be present in the source directories. This, for example, allows device nodes to be added to the filesystem without requiring root access. Mksquashfs 4.1 adds support for "dynamic pseudo files" and a modify operation. Dynamic pseudo files allow files to be dynamically created when Mksquashfs is run, their contents being the result of running a command or piece of shell script. The modifiy operation allows the mode/uid/gid of an existing file in the source filesystem to be modified. Two Mksquashfs options are supported, -p allows one pseudo file to be specified on the command line, and -pf allows a pseudo file to be specified containing a list of pseduo definitions, one per line. Pseudo operations ----------------- 3.8.1. Creating a dynamic file -------------------------- Pseudo definition Filename f mode uid gid command mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. command can be an executable or a piece of shell script, and it is executed by running "/bin/sh -c command". The stdout becomes the contents of "Filename". Examples: Running a basic command ----------------------- /somedir/dmesg f 444 root root dmesg creates a file "/somedir/dmesg" containing the output from dmesg. Executing shell script ---------------------- RELEASE f 444 root root \ if [ ! -e /tmp/ver ]; then \ echo 0 > /tmp/ver; \ fi; \ ver=`cat /tmp/ver`; \ ver=$((ver +1)); \ echo $ver > /tmp/ver; \ echo -n `cat /tmp/release`; \ echo "-dev #"$ver `date` "Build host" `hostname` Creates a file RELEASE containing the release name, date, build host, and an incrementing version number. The incrementing version is a side-effect of executing the shell script, and ensures every time Mksquashfs is run a new version number is used without requiring any other shell scripting. The above example also shows that commands can be split across multiple lines using "\". Obviously as the script will be presented to the shell as a single line, a semicolon is need to separate individual shell commands within the shell script. Reading from a device (or fifo/named socket) -------------------------------------------- input f 444 root root dd if=/dev/sda1 bs=1024 count=10 Copies 10K from the device /dev/sda1 into the file input. Ordinarily Mksquashfs given a device, fifo, or named socket will place that special file within the Squashfs filesystem, the above allows input from these special files to be captured and placed in the Squashfs filesystem. 3.8.2. Creating a block or character device --------------------------------------- Pseudo definition Filename type mode uid gid major minor Where type is either b - for block devices, and c - for character devices mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: /dev/chr_dev c 666 root root 100 1 /dev/blk_dev b 666 0 0 200 200 creates a character device "/dev/chr_dev" with major:minor 100:1 and a block device "/dev/blk_dev" with major:minor 200:200, both with root uid/gid and a mode of rw-rw-rw. 3.8.3. Creating a directory ----------------------- Pseudo definition Filename d mode uid gid mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: /pseudo_dir d 666 root root creates a directory "/pseudo_dir" with root uid/gid and mode of rw-rw-rw. 4.8.4. Modifying attributes of an existing file ------------------------------------------- Pseudo definition Filename m mode uid gid mode is the octal mode specifier, similar to that expected by chmod. uid and gid can be either specified as a decimal number, or by name. For example: dmesg m 666 root root Changes the attributes of the file "dmesg" in the filesystem to have root uid/gid and a mode of rw-rw-rw, overriding the attributes obtained from the source filesystem. 3.9 Miscellaneous options ------------------------- The -info option displays the files/directories as they are compressed and added to the filesystem. The original uncompressed size of each file is printed, along with DUPLICATE if the file is a duplicate of a file in the filesystem. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 4. UNSQUASHFS ------------- Unsquashfs allows you to decompress and extract a Squashfs filesystem without mounting it. It can extract the entire filesystem, or a specific file or directory. The Unsquashfs usage info is: SYNTAX: unsquashfs [options] filesystem [directories or files to extract] -v[ersion] print version, licence and copyright information -d[est] <pathname> unsquash to <pathname>, default "squashfs-root" -n[o-progress] don't display the progress bar -no[-xattrs] don't extract xattrs in file system -x[attrs] extract xattrs in file system (default) -p[rocessors] <number> use <number> processors. By default will use number of processors available -i[nfo] print files as they are unsquashed -li[nfo] print files as they are unsquashed with file attributes (like ls -l output) -l[s] list filesystem, but don't unsquash -ll[s] list filesystem with file attributes (like ls -l output), but don't unsquash -f[orce] if file already exists then overwrite -s[tat] display filesystem superblock information -e[f] <extract file> list of directories or files to extract. One per line -da[ta-queue] <size> Set data queue to <size> Mbytes. Default 256 Mbytes -fr[ag-queue] <size> Set fagment queue to <size> Mbytes. Default 256 Mbytes -r[egex] treat extract names as POSIX regular expressions rather than use the default shell wildcard expansion (globbing) Decompressors available: gzip lzma xz To extract a subset of the filesystem, the filenames or directory trees that are to be extracted can be specified on the command line. The files/directories should be specified using the full path to the files/directories as they appear within the Squashfs filesystem. The files/directories will also be extracted to those positions within the specified destination directory. The extract files can also be given in a file using the "-e[f]" option. Similarly to Mksquashfs, wildcard matching is performed on the extract files. Wildcard matching is enabled by default. Examples: 1. unsquashfs image.sqsh 'test/*.gz' Extract all files matching "*.gz" in the top level directory "test". 2. unsquashfs image.sqsh '[Tt]est/example*' Extract all files beginning with "example" inside top level directories called "Test" or "test". Using extended wildcards, negative matching is also possible. 3. unsquashfs image.sqsh 'test/!(*data*).gz' Extract all files matching "*.gz" in top level directory "test", except those with "data" in the name. 4.1 Unsquashfs options ---------------------- The "-ls" option can be used to list the contents of a filesystem without decompressing the filesystem data itself. The "-lls" option is similar but it also displays file attributes (ls -l style output). The "-info" option forces Unsquashfs to print each file as it is decompressed. The -"linfo" is similar but it also displays file attributes. The "-dest" option specifies the directory that is used to decompress the filesystem data. If this option is not given then the filesystem is decompressed to the directory "squashfs-root" in the current working directory. The "-force" option forces Unsquashfs to output to the destination directory even if files or directories already exist. This allows you to update an existing directory tree, or to Unsquashfs to a partially filled directory. Without the "-force" option, Unsquashfs will refuse to overwrite any existing files, or to create any directories if they already exist. This is done to protect data in case of mistakes, and so the "-force" option should be used with caution. The "-stat" option displays filesystem superblock information. This is useful to discover the filesystem version, byte ordering, whether it has a NFS export table, and what options were used to compress the filesystem, etc. Unsquashfs can decompress all Squashfs filesystem versions, 1.x, 2.x and 3.x filesystems. 5. FILESYSTEM LAYOUT -------------------- A squashfs filesystem consists of a maximum of nine parts, packed together on a byte alignment: --------------- | superblock | |---------------| | compression | | options | |---------------| | datablocks | | & fragments | |---------------| | inode table | |---------------| | directory | | table | |---------------| | fragment | | table | |---------------| | export | | table | |---------------| | uid/gid | | lookup table | |---------------| | xattr | | table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory, fragment, export and uid/gid lookup tables are written. 5.1 Compression options ----------------------- Compressors can optionally support compression specific options (e.g. dictionary size). If non-default compression options have been used, then these are stored here. 5.2 Inodes ---------- Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. Inodes are identified by a 48-bit number which encodes the location of the compressed metadata block containing the inode, and the byte offset into that block where the inode is placed (<block, offset>). To maximise compression there are different inodes for each file type (regular file, directory, device, etc.), the inode contents and length varying with the type. To further maximise compression, two types of regular file inode and directory inode are defined: inodes optimised for frequently occurring regular files and directories, and extended types where extra information has to be stored. 5.3 Directories --------------- Like inodes, directories are packed into compressed metadata blocks, stored in a directory table. Directories are accessed using the start address of the metablock containing the directory and the offset into the decompressed block (<block, offset>). Directories are organised in a slightly complex way, and are not simply a list of file names. The organisation takes advantage of the fact that (in most cases) the inodes of the files will be in the same compressed metadata block, and therefore, can share the start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. Directories are sorted, and can contain a directory index to speed up file lookup. Directory indexes store one entry per metablock, each entry storing the index/filename mapping to the first directory header in each metadata block. Directories are sorted in alphabetical order, and at lookup the index is scanned linearly looking for the first filename alphabetically larger than the filename being looked up. At this point the location of the metadata block the filename is in has been found. The general idea of the index is ensure only one metadata block needs to be decompressed to do a lookup irrespective of the length of the directory. This scheme has the advantage that it doesn't require extra memory overhead and doesn't require much extra storage on disk. 5.4 File data ------------- Regular files consist of a sequence of contiguous compressed blocks, and/or a compressed fragment block (tail-end packed block). The compressed size of each datablock is stored in a block list contained within the file inode. To speed up access to datablocks when reading 'large' files (256 Mbytes or larger), the code implements an index cache that caches the mapping from block index to datablock location on disk. The index cache allows Squashfs to handle large files (up to 1.75 TiB) while retaining a simple and space-efficient block list on disk. The cache is split into slots, caching up to eight 224 GiB files (128 KiB blocks). Larger files use multiple slots, with 1.75 TiB files using all 8 slots. The index cache is designed to be memory efficient, and by default uses 16 KiB. 5.5 Fragment lookup table ------------------------- Regular files can contain a fragment index which is mapped to a fragment location on disk and compressed size using a fragment lookup table. This fragment lookup table is itself stored compressed into metadata blocks. A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. 5.6 Uid/gid lookup table ------------------------ For space efficiency regular files store uid and gid indexes, which are converted to 32-bit uids/gids using an id look up table. This table is stored compressed into metadata blocks. A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. 5.7 Export table ---------------- To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems can optionally (disabled with the -no-exports Mksquashfs option) contain an inode number to inode disk location lookup table. This is required to enable Squashfs to map inode numbers passed in filehandles to the inode location on disk, which is necessary when the export code reinstantiates expired/flushed inodes. This table is stored compressed into metadata blocks. A second index table is used to locate these. This second index table for speed of access (and because it is small) is read at mount time and cached in memory. 5.8 Xattr table --------------- The xattr table contains extended attributes for each inode. The xattrs for each inode are stored in a list, each list entry containing a type, name and value field. The type field encodes the xattr prefix ("user.", "trusted." etc) and it also encodes how the name/value fields should be interpreted. Currently the type indicates whether the value is stored inline (in which case the value field contains the xattr value), or if it is stored out of line (in which case the value field stores a reference to where the actual value is stored). This allows large values to be stored out of line improving scanning and lookup performance and it also allows values to be de-duplicated, the value being stored once, and all other occurences holding an out of line reference to that value. The xattr lists are packed into compressed 8K metadata blocks. To reduce overhead in inodes, rather than storing the on-disk location of the xattr list inside each inode, a 32-bit xattr id is stored. This xattr id is mapped into the location of the xattr list using a second xattr id lookup table. 6. AUTHOR INFO -------------- Squashfs was written by Phillip Lougher, email phillip@lougher.demon.co.uk, in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback! ================================================ FILE: src/others/squashfs-4.2/README-4.2 ================================================ SQUASHFS 4.2 - A squashed read-only filesystem for Linux Copyright 2002-2011 Phillip Lougher <phillip@lougher.demon.co.uk> Released under the GPL licence (version 2 or later). Welcome to Squashfs 4.2. This is a tools only release, support for Squashfs filesystems is in mainline (2.6.29 and later). New features in Squashfs-tools 4.2 ---------------------------------- 1. Support for XZ compression 2. Support for compressor specific options Compatiblity ------------ Mksquashfs 4.2 generates 4.0 filesystems. These filesystems are fully compatible/interchangable with filesystems generated by Mksquashfs 4.0 and are mountable on 2.6.29 and later kernels. XZ compression -------------- Squashfs now supports XZ compression. XZ support is in 2.6.38 and newer kernels. New Mksquashfs options ---------------------- -X<compressor-option> Compression algorithms can now support compression specific options. These options are prefixed by -X, and are passed to the compressor for handling. The compression specific options supported by each compressor can be found by typing mksquashfs without any arguments. They are displayed at the end of the help message, e.g. Compressors available and compressor specific options: gzip (no options) (default) lzo (no options) xz -Xbcj filter1,filter2,...,filterN Compress using filter1,filter2,...,filterN in turn (in addition to no filter), and choose the best compression. Available filters: x86, arm, armthumb, powerpc, sparc, ia64 -Xdict-size <dict-size> Use <dict-size> as the XZ dictionary size. The dictionary size can be specified as a percentage of the block size, or as an absolute value. The dictionary size must be less than or equal to the block size and 8192 bytes or larger. It must also be storable in the xz header as either 2^n or as 2^n+2^(n+1). Example dict-sizes are 75%, 50%, 37.5%, 25%, or 32K, 16K, 8K etc. ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/.built ================================================ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/.built_check ================================================ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/.configured ================================================ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/.prepared1a23cc84ca172080ca2c2f332cb31052 ================================================ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/.prepared1a23cc84ca172080ca2c2f332cb31052_check ================================================ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/7zC.txt ================================================ 7z ANSI-C Decoder 4.62 ---------------------- 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- 7z ANSI-C Decoder is part of the LZMA SDK. LZMA SDK is written and placed in the public domain by Igor Pavlov. Files --------------------- 7zDecode.* - Low level 7z decoding 7zExtract.* - High level 7z decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ILookInStream interface */ CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call CrcGenerateTable(); function to initialize CRC structures. 3) call SzArEx_Init(&db); function to initialize db structures. 4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CFileItem *f = db.db.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzAr_Extract( CArchiveDatabaseEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - LastWriteTime (8 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these temprorary buffers can be about 15% of solid block size. 7z Decoder doesn't allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. Defines ------- _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles for (;;) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zBuf.c ================================================ /* 7zBuf.c -- Byte Buffer 2008-03-28 Igor Pavlov Public domain */ #include "7zBuf.h" void Buf_Init(CBuf *p) { p->data = 0; p->size = 0; } int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) { p->size = 0; if (size == 0) { p->data = 0; return 1; } p->data = (Byte *)alloc->Alloc(alloc, size); if (p->data != 0) { p->size = size; return 1; } return 0; } void Buf_Free(CBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zBuf.h ================================================ /* 7zBuf.h -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_BUF_H #define __7Z_BUF_H #include "Types.h" typedef struct { Byte *data; size_t size; } CBuf; void Buf_Init(CBuf *p); int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); void Buf_Free(CBuf *p, ISzAlloc *alloc); typedef struct { Byte *data; size_t size; size_t pos; } CDynBuf; void DynBuf_Construct(CDynBuf *p); void DynBuf_SeekToBeg(CDynBuf *p); int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zBuf2.c ================================================ /* 7zBuf2.c -- Byte Buffer 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "7zBuf.h" void DynBuf_Construct(CDynBuf *p) { p->data = 0; p->size = 0; p->pos = 0; } void DynBuf_SeekToBeg(CDynBuf *p) { p->pos = 0; } int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) { if (size > p->size - p->pos) { size_t newSize = p->pos + size; Byte *data; newSize += newSize / 4; data = (Byte *)alloc->Alloc(alloc, newSize); if (data == 0) return 0; p->size = newSize; memcpy(data, p->data, p->pos); alloc->Free(alloc, p->data); p->data = data; } memcpy(p->data + p->pos, buf, size); p->pos += size; return 1; } void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) { alloc->Free(alloc, p->data); p->data = 0; p->size = 0; p->pos = 0; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zCrc.c ================================================ /* 7zCrc.c -- CRC32 calculation 2008-08-05 Igor Pavlov Public domain */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void MY_FAST_CALL CrcGenerateTable(void) { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); g_CrcTable[i] = r; } } UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) { const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = CRC_UPDATE_BYTE(v, *p); return v; } UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) { return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zCrc.h ================================================ /* 7zCrc.h -- CRC32 calculation 2008-03-13 Igor Pavlov Public domain */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "Types.h" extern UInt32 g_CrcTable[]; void MY_FAST_CALL CrcGenerateTable(void); #define CRC_INIT_VAL 0xFFFFFFFF #define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zFile.c ================================================ /* 7zFile.c -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #include "7zFile.h" #ifndef USE_WINDOWS_FILE #include <errno.h> #endif #ifdef USE_WINDOWS_FILE /* ReadFile and WriteFile functions in Windows have BUG: If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES (Insufficient system resources exist to complete the requested service). Probably in some version of Windows there are problems with other sizes: for 32 MB (maybe also for 16 MB). And message can be "Network connection was lost" */ #define kChunkSizeMax (1 << 22) #endif void File_Construct(CSzFile *p) { #ifdef USE_WINDOWS_FILE p->handle = INVALID_HANDLE_VALUE; #else p->file = NULL; #endif } static WRes File_Open(CSzFile *p, const char *name, int writeMode) { #ifdef USE_WINDOWS_FILE p->handle = CreateFileA(name, writeMode ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, writeMode ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); #else p->file = fopen(name, writeMode ? "wb+" : "rb"); return (p->file != 0) ? 0 : errno; #endif } WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } WRes File_Close(CSzFile *p) { #ifdef USE_WINDOWS_FILE if (p->handle != INVALID_HANDLE_VALUE) { if (!CloseHandle(p->handle)) return GetLastError(); p->handle = INVALID_HANDLE_VALUE; } #else if (p->file != NULL) { int res = fclose(p->file); if (res != 0) return res; p->file = NULL; } #endif return 0; } WRes File_Read(CSzFile *p, void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fread(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Write(CSzFile *p, const void *data, size_t *size) { size_t originalSize = *size; if (originalSize == 0) return 0; #ifdef USE_WINDOWS_FILE *size = 0; do { DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; DWORD processed = 0; BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); data = (void *)((Byte *)data + processed); originalSize -= processed; *size += processed; if (!res) return GetLastError(); if (processed == 0) break; } while (originalSize > 0); return 0; #else *size = fwrite(data, 1, originalSize, p->file); if (*size == originalSize) return 0; return ferror(p->file); #endif } WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) { #ifdef USE_WINDOWS_FILE LARGE_INTEGER value; DWORD moveMethod; value.LowPart = (DWORD)*pos; value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ switch (origin) { case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; case SZ_SEEK_END: moveMethod = FILE_END; break; default: return ERROR_INVALID_PARAMETER; } value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) { WRes res = GetLastError(); if (res != NO_ERROR) return res; } *pos = ((Int64)value.HighPart << 32) | value.LowPart; return 0; #else int moveMethod; int res; switch (origin) { case SZ_SEEK_SET: moveMethod = SEEK_SET; break; case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; case SZ_SEEK_END: moveMethod = SEEK_END; break; default: return 1; } res = fseek(p->file, (long)*pos, moveMethod); *pos = ftell(p->file); return res; #endif } WRes File_GetLength(CSzFile *p, UInt64 *length) { #ifdef USE_WINDOWS_FILE DWORD sizeHigh; DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) { DWORD res = GetLastError(); if (res != NO_ERROR) return res; } *length = (((UInt64)sizeHigh) << 32) + sizeLow; return 0; #else long pos = ftell(p->file); int res = fseek(p->file, 0, SEEK_END); *length = ftell(p->file); fseek(p->file, pos, SEEK_SET); return res; #endif } /* ---------- FileSeqInStream ---------- */ static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) { CFileSeqInStream *p = (CFileSeqInStream *)pp; return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; } void FileSeqInStream_CreateVTable(CFileSeqInStream *p) { p->s.Read = FileSeqInStream_Read; } /* ---------- FileInStream ---------- */ static SRes FileInStream_Read(void *pp, void *buf, size_t *size) { CFileInStream *p = (CFileInStream *)pp; return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; } static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) { CFileInStream *p = (CFileInStream *)pp; return File_Seek(&p->file, pos, origin); } void FileInStream_CreateVTable(CFileInStream *p) { p->s.Read = FileInStream_Read; p->s.Seek = FileInStream_Seek; } /* ---------- FileOutStream ---------- */ static size_t FileOutStream_Write(void *pp, const void *data, size_t size) { CFileOutStream *p = (CFileOutStream *)pp; File_Write(&p->file, data, &size); return size; } void FileOutStream_CreateVTable(CFileOutStream *p) { p->s.Write = FileOutStream_Write; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zFile.h ================================================ /* 7zFile.h -- File IO 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_FILE_H #define __7Z_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE #endif #ifdef USE_WINDOWS_FILE #include <windows.h> #else #include <stdio.h> #endif #include "Types.h" /* ---------- File ---------- */ typedef struct { #ifdef USE_WINDOWS_FILE HANDLE handle; #else FILE *file; #endif } CSzFile; void File_Construct(CSzFile *p); WRes InFile_Open(CSzFile *p, const char *name); WRes OutFile_Open(CSzFile *p, const char *name); WRes File_Close(CSzFile *p); /* reads max(*size, remain file's size) bytes */ WRes File_Read(CSzFile *p, void *data, size_t *size); /* writes *size bytes */ WRes File_Write(CSzFile *p, const void *data, size_t *size); WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); WRes File_GetLength(CSzFile *p, UInt64 *length); /* ---------- FileInStream ---------- */ typedef struct { ISeqInStream s; CSzFile file; } CFileSeqInStream; void FileSeqInStream_CreateVTable(CFileSeqInStream *p); typedef struct { ISeekInStream s; CSzFile file; } CFileInStream; void FileInStream_CreateVTable(CFileInStream *p); typedef struct { ISeqOutStream s; CSzFile file; } CFileOutStream; void FileOutStream_CreateVTable(CFileOutStream *p); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zStream.c ================================================ /* 7zStream.c -- 7z Stream functions 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "Types.h" SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) { return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) { size_t processed = 1; RINOK(stream->Read(stream, buf, &processed)); return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; } SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) { Int64 t = offset; return stream->Seek(stream, &t, SZ_SEEK_SET); } SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) { void *lookBuf; if (*size == 0) return SZ_OK; RINOK(stream->Look(stream, &lookBuf, size)); memcpy(buf, lookBuf, *size); return stream->Skip(stream, *size); } SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) { while (size != 0) { size_t processed = size; RINOK(stream->Read(stream, buf, &processed)); if (processed == 0) return errorType; buf = (void *)((Byte *)buf + processed); size -= processed; } return SZ_OK; } SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) { return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); } static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; size2 = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, &size2); p->size = size2; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) { SRes res = SZ_OK; CLookToRead *p = (CLookToRead *)pp; size_t size2 = p->size - p->pos; if (size2 == 0 && *size > 0) { p->pos = 0; if (*size > LookToRead_BUF_SIZE) *size = LookToRead_BUF_SIZE; res = p->realStream->Read(p->realStream, p->buf, size); size2 = p->size = *size; } if (size2 < *size) *size = size2; *buf = p->buf + p->pos; return res; } static SRes LookToRead_Skip(void *pp, size_t offset) { CLookToRead *p = (CLookToRead *)pp; p->pos += offset; return SZ_OK; } static SRes LookToRead_Read(void *pp, void *buf, size_t *size) { CLookToRead *p = (CLookToRead *)pp; size_t rem = p->size - p->pos; if (rem == 0) return p->realStream->Read(p->realStream, buf, size); if (rem > *size) rem = *size; memcpy(buf, p->buf + p->pos, rem); p->pos += rem; *size = rem; return SZ_OK; } static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) { CLookToRead *p = (CLookToRead *)pp; p->pos = p->size = 0; return p->realStream->Seek(p->realStream, pos, origin); } void LookToRead_CreateVTable(CLookToRead *p, int lookahead) { p->s.Look = lookahead ? LookToRead_Look_Lookahead : LookToRead_Look_Exact; p->s.Skip = LookToRead_Skip; p->s.Read = LookToRead_Read; p->s.Seek = LookToRead_Seek; } void LookToRead_Init(CLookToRead *p) { p->pos = p->size = 0; } static SRes SecToLook_Read(void *pp, void *buf, size_t *size) { CSecToLook *p = (CSecToLook *)pp; return LookInStream_LookRead(p->realStream, buf, size); } void SecToLook_CreateVTable(CSecToLook *p) { p->s.Read = SecToLook_Read; } static SRes SecToRead_Read(void *pp, void *buf, size_t *size) { CSecToRead *p = (CSecToRead *)pp; return p->realStream->Read(p->realStream, buf, size); } void SecToRead_CreateVTable(CSecToRead *p) { p->s.Read = SecToRead_Read; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/7zVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT ": Igor Pavlov : Public domain" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Alloc.c ================================================ /* Alloc.c -- Memory allocation functions 2008-09-24 Igor Pavlov Public domain */ #ifdef _WIN32 #include <windows.h> #endif #include <stdlib.h> #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG { void *p = malloc(size); fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); return p; } #else return malloc(size); #endif } void MyFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); #endif free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #ifndef MEM_LARGE_PAGES #undef _7ZIP_LARGE_PAGES #endif #ifdef _7ZIP_LARGE_PAGES SIZE_T g_LargePageSize = 0; typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); #endif void SetLargePageSize() { #ifdef _7ZIP_LARGE_PAGES SIZE_T size = 0; GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return; size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return; g_LargePageSize = size; #endif } void *BigAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) { void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } #endif return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Alloc.h ================================================ /* Alloc.h -- Memory allocation functions 2008-03-13 Igor Pavlov Public domain */ #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size); void MyFree(void *address); #ifdef _WIN32 void SetLargePageSize(); void *MidAlloc(size_t size); void MidFree(void *address); void *BigAlloc(size_t size); void BigFree(void *address); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FAs /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z - Win32 Release" # Name "7z - Win32 Debug" # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\7zBuf.c # End Source File # Begin Source File SOURCE=..\..\7zBuf.h # End Source File # Begin Source File SOURCE=..\..\7zCrc.c # End Source File # Begin Source File SOURCE=..\..\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\7zFile.c # End Source File # Begin Source File SOURCE=..\..\7zFile.h # End Source File # Begin Source File SOURCE=..\..\7zStream.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.c # End Source File # Begin Source File SOURCE=..\..\Bcj2.h # End Source File # Begin Source File SOURCE=..\..\Bra.h # End Source File # Begin Source File SOURCE=..\..\Bra86.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\Types.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z"=.\7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zAlloc.c ================================================ /* 7zAlloc.c -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(void *p, size_t size) { p = p; if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *p, void *address) { p = p; #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zAlloc.h ================================================ /* 7zAlloc.h -- Allocation functions 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> void *SzAlloc(void *p, size_t size); void SzFree(void *p, void *address); void *SzAllocTemp(void *p, size_t size); void SzFreeTemp(void *p, void *address); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zDecode.c ================================================ /* 7zDecode.c -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #include <string.h> #include "../../Bcj2.h" #include "../../Bra.h" #include "../../LzmaDec.h" #include "7zDecode.h" #define k_Copy 0 #define k_LZMA 0x30101 #define k_BCJ 0x03030103 #define k_BCJ2 0x0303011B static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzmaDec state; SRes res = SZ_OK; LzmaDec_Construct(&state); RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); state.dic = outBuffer; state.dicBufSize = outSize; LzmaDec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; ELzmaStatus status; res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) { if (state.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } LzmaDec_FreeProbs(&state, allocMain); return res; } static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) { while (inSize > 0) { void *inBuf; size_t curSize = (1 << 18); if (curSize > inSize) curSize = (size_t)inSize; RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); if (curSize == 0) return SZ_ERROR_INPUT_EOF; memcpy(outBuffer, inBuf, curSize); outBuffer += curSize; inSize -= curSize; RINOK(inStream->Skip((void *)inStream, curSize)); } return SZ_OK; } #define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) #define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) #define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) SRes CheckSupportedFolder(const CSzFolder *f) { if (f->NumCoders < 1 || f->NumCoders > 4) return SZ_ERROR_UNSUPPORTED; if (IS_UNSUPPORTED_CODER(f->Coders[0])) return SZ_ERROR_UNSUPPORTED; if (f->NumCoders == 1) { if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 2) { if (IS_NO_BCJ(f->Coders[1]) || f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 1 || f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } if (f->NumCoders == 4) { if (IS_UNSUPPORTED_CODER(f->Coders[1]) || IS_UNSUPPORTED_CODER(f->Coders[2]) || IS_NO_BCJ2(f->Coders[3])) return SZ_ERROR_UNSUPPORTED; if (f->NumPackStreams != 4 || f->PackStreams[0] != 2 || f->PackStreams[1] != 6 || f->PackStreams[2] != 1 || f->PackStreams[3] != 0 || f->NumBindPairs != 3 || f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) return SZ_ERROR_UNSUPPORTED; return SZ_OK; } return SZ_ERROR_UNSUPPORTED; } UInt64 GetSum(const UInt64 *values, UInt32 index) { UInt64 sum = 0; UInt32 i; for (i = 0; i < index; i++) sum += values[i]; return sum; } SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *tempBuf[]) { UInt32 ci; SizeT tempSizes[3] = { 0, 0, 0}; SizeT tempSize3 = 0; Byte *tempBuf3 = 0; RINOK(CheckSupportedFolder(folder)); for (ci = 0; ci < folder->NumCoders; ci++) { CSzCoderInfo *coder = &folder->Coders[ci]; if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) { UInt32 si = 0; UInt64 offset; UInt64 inSize; Byte *outBufCur = outBuffer; SizeT outSizeCur = outSize; if (folder->NumCoders == 4) { UInt32 indices[] = { 3, 2, 0 }; UInt64 unpackSize = folder->UnpackSizes[ci]; si = indices[ci]; if (ci < 2) { Byte *temp; outSizeCur = (SizeT)unpackSize; if (outSizeCur != unpackSize) return SZ_ERROR_MEM; temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); if (temp == 0 && outSizeCur != 0) return SZ_ERROR_MEM; outBufCur = tempBuf[1 - ci] = temp; tempSizes[1 - ci] = outSizeCur; } else if (ci == 2) { if (unpackSize > outSize) /* check it */ return SZ_ERROR_PARAM; tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); tempSize3 = outSizeCur = (SizeT)unpackSize; } else return SZ_ERROR_UNSUPPORTED; } offset = GetSum(packSizes, si); inSize = packSizes[si]; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); if (coder->MethodID == k_Copy) { if (inSize != outSizeCur) /* check it */ return SZ_ERROR_DATA; RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); } else { RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); } } else if (coder->MethodID == k_BCJ) { UInt32 state; if (ci != 1) return SZ_ERROR_UNSUPPORTED; x86_Convert_Init(state); x86_Convert(outBuffer, outSize, 0, &state, 0); } else if (coder->MethodID == k_BCJ2) { UInt64 offset = GetSum(packSizes, 1); UInt64 s3Size = packSizes[1]; SRes res; if (ci != 3) return SZ_ERROR_UNSUPPORTED; RINOK(LookInStream_SeekTo(inStream, startPos + offset)); tempSizes[2] = (SizeT)s3Size; if (tempSizes[2] != s3Size) return SZ_ERROR_MEM; tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); if (tempBuf[2] == 0 && tempSizes[2] != 0) return SZ_ERROR_MEM; res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); RINOK(res) res = Bcj2_Decode( tempBuf3, tempSize3, tempBuf[0], tempSizes[0], tempBuf[1], tempSizes[1], tempBuf[2], tempSizes[2], outBuffer, outSize); RINOK(res) } else return SZ_ERROR_UNSUPPORTED; } return SZ_OK; } SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *inStream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) { Byte *tempBuf[3] = { 0, 0, 0}; int i; SRes res = SzDecode2(packSizes, folder, inStream, startPos, outBuffer, (SizeT)outSize, allocMain, tempBuf); for (i = 0; i < 3; i++) IAlloc_Free(allocMain, tempBuf[i]); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zDecode.h ================================================ /* 7zDecode.h -- Decoding from 7z folder 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, ILookInStream *stream, UInt64 startPos, Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zExtract.c ================================================ /* 7zExtract.c -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "7zDecode.h" #include "7zExtract.h" SRes SzAr_Extract( const CSzArEx *p, ILookInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->FileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zExtract.h ================================================ /* 7zExtract.h -- Extracting from 7z archive 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SRes SzAr_Extract( const CSzArEx *db, ILookInStream *inStream, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zHeader.c ================================================ /* 7zHeader.c -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zHeader.h ================================================ /* 7zHeader.h -- 7z Headers 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../Types.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnpackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnpackSize, k7zIdNumUnpackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCTime, k7zIdATime, k7zIdMTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zIn.c ================================================ /* 7zIn.c -- 7z Input functions 2008-12-31 : Igor Pavlov : Public domain */ #include "../../7zCrc.h" #include "../../CpuArch.h" #include "7zDecode.h" #include "7zIn.h" #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define NUM_FOLDER_CODERS_MAX 32 #define NUM_CODER_STREAMS_MAX 32 void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); p->FolderStartPackStreamIndex = 0; p->PackStreamStartPositions = 0; p->FolderStartFileIndex = 0; p->FileIndexToFolderIndexMap = 0; } void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); SzAr_Free(&p->db, alloc); SzArEx_Init(p); } /* UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CSzFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ #define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) { UInt32 startPos = 0; UInt64 startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); for (i = 0; i < p->db.NumFolders; i++) { p->FolderStartPackStreamIndex[i] = startPos; startPos += p->db.Folders[i].NumPackStreams; } MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); for (i = 0; i < p->db.NumPackStreams; i++) { p->PackStreamStartPositions[i] = startPosSize; startPosSize += p->db.PackSizes[i]; } MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); for (i = 0; i < p->db.NumFiles; i++) { CSzFileItem *file = p->db.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { p->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ for (;;) { if (folderIndex >= p->db.NumFolders) return SZ_ERROR_ARCHIVE; p->FolderStartFileIndex[folderIndex] = i; if (p->db.Folders[folderIndex].NumUnpackStreams != 0) break; folderIndex++; } } p->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) { return p->dataPos + p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) { UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; CSzFolder *folder = p->db.Folders + folderIndex; UInt64 size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) { UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; if (t < size) /* check it */ return SZ_ERROR_FAIL; size = t; } *resSize = size; return SZ_OK; } /* SRes SzReadTime(const CObjectVector<CBuf> &dataVector, CObjectVector<CSzFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for (int i = 0; i < files.Size(); i++) { CSzFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; } } return SZ_OK; } */ static int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; static SRes SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZ_ERROR_ARCHIVE; sd->Size--; *b = *sd->Data++; return SZ_OK; } static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } static SRes SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } static SRes SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } static SRes SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZ_ERROR_UNSUPPORTED; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZ_ERROR_UNSUPPORTED; *value = (UInt32)value64; return SZ_OK; } static SRes SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZ_ERROR_ARCHIVE; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } static SRes SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } static SRes SzReadArchiveProperties(CSzData *sd) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZ_ERROR_ARCHIVE; RINOK(SzSkeepData(sd)); } } static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, alloc); MY_ALLOC(Byte, *v, numItems, alloc); for (i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } static SRes SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, ISzAlloc *alloc) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); MY_ALLOC(UInt32, *digests, numItems, alloc); for (i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } static SRes SzReadPackInfo( CSzData *sd, UInt64 *dataOffset, UInt32 *numPackStreams, UInt64 **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, ISzAlloc *alloc) { UInt32 i; RINOK(SzReadNumber(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { RINOK(SzReadNumber(sd, (*packSizes) + i)); } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); for (i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } static SRes SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; } static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) { UInt32 numCoders, numBindPairs, numPackStreams, i; UInt32 numInStreams = 0, numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); if (numCoders > NUM_FOLDER_CODERS_MAX) return SZ_ERROR_UNSUPPORTED; folder->NumCoders = numCoders; MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); for (i = 0; i < numCoders; i++) SzCoderInfo_Init(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CSzCoderInfo *coder = folder->Coders + i; { unsigned idSize, j; Byte longID[15]; RINOK(SzReadByte(sd, &mainByte)); idSize = (unsigned)(mainByte & 0xF); RINOK(SzReadBytes(sd, longID, idSize)); if (idSize > sizeof(coder->MethodID)) return SZ_ERROR_UNSUPPORTED; coder->MethodID = 0; for (j = 0; j < idSize; j++) coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || coder->NumOutStreams > NUM_CODER_STREAMS_MAX) return SZ_ERROR_UNSUPPORTED; } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) return SZ_ERROR_MEM; RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += coder->NumInStreams; numOutStreams += coder->NumOutStreams; } if (numOutStreams == 0) return SZ_ERROR_UNSUPPORTED; folder->NumBindPairs = numBindPairs = numOutStreams - 1; MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); for (i = 0; i < numBindPairs; i++) { CBindPair *bp = folder->BindPairs + i; RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex)); } if (numInStreams < numBindPairs) return SZ_ERROR_UNSUPPORTED; folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); if (numPackStreams == 1) { for (i = 0; i < numInStreams ; i++) if (SzFolder_FindBindPairForInStream(folder, i) < 0) break; if (i == numInStreams) return SZ_ERROR_UNSUPPORTED; folder->PackStreams[0] = i; } else for (i = 0; i < numPackStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } static SRes SzReadUnpackInfo( CSzData *sd, UInt32 *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { UInt32 j; CSzFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } static SRes SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CSzFolder *folders, UInt32 *numUnpackStreams, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); RINOM(*unpackSizes); *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ UInt64 sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { UInt64 size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } static SRes SzReadStreamsInfo( CSzData *sd, UInt64 *dataOffset, CSzAr *p, UInt32 *numUnpackStreams, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ ISzAlloc *alloc, ISzAlloc *allocTemp) { for (;;) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZ_ERROR_UNSUPPORTED; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); break; } case k7zIdUnpackInfo: { RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZ_ERROR_UNSUPPORTED; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) { UInt32 i; for (i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CSzFileItem *file = files + i; while (pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZ_ERROR_ARCHIVE; if (pos + 2 > sd->Size) return SZ_ERROR_ARCHIVE; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZ_ERROR_ARCHIVE; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } MY_ALLOC(char, file->Name, (size_t)len, alloc); len = 0; while (2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += numAdds; } } return SZ_OK; } static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, UInt64 **unpackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ Byte **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnpackStreams = 0; UInt32 numFiles = 0; CSzFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; Byte defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReadUInt32(sd, &f->MTime.Low)); RINOK(SzReadUInt32(sd, &f->MTime.High)); } } break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->FileCRCDefined = 0; } } } return SzArEx_Fill(p, allocMain); } static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; Byte *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; } static SRes SzReadAndDecodePackedStreams2( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, CSzAr *p, UInt64 **unpackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt32 numUnpackStreams = 0; UInt64 dataStartPos; CSzFolder *folder; UInt64 unpackSize; SRes res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp, allocTemp)); dataStartPos += baseOffset; if (p->NumFolders != 1) return SZ_ERROR_ARCHIVE; folder = p->Folders; unpackSize = SzFolder_GetUnpackSize(folder); RINOK(LookInStream_SeekTo(inStream, dataStartPos)); if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) return SZ_ERROR_MEM; res = SzDecode(p->PackSizes, folder, inStream, dataStartPos, outBuffer->data, (size_t)unpackSize, allocTemp); RINOK(res); if (folder->UnpackCRCDefined) if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) return SZ_ERROR_CRC; return SZ_OK; } static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; } static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; } SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); if (res != SZ_OK) SzArEx_Free(p, allocMain); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zIn.h ================================================ /* 7zIn.h -- 7z Input functions 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" typedef struct { CSzAr db; UInt64 startPosAfterHeader; UInt64 dataPos; UInt32 *FolderStartPackStreamIndex; UInt64 *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; } CSzArEx; void SzArEx_Init(CSzArEx *p); void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); /* Errors: SZ_ERROR_NO_ARCHIVE SZ_ERROR_ARCHIVE SZ_ERROR_UNSUPPORTED SZ_ERROR_MEM SZ_ERROR_CRC SZ_ERROR_INPUT_EOF SZ_ERROR_FAIL */ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zItem.c ================================================ /* 7zItem.c -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #include "7zItem.h" void SzCoderInfo_Init(CSzCoderInfo *p) { Buf_Init(&p->Props); } void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) { Buf_Free(&p->Props, alloc); SzCoderInfo_Init(p); } void SzFolder_Init(CSzFolder *p) { p->Coders = 0; p->BindPairs = 0; p->PackStreams = 0; p->UnpackSizes = 0; p->NumCoders = 0; p->NumBindPairs = 0; p->NumPackStreams = 0; p->UnpackCRCDefined = 0; p->UnpackCRC = 0; p->NumUnpackStreams = 0; } void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { UInt32 i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); } UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) { UInt32 result = 0; UInt32 i; for (i = 0; i < p->NumCoders; i++) result += p->Coders[i].NumOutStreams; return result; } int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) { UInt32 i; for (i = 0; i < p->NumBindPairs; i++) if (p->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } UInt64 SzFolder_GetUnpackSize(CSzFolder *p) { int i = (int)SzFolder_GetNumOutStreams(p); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolder_FindBindPairForOutStream(p, i) < 0) return p->UnpackSizes[i]; /* throw 1; */ return 0; } void SzFile_Init(CSzFileItem *p) { p->HasStream = 1; p->IsDir = 0; p->IsAnti = 0; p->FileCRCDefined = 0; p->MTimeDefined = 0; p->Name = 0; } static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Name); SzFile_Init(p); } void SzAr_Init(CSzAr *p) { p->PackSizes = 0; p->PackCRCsDefined = 0; p->PackCRCs = 0; p->Folders = 0; p->Files = 0; p->NumPackStreams = 0; p->NumFolders = 0; p->NumFiles = 0; } void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { UInt32 i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); if (p->Files) for (i = 0; i < p->NumFiles; i++) SzFile_Free(&p->Files[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zItem.h ================================================ /* 7zItem.h -- 7z Items 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../7zBuf.h" typedef struct { UInt32 NumInStreams; UInt32 NumOutStreams; UInt64 MethodID; CBuf Props; } CSzCoderInfo; void SzCoderInfo_Init(CSzCoderInfo *p); void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); typedef struct { UInt32 InIndex; UInt32 OutIndex; } CBindPair; typedef struct { CSzCoderInfo *Coders; CBindPair *BindPairs; UInt32 *PackStreams; UInt64 *UnpackSizes; UInt32 NumCoders; UInt32 NumBindPairs; UInt32 NumPackStreams; int UnpackCRCDefined; UInt32 UnpackCRC; UInt32 NumUnpackStreams; } CSzFolder; void SzFolder_Init(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); UInt64 SzFolder_GetUnpackSize(CSzFolder *p); typedef struct { UInt32 Low; UInt32 High; } CNtfsFileTime; typedef struct { CNtfsFileTime MTime; UInt64 Size; char *Name; UInt32 FileCRC; Byte HasStream; Byte IsDir; Byte IsAnti; Byte FileCRCDefined; Byte MTimeDefined; } CSzFileItem; void SzFile_Init(CSzFileItem *p); typedef struct { UInt64 *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; CSzFolder *Folders; CSzFileItem *Files; UInt32 NumPackStreams; UInt32 NumFolders; UInt32 NumFiles; } CSzAr; void SzAr_Init(CSzAr *p); void SzAr_Free(CSzAr *p, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/7zMain.c ================================================ /* 7zMain.c - Test application for 7z Decoder 2008-11-23 : Igor Pavlov : Public domain */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "../../7zCrc.h" #include "../../7zFile.h" #include "../../7zVersion.h" #include "7zAlloc.h" #include "7zExtract.h" #include "7zIn.h" static void ConvertNumberToString(UInt64 value, char *s) { char temp[32]; int pos = 0; do { temp[pos++] = (char)('0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } #define PERIOD_4 (4 * 365 + 1) #define PERIOD_100 (PERIOD_4 * 25 - 1) #define PERIOD_400 (PERIOD_100 * 4 + 1) static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s) { unsigned year, mon, day, hour, min, sec; UInt64 v64 = ft->Low | ((UInt64)ft->High << 32); Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; unsigned temp; UInt32 v; v64 /= 10000000; sec = (unsigned)(v64 % 60); v64 /= 60; min = (unsigned)(v64 % 60); v64 /= 60; hour = (unsigned)(v64 % 24); v64 /= 24; v = (UInt32)v64; year = (unsigned)(1601 + v / PERIOD_400 * 400); v %= PERIOD_400; temp = (unsigned)(v / PERIOD_100); if (temp == 4) temp = 3; year += temp * 100; v -= temp * PERIOD_100; temp = v / PERIOD_4; if (temp == 25) temp = 24; year += temp * 4; v -= temp * PERIOD_4; temp = v / 365; if (temp == 4) temp = 3; year += temp; v -= temp * 365; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; for (mon = 1; mon <= 12; mon++) { unsigned s = ms[mon - 1]; if (v < s) break; v -= s; } day = (unsigned)v + 1; sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } if (InFile_Open(&archiveStream.file, args[2])) { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *f = db.db.Files + i; char s[32], t[32]; ConvertNumberToString(f->Size, s); if (f->MTimeDefined) ConvertFileTimeToString(&f->MTime, t); else strcpy(t, " "); printf("%s %10s %s\n", t, s, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ printf("\n"); for (i = 0; i < db.db.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (f->IsDir) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDir) { printf("\n"); continue; } res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { CSzFile outFile; size_t processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } if (OutFile_Open(&outFile, fileName)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/makefile ================================================ MY_STATIC_LINK=1 PROG = 7zDec.exe C_OBJS = \ $O\7zBuf.obj \ $O\7zBuf2.obj \ $O\7zCrc.obj \ $O\LzmaDec.obj \ $O\Bra86.obj \ $O\Bcj2.obj \ $O\7zFile.obj \ $O\7zStream.obj \ 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ OBJS = \ $(7Z_OBJS) \ $(C_OBJS) \ !include "../../../CPP/Build.mak" $(7Z_OBJS): $(*B).c $(COMPL_O1) $(C_OBJS): ../../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Archive/7z/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuf.o: ../../7zBuf.c $(CXX) $(CFLAGS) ../../7zBuf.c 7zBuf2.o: ../../7zBuf2.c $(CXX) $(CFLAGS) ../../7zBuf2.c 7zCrc.o: ../../7zCrc.c $(CXX) $(CFLAGS) ../../7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c LzmaDec.o: ../../LzmaDec.c $(CXX) $(CFLAGS) ../../LzmaDec.c Bra86.o: ../../Bra86.c $(CXX) $(CFLAGS) ../../Bra86.c Bcj2.o: ../../Bcj2.c $(CXX) $(CFLAGS) ../../Bcj2.c 7zFile.o: ../../7zFile.c $(CXX) $(CFLAGS) ../../7zFile.c 7zStream.o: ../../7zStream.c $(CXX) $(CFLAGS) ../../7zStream.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Bcj2.c ================================================ /* Bcj2.c -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bcj2.h" #ifdef _LZMA_PROB32 #define CProb UInt32 #else #define CProb UInt16 #endif #define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) #define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) #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_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } #define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} #define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } #define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize) { CProb p[256 + 2]; SizeT inPos = 0, outPos = 0; const Byte *buffer, *bufferLim; UInt32 range, code; Byte prevByte = 0; unsigned int i; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = kBitModelTotal >> 1; buffer = buf3; bufferLim = buffer + size3; RC_INIT2 if (outSize == 0) return SZ_OK; for (;;) { Byte b; CProb *prob; UInt32 bound; UInt32 ttt; SizeT limit = size0 - inPos; if (outSize - outPos < limit) limit = outSize - outPos; while (limit != 0) { Byte b = buf0[inPos]; outBuf[outPos++] = b; if (IsJ(prevByte, b)) break; inPos++; prevByte = b; limit--; } if (limit == 0 || outPos == outSize) break; b = buf0[inPos++]; if (b == 0xE8) prob = p + prevByte; else if (b == 0xE9) prob = p + 256; else prob = p + 257; IF_BIT_0(prob) { UPDATE_0(prob) prevByte = b; } else { UInt32 dest; const Byte *v; UPDATE_1(prob) if (b == 0xE8) { v = buf1; if (size1 < 4) return SZ_ERROR_DATA; buf1 += 4; size1 -= 4; } else { v = buf2; if (size2 < 4) return SZ_ERROR_DATA; buf2 += 4; size2 -= 4; } dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); outBuf[outPos++] = (Byte)dest; if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 8); if (outPos == outSize) break; outBuf[outPos++] = (Byte)(dest >> 16); if (outPos == outSize) break; outBuf[outPos++] = prevByte = (Byte)(dest >> 24); } } return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Bcj2.h ================================================ /* Bcj2.h -- Converter for x86 code (BCJ2) 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BCJ2_H #define __BCJ2_H #include "Types.h" /* Conditions: outSize <= FullOutputSize, where FullOutputSize is full size of output stream of x86_2 filter. If buf0 overlaps outBuf, there are two required conditions: 1) (buf0 >= outBuf) 2) (buf0 + size0 >= outBuf + FullOutputSize). Returns: SZ_OK SZ_ERROR_DATA - Data error */ int Bcj2_Decode( const Byte *buf0, SizeT size0, const Byte *buf1, SizeT size1, const Byte *buf2, SizeT size2, const Byte *buf3, SizeT size3, Byte *outBuf, SizeT outSize); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Bra.c ================================================ /* Bra.c -- Converters for RISC code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 8; for (i = 0; i <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 dest; UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); src <<= 2; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 2; data[i + 2] = (Byte)(dest >> 16); data[i + 1] = (Byte)(dest >> 8); data[i + 0] = (Byte)dest; } } return i; } SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; ip += 4; for (i = 0; i <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 dest; UInt32 src = (((UInt32)data[i + 1] & 0x7) << 19) | ((UInt32)data[i + 0] << 11) | (((UInt32)data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 1; data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); data[i + 0] = (Byte)(dest >> 11); data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); data[i + 2] = (Byte)dest; i += 2; } } return i; } SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) { UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { UInt32 i; if (size < 4) return 0; size -= 4; for (i = 0; i <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); UInt32 dest; src <<= 2; if (encoding) dest = ip + i + src; else dest = src - (ip + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Bra.h ================================================ /* Bra.h -- Branch converters for executables 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __BRA_H #define __BRA_H #include "Types.h" /* These functions convert relative addresses to absolute addresses in CALL instructions to increase the compression ratio. In: data - data buffer size - size of data ip - current virtual Instruction Pinter (IP) value state - state variable for x86 converter encoding - 0 (for decoding), 1 (for encoding) Out: state - state variable for x86 converter Returns: The number of processed bytes. If you call these functions with multiple calls, you must start next call with first byte after block of processed bytes. Type Endian Alignment LookAhead x86 little 1 4 ARMT little 2 2 ARM little 4 0 PPC big 4 0 SPARC big 4 0 IA64 little 16 0 size must be >= Alignment + LookAhead, if it's not last block. If (size < Alignment + LookAhead), converter returns 0. Example: UInt32 ip = 0; for () { ; size must be >= Alignment + LookAhead, if it's not last block SizeT processed = Convert(data, size, ip, 1); data += processed; size -= processed; ip += processed; } */ #define x86_Convert_Init(state) { state = 0; } SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Bra86.c ================================================ /* Bra86.c -- Converter for x86 code (BCJ) 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) { SizeT bufferPos = 0, prevPosT; UInt32 prevMask = *state & 0x7; if (size < 5) return 0; ip += 5; prevPosT = (SizeT)0 - 1; for (;;) { Byte *p = data + bufferPos; Byte *limit = data + size - 4; for (; p < limit; p++) if ((*p & 0xFE) == 0xE8) break; bufferPos = (SizeT)(p - data); if (p >= limit) break; prevPosT = bufferPos - prevPosT; if (prevPosT > 3) prevMask = 0; else { prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; if (prevMask != 0) { Byte b = p[4 - kMaskToBitNumber[prevMask]]; if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) { prevPosT = bufferPos; prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; continue; } } } prevPosT = bufferPos; if (Test86MSByte(p[4])) { UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); UInt32 dest; for (;;) { Byte b; int index; if (encoding) dest = (ip + (UInt32)bufferPos) + src; else dest = src - (ip + (UInt32)bufferPos); if (prevMask == 0) break; index = kMaskToBitNumber[prevMask] * 8; b = (Byte)(dest >> (24 - index)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index)) - 1); } p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); p[3] = (Byte)(dest >> 16); p[2] = (Byte)(dest >> 8); p[1] = (Byte)dest; bufferPos += 5; } else { prevMask = ((prevMask << 1) & 0x7) | 1; bufferPos++; } } prevPosT = bufferPos - prevPosT; *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); return bufferPos; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/BraIA64.c ================================================ /* BraIA64.c -- Converter for IA-64 code 2008-10-04 : Igor Pavlov : Public domain */ #include "Bra.h" static const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { SizeT i; if (size < 16) return 0; size -= 16; for (i = 0; i <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; int slot; for (slot = 0; slot < 3; slot++, bitPos += 41) { UInt32 bytePos, bitRes; UInt64 instruction, instNorm; int j; if (((mask >> slot) & 1) == 0) continue; bytePos = (bitPos >> 3); bitRes = bitPos & 0x7; instruction = 0; for (j = 0; j < 6; j++) instruction += (UInt64)data[i + j + bytePos] << (8 * j); instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) { UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); UInt32 dest; src |= ((UInt32)(instNorm >> 36) & 1) << 20; src <<= 4; if (encoding) dest = ip + (UInt32)i + src; else dest = src - (ip + (UInt32)i); dest >>= 4; instNorm &= ~((UInt64)(0x8FFFFF) << 13); instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); for (j = 0; j < 6; j++) data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/CpuArch.h ================================================ /* CpuArch.h 2008-08-05 Igor Pavlov Public domain */ #ifndef __CPUARCH_H #define __CPUARCH_H /* LITTLE_ENDIAN_UNALIGN means: 1) CPU is LITTLE_ENDIAN 2) it's allowed to make unaligned memory accesses if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know about these properties of platform. */ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #define LITTLE_ENDIAN_UNALIGN #endif #ifdef LITTLE_ENDIAN_UNALIGN #define GetUi16(p) (*(const UInt16 *)(p)) #define GetUi32(p) (*(const UInt32 *)(p)) #define GetUi64(p) (*(const UInt64 *)(p)) #define SetUi32(p, d) *(UInt32 *)(p) = (d); #else #define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) #define GetUi32(p) ( \ ((const Byte *)(p))[0] | \ ((UInt32)((const Byte *)(p))[1] << 8) | \ ((UInt32)((const Byte *)(p))[2] << 16) | \ ((UInt32)((const Byte *)(p))[3] << 24)) #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) #define SetUi32(p, d) { UInt32 _x_ = (d); \ ((Byte *)(p))[0] = (Byte)_x_; \ ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } #endif #if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_uint64) #define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) #define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) #else #define GetBe32(p) ( \ ((UInt32)((const Byte *)(p))[0] << 24) | \ ((UInt32)((const Byte *)(p))[1] << 16) | \ ((UInt32)((const Byte *)(p))[2] << 8) | \ ((const Byte *)(p))[3] ) #define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) #endif #define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzFind.c ================================================ /* LzFind.c -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include <string.h> #include "LzFind.h" #include "LzHash.h" #define kEmptyHashValue 0 #define kMaxValForNormalize ((UInt32)0xFFFFFFFF) #define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ #define kNormalizeMask (~(kNormalizeStepMin - 1)) #define kMaxHistorySize ((UInt32)3 << 30) #define kStartMaxLen 3 static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) { if (!p->directInput) { alloc->Free(alloc, p->bufferBase); p->bufferBase = 0; } } /* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) { UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; if (p->directInput) { p->blockSize = blockSize; return 1; } if (p->bufferBase == 0 || p->blockSize != blockSize) { LzInWindow_Free(p, alloc); p->blockSize = blockSize; p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); } return (p->bufferBase != 0); } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { p->posLimit -= subValue; p->pos -= subValue; p->streamPos -= subValue; } static void MatchFinder_ReadBlock(CMatchFinder *p) { if (p->streamEndWasReached || p->result != SZ_OK) return; for (;;) { Byte *dest = p->buffer + (p->streamPos - p->pos); size_t size = (p->bufferBase + p->blockSize - dest); if (size == 0) return; p->result = p->stream->Read(p->stream, dest, &size); if (p->result != SZ_OK) return; if (size == 0) { p->streamEndWasReached = 1; return; } p->streamPos += (UInt32)size; if (p->streamPos - p->pos > p->keepSizeAfter) return; } } void MatchFinder_MoveBlock(CMatchFinder *p) { memmove(p->bufferBase, p->buffer - p->keepSizeBefore, (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); p->buffer = p->bufferBase + p->keepSizeBefore; } int MatchFinder_NeedMove(CMatchFinder *p) { /* if (p->streamEndWasReached) return 0; */ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); } void MatchFinder_ReadIfRequired(CMatchFinder *p) { if (p->streamEndWasReached) return; if (p->keepSizeAfter >= p->streamPos - p->pos) MatchFinder_ReadBlock(p); } static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) { if (MatchFinder_NeedMove(p)) MatchFinder_MoveBlock(p); MatchFinder_ReadBlock(p); } static void MatchFinder_SetDefaultSettings(CMatchFinder *p) { p->cutValue = 32; p->btMode = 1; p->numHashBytes = 4; /* p->skipModeBits = 0; */ p->directInput = 0; p->bigHash = 0; } #define kCrcPoly 0xEDB88320 void MatchFinder_Construct(CMatchFinder *p) { UInt32 i; p->bufferBase = 0; p->directInput = 0; p->hash = 0; MatchFinder_SetDefaultSettings(p); for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); p->crc[i] = r; } } static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hash); p->hash = 0; } void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) { MatchFinder_FreeThisClassMemory(p, alloc); LzInWindow_Free(p, alloc); } static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) { size_t sizeInBytes = (size_t)num * sizeof(CLzRef); if (sizeInBytes / sizeof(CLzRef) != num) return 0; return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); } int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { UInt32 sizeReserv; if (historySize > kMaxHistorySize) { MatchFinder_Free(p, alloc); return 0; } sizeReserv = historySize >> 1; if (historySize > ((UInt32)2 << 30)) sizeReserv = historySize >> 2; sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); p->keepSizeBefore = historySize + keepAddBufferBefore + 1; p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ if (LzInWindow_Create(p, sizeReserv, alloc)) { UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; UInt32 hs; p->matchMaxLen = matchMaxLen; { p->fixedHashSize = 0; if (p->numHashBytes == 2) hs = (1 << 16) - 1; else { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; /* hs >>= p->skipModeBits; */ hs |= 0xFFFF; /* don't change it! It's required for Deflate */ if (hs > (1 << 24)) { if (p->numHashBytes == 3) hs = (1 << 24) - 1; else hs >>= 1; } } p->hashMask = hs; hs++; if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; hs += p->fixedHashSize; } { UInt32 prevSize = p->hashSizeSum + p->numSons; UInt32 newSize; p->historySize = historySize; p->hashSizeSum = hs; p->cyclicBufferSize = newCyclicBufferSize; p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); newSize = p->hashSizeSum + p->numSons; if (p->hash != 0 && prevSize == newSize) return 1; MatchFinder_FreeThisClassMemory(p, alloc); p->hash = AllocRefs(newSize, alloc); if (p->hash != 0) { p->son = p->hash + p->hashSizeSum; return 1; } } } MatchFinder_Free(p, alloc); return 0; } static void MatchFinder_SetLimits(CMatchFinder *p) { UInt32 limit = kMaxValForNormalize - p->pos; UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; if (limit2 < limit) limit = limit2; limit2 = p->streamPos - p->pos; if (limit2 <= p->keepSizeAfter) { if (limit2 > 0) limit2 = 1; } else limit2 -= p->keepSizeAfter; if (limit2 < limit) limit = limit2; { UInt32 lenLimit = p->streamPos - p->pos; if (lenLimit > p->matchMaxLen) lenLimit = p->matchMaxLen; p->lenLimit = lenLimit; } p->posLimit = p->pos + limit; } void MatchFinder_Init(CMatchFinder *p) { UInt32 i; for (i = 0; i < p->hashSizeSum; i++) p->hash[i] = kEmptyHashValue; p->cyclicBufferPos = 0; p->buffer = p->bufferBase; p->pos = p->streamPos = p->cyclicBufferSize; p->result = SZ_OK; p->streamEndWasReached = 0; MatchFinder_ReadBlock(p); MatchFinder_SetLimits(p); } static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) { return (p->pos - p->historySize - 1) & kNormalizeMask; } void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) { UInt32 i; for (i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } static void MatchFinder_Normalize(CMatchFinder *p) { UInt32 subValue = MatchFinder_GetSubValue(p); MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); MatchFinder_ReduceOffsets(p, subValue); } static void MatchFinder_CheckLimits(CMatchFinder *p) { if (p->pos == kMaxValForNormalize) MatchFinder_Normalize(p); if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) MatchFinder_CheckAndMoveAndRead(p); if (p->cyclicBufferPos == p->cyclicBufferSize) p->cyclicBufferPos = 0; MatchFinder_SetLimits(p); } static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { son[_cyclicBufferPos] = curMatch; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) return distances; { const Byte *pb = cur - delta; curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; if (pb[maxLen] == cur[maxLen] && *pb == *cur) { UInt32 len = 0; while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) return distances; } } } } } UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, UInt32 *distances, UInt32 maxLen) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return distances; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return distances; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) { CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; return; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { while (++len != lenLimit) if (pb[len] != cur[len]) break; { if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } } #define MOVE_POS \ ++p->cyclicBufferPos; \ p->buffer++; \ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); #define MOVE_POS_RET MOVE_POS return offset; static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } #define GET_MATCHES_HEADER2(minLen, ret_op) \ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ cur = p->buffer; #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) #define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) #define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define GET_MATCHES_FOOTER(offset, maxLen) \ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ distances + offset, maxLen) - distances); MOVE_POS_RET; #define SKIP_FOOTER \ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 1) } UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = 0; GET_MATCHES_FOOTER(offset, 2) } static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, delta2, maxLen, offset; GET_MATCHES_HEADER(3) HASH3_CALC; delta2 = p->pos - p->hash[hash2Value]; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; maxLen = 2; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[0] = maxLen; distances[1] = delta2 - 1; offset = 2; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; GET_MATCHES_FOOTER(offset, maxLen) } static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; GET_MATCHES_HEADER(4) HASH4_CALC; delta2 = p->pos - p->hash[ hash2Value]; delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; maxLen = 1; offset = 0; if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) { distances[0] = maxLen = 2; distances[1] = delta2 - 1; offset = 2; } if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) { maxLen = 3; distances[offset + 1] = delta3 - 1; offset += 2; delta2 = delta3; } if (offset != 0) { for (; maxLen != lenLimit; maxLen++) if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) break; distances[offset - 2] = maxLen; if (maxLen == lenLimit) { p->son[p->cyclicBufferPos] = curMatch; MOVE_POS_RET; } } if (maxLen < 3) maxLen = 3; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - (distances)); MOVE_POS_RET } UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) { UInt32 offset; GET_MATCHES_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) - (distances)); MOVE_POS_RET } static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(2) HASH2_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value; SKIP_HEADER(3) HASH3_CALC; curMatch = p->hash[kFix3HashSize + hashValue]; p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos; p->hash[kFix4HashSize + hashValue] = p->pos; SKIP_FOOTER } while (--num != 0); } static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { UInt32 hash2Value, hash3Value; SKIP_HEADER(4) HASH4_CALC; curMatch = p->hash[kFix4HashSize + hashValue]; p->hash[ hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->hash[kFix4HashSize + hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) { do { SKIP_HEADER(3) HASH_ZIP_CALC; curMatch = p->hash[hashValue]; p->hash[hashValue] = p->pos; p->son[p->cyclicBufferPos] = curMatch; MOVE_POS } while (--num != 0); } void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; if (!p->btMode) { vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; } else if (p->numHashBytes == 2) { vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; } else if (p->numHashBytes == 3) { vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; } else { vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzFind.h ================================================ /* LzFind.h -- Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFIND_H #define __LZFIND_H #include "Types.h" typedef UInt32 CLzRef; typedef struct _CMatchFinder { Byte *buffer; UInt32 pos; UInt32 posLimit; UInt32 streamPos; UInt32 lenLimit; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ UInt32 matchMaxLen; CLzRef *hash; CLzRef *son; UInt32 hashMask; UInt32 cutValue; Byte *bufferBase; ISeqInStream *stream; int streamEndWasReached; UInt32 blockSize; UInt32 keepSizeBefore; UInt32 keepSizeAfter; UInt32 numHashBytes; int directInput; int btMode; /* int skipModeBits; */ int bigHash; UInt32 historySize; UInt32 fixedHashSize; UInt32 hashSizeSum; UInt32 numSons; SRes result; UInt32 crc[256]; } CMatchFinder; #define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) #define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) #define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) int MatchFinder_NeedMove(CMatchFinder *p); Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); void MatchFinder_MoveBlock(CMatchFinder *p); void MatchFinder_ReadIfRequired(CMatchFinder *p); void MatchFinder_Construct(CMatchFinder *p); /* Conditions: historySize <= 3 GB keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB */ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *distances, UInt32 maxLen); /* Conditions: Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. Mf_GetPointerToCurrentPos_Func's result must be used only before any other function */ typedef void (*Mf_Init_Func)(void *object); typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); typedef void (*Mf_Skip_Func)(void *object, UInt32); typedef struct _IMatchFinder { Mf_Init_Func Init; Mf_GetIndexByte_Func GetIndexByte; Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; Mf_GetMatches_Func GetMatches; Mf_Skip_Func Skip; } IMatchFinder; void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); void MatchFinder_Init(CMatchFinder *p); UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzFindMt.c ================================================ /* LzFindMt.c -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #include "LzHash.h" #include "LzFindMt.h" void MtSync_Construct(CMtSync *p) { p->wasCreated = False; p->csWasInitialized = False; p->csWasEntered = False; Thread_Construct(&p->thread); Event_Construct(&p->canStart); Event_Construct(&p->wasStarted); Event_Construct(&p->wasStopped); Semaphore_Construct(&p->freeSemaphore); Semaphore_Construct(&p->filledSemaphore); } void MtSync_GetNextBlock(CMtSync *p) { if (p->needStart) { p->numProcessedBlocks = 1; p->needStart = False; p->stopWriting = False; p->exit = False; Event_Reset(&p->wasStarted); Event_Reset(&p->wasStopped); Event_Set(&p->canStart); Event_Wait(&p->wasStarted); } else { CriticalSection_Leave(&p->cs); p->csWasEntered = False; p->numProcessedBlocks++; Semaphore_Release1(&p->freeSemaphore); } Semaphore_Wait(&p->filledSemaphore); CriticalSection_Enter(&p->cs); p->csWasEntered = True; } /* MtSync_StopWriting must be called if Writing was started */ void MtSync_StopWriting(CMtSync *p) { UInt32 myNumBlocks = p->numProcessedBlocks; if (!Thread_WasCreated(&p->thread) || p->needStart) return; p->stopWriting = True; if (p->csWasEntered) { CriticalSection_Leave(&p->cs); p->csWasEntered = False; } Semaphore_Release1(&p->freeSemaphore); Event_Wait(&p->wasStopped); while (myNumBlocks++ != p->numProcessedBlocks) { Semaphore_Wait(&p->filledSemaphore); Semaphore_Release1(&p->freeSemaphore); } p->needStart = True; } void MtSync_Destruct(CMtSync *p) { if (Thread_WasCreated(&p->thread)) { MtSync_StopWriting(p); p->exit = True; if (p->needStart) Event_Set(&p->canStart); Thread_Wait(&p->thread); Thread_Close(&p->thread); } if (p->csWasInitialized) { CriticalSection_Delete(&p->cs); p->csWasInitialized = False; } Event_Close(&p->canStart); Event_Close(&p->wasStarted); Event_Close(&p->wasStopped); Semaphore_Close(&p->freeSemaphore); Semaphore_Close(&p->filledSemaphore); p->wasCreated = False; } #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { if (p->wasCreated) return SZ_OK; RINOK_THREAD(CriticalSection_Init(&p->cs)); p->csWasInitialized = True; RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); p->needStart = True; RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); p->wasCreated = True; return SZ_OK; } static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks) { SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); if (res != SZ_OK) MtSync_Destruct(p); return res; } void MtSync_Init(CMtSync *p) { p->needStart = True; } #define kMtMaxValForNormalize 0xFFFFFFFF #define DEF_GetHeads2(name, v, action) \ static void GetHeads ## name(const Byte *p, UInt32 pos, \ UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ { action; for (; numHeads != 0; numHeads--) { \ const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } #define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) void HashThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->hashSync; for (;;) { UInt32 numProcessedBlocks = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = numProcessedBlocks; Event_Set(&p->wasStopped); break; } { CMatchFinder *mf = mt->MatchFinder; if (MatchFinder_NeedMove(mf)) { CriticalSection_Enter(&mt->btSync.cs); CriticalSection_Enter(&mt->hashSync.cs); { const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); const Byte *afterPtr; MatchFinder_MoveBlock(mf); afterPtr = MatchFinder_GetPointerToCurrentPos(mf); mt->pointerToCurPos -= beforePtr - afterPtr; mt->buffer -= beforePtr - afterPtr; } CriticalSection_Leave(&mt->btSync.cs); CriticalSection_Leave(&mt->hashSync.cs); continue; } Semaphore_Wait(&p->freeSemaphore); MatchFinder_ReadIfRequired(mf); if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) { UInt32 subValue = (mf->pos - mf->historySize - 1); MatchFinder_ReduceOffsets(mf, subValue); MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); } { UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; UInt32 num = mf->streamPos - mf->pos; heads[0] = 2; heads[1] = num; if (num >= mf->numHashBytes) { num = num - mf->numHashBytes + 1; if (num > kMtHashBlockSize - 2) num = kMtHashBlockSize - 2; mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); heads[0] += num; } mf->pos += num; mf->buffer += num; } } Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) { MtSync_GetNextBlock(&p->hashSync); p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; p->hashNumAvail = p->hashBuf[p->hashBufPos++]; } #define kEmptyHashValue 0 /* #define MFMT_GM_INLINE */ #ifdef MFMT_GM_INLINE #define NO_INLINE MY_FAST_CALL Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) { do { UInt32 *distances = _distances + 1; UInt32 curMatch = pos - *hash++; CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; CLzRef *ptr1 = son + (_cyclicBufferPos << 1); UInt32 len0 = 0, len1 = 0; UInt32 cutValue = _cutValue; UInt32 maxLen = _maxLen; for (;;) { UInt32 delta = pos - curMatch; if (cutValue-- == 0 || delta >= _cyclicBufferSize) { *ptr0 = *ptr1 = kEmptyHashValue; break; } { CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); const Byte *pb = cur - delta; UInt32 len = (len0 < len1 ? len0 : len1); if (pb[len] == cur[len]) { if (++len != lenLimit && pb[len] == cur[len]) while (++len != lenLimit) if (pb[len] != cur[len]) break; if (maxLen < len) { *distances++ = maxLen = len; *distances++ = delta - 1; if (len == lenLimit) { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } } pos++; _cyclicBufferPos++; cur++; { UInt32 num = (UInt32)(distances - _distances); *_distances = num - 1; _distances += num; limit -= num; } } while (limit > 0 && --size != 0); *posRes = pos; return limit; } #endif void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) { UInt32 numProcessed = 0; UInt32 curPos = 2; UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); distances[1] = p->hashNumAvail; while (curPos < limit) { if (p->hashBufPos == p->hashBufPosLimit) { MatchFinderMt_GetNextBlock_Hash(p); distances[1] = numProcessed + p->hashNumAvail; if (p->hashNumAvail >= p->numHashBytes) continue; for (; p->hashNumAvail != 0; p->hashNumAvail--) distances[curPos++] = 0; break; } { UInt32 size = p->hashBufPosLimit - p->hashBufPos; UInt32 lenLimit = p->matchMaxLen; UInt32 pos = p->pos; UInt32 cyclicBufferPos = p->cyclicBufferPos; if (lenLimit >= p->hashNumAvail) lenLimit = p->hashNumAvail; { UInt32 size2 = p->hashNumAvail - lenLimit + 1; if (size2 < size) size = size2; size2 = p->cyclicBufferSize - cyclicBufferPos; if (size2 < size) size = size2; } #ifndef MFMT_GM_INLINE while (curPos < limit && size-- != 0) { UInt32 *startDistances = distances + curPos; UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, startDistances + 1, p->numHashBytes - 1) - startDistances); *startDistances = num - 1; curPos += num; cyclicBufferPos++; pos++; p->buffer++; } #else { UInt32 posRes; curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); p->hashBufPos += posRes - pos; cyclicBufferPos += posRes - pos; p->buffer += posRes - pos; pos = posRes; } #endif numProcessed += pos - p->pos; p->hashNumAvail -= pos - p->pos; p->pos = pos; if (cyclicBufferPos == p->cyclicBufferSize) cyclicBufferPos = 0; p->cyclicBufferPos = cyclicBufferPos; } } distances[0] = curPos; } void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) { CMtSync *sync = &p->hashSync; if (!sync->needStart) { CriticalSection_Enter(&sync->cs); sync->csWasEntered = True; } BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) { UInt32 subValue = p->pos - p->cyclicBufferSize; MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); p->pos -= subValue; } if (!sync->needStart) { CriticalSection_Leave(&sync->cs); sync->csWasEntered = False; } } void BtThreadFunc(CMatchFinderMt *mt) { CMtSync *p = &mt->btSync; for (;;) { UInt32 blockIndex = 0; Event_Wait(&p->canStart); Event_Set(&p->wasStarted); for (;;) { if (p->exit) return; if (p->stopWriting) { p->numProcessedBlocks = blockIndex; MtSync_StopWriting(&mt->hashSync); Event_Set(&p->wasStopped); break; } Semaphore_Wait(&p->freeSemaphore); BtFillBlock(mt, blockIndex++); Semaphore_Release1(&p->filledSemaphore); } } } void MatchFinderMt_Construct(CMatchFinderMt *p) { p->hashBuf = 0; MtSync_Construct(&p->hashSync); MtSync_Construct(&p->btSync); } void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) { alloc->Free(alloc, p->hashBuf); p->hashBuf = 0; } void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) { MtSync_Destruct(&p->hashSync); MtSync_Destruct(&p->btSync); MatchFinderMt_FreeMem(p, alloc); } #define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) #define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } static unsigned MY_STD_CALL BtThreadFunc2(void *p) { Byte allocaDummy[0x180]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; BtThreadFunc((CMatchFinderMt *)p); return 0; } SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) { CMatchFinder *mf = p->MatchFinder; p->historySize = historySize; if (kMtBtBlockSize <= matchMaxLen * 4) return SZ_ERROR_PARAM; if (p->hashBuf == 0) { p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); if (p->hashBuf == 0) return SZ_ERROR_MEM; p->btBuf = p->hashBuf + kHashBufferSize; } keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); keepAddBufferAfter += kMtHashBlockSize; if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) return SZ_ERROR_MEM; RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); return SZ_OK; } /* Call it after ReleaseStream / SetStream */ void MatchFinderMt_Init(CMatchFinderMt *p) { CMatchFinder *mf = p->MatchFinder; p->btBufPos = p->btBufPosLimit = 0; p->hashBufPos = p->hashBufPosLimit = 0; MatchFinder_Init(mf); p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); p->btNumAvailBytes = 0; p->lzPos = p->historySize + 1; p->hash = mf->hash; p->fixedHashSize = mf->fixedHashSize; p->crc = mf->crc; p->son = mf->son; p->matchMaxLen = mf->matchMaxLen; p->numHashBytes = mf->numHashBytes; p->pos = mf->pos; p->buffer = mf->buffer; p->cyclicBufferPos = mf->cyclicBufferPos; p->cyclicBufferSize = mf->cyclicBufferSize; p->cutValue = mf->cutValue; } /* ReleaseStream is required to finish multithreading */ void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) { MtSync_StopWriting(&p->btSync); /* p->MatchFinder->ReleaseStream(); */ } void MatchFinderMt_Normalize(CMatchFinderMt *p) { MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); p->lzPos = p->historySize + 1; } void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) { UInt32 blockIndex; MtSync_GetNextBlock(&p->btSync); blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; p->btBufPosLimit += p->btBuf[p->btBufPos++]; p->btNumAvailBytes = p->btBuf[p->btBufPos++]; if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) MatchFinderMt_Normalize(p); } const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) { return p->pointerToCurPos; } #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) { GET_NEXT_BLOCK_IF_REQUIRED; return p->btNumAvailBytes; } Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) { return p->pointerToCurPos[index]; } UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, curMatch2; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH2_CALC curMatch2 = hash[hash2Value]; hash[hash2Value] = lzPos; if (curMatch2 >= matchMinPos) if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { *distances++ = 2; *distances++ = lzPos - curMatch2 - 1; } return distances; } UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, curMatch2, curMatch3; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH3_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { *distances++ = 3; *distances++ = lzPos - curMatch3 - 1; } return distances; } /* UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) { UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; UInt32 *hash = p->hash; const Byte *cur = p->pointerToCurPos; UInt32 lzPos = p->lzPos; MT_HASH4_CALC curMatch2 = hash[ hash2Value]; curMatch3 = hash[kFix3HashSize + hash3Value]; curMatch4 = hash[kFix4HashSize + hash4Value]; hash[ hash2Value] = hash[kFix3HashSize + hash3Value] = hash[kFix4HashSize + hash4Value] = lzPos; if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch2 - 1; if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) { distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; return distances + 2; } distances[0] = 2; distances += 2; } if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) { distances[1] = lzPos - curMatch3 - 1; if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) { distances[0] = 4; return distances + 2; } distances[0] = 3; distances += 2; } if (curMatch4 >= matchMinPos) if ( cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] ) { *distances++ = 4; *distances++ = lzPos - curMatch4 - 1; } return distances; } */ #define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; p->btNumAvailBytes--; { UInt32 i; for (i = 0; i < len; i += 2) { *distances++ = *btBuf++; *distances++ = *btBuf++; } } INCREASE_LZ_POS return len; } UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) { const UInt32 *btBuf = p->btBuf + p->btBufPos; UInt32 len = *btBuf++; p->btBufPos += 1 + len; if (len == 0) { if (p->btNumAvailBytes-- >= 4) len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); } else { /* Condition: there are matches in btBuf with length < p->numHashBytes */ UInt32 *distances2; p->btNumAvailBytes--; distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); do { *distances2++ = *btBuf++; *distances2++ = *btBuf++; } while ((len -= 2) != 0); len = (UInt32)(distances2 - (distances)); } INCREASE_LZ_POS return len; } #define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED #define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER2 { p->btNumAvailBytes--; SKIP_FOOTER } void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(2) UInt32 hash2Value; MT_HASH2_CALC hash[hash2Value] = p->lzPos; SKIP_FOOTER } void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(3) UInt32 hash2Value, hash3Value; MT_HASH3_CALC hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } /* void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) { SKIP_HEADER(4) UInt32 hash2Value, hash3Value, hash4Value; MT_HASH4_CALC hash[kFix4HashSize + hash4Value] = hash[kFix3HashSize + hash3Value] = hash[ hash2Value] = p->lzPos; SKIP_FOOTER } */ void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) { vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; switch(p->MatchFinder->numHashBytes) { case 2: p->GetHeadsFunc = GetHeads2; p->MixMatchesFunc = (Mf_Mix_Matches)0; vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; break; case 3: p->GetHeadsFunc = GetHeads3; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; break; default: /* case 4: */ p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; /* p->GetHeadsFunc = GetHeads4; */ p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; break; /* default: p->GetHeadsFunc = GetHeads5; p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; break; */ } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzFindMt.h ================================================ /* LzFindMt.h -- multithreaded Match finder for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZFINDMT_H #define __LZFINDMT_H #include "Threads.h" #include "LzFind.h" #define kMtHashBlockSize (1 << 13) #define kMtHashNumBlocks (1 << 3) #define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) #define kMtBtBlockSize (1 << 14) #define kMtBtNumBlocks (1 << 6) #define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) typedef struct _CMtSync { Bool wasCreated; Bool needStart; Bool exit; Bool stopWriting; CThread thread; CAutoResetEvent canStart; CAutoResetEvent wasStarted; CAutoResetEvent wasStopped; CSemaphore freeSemaphore; CSemaphore filledSemaphore; Bool csWasInitialized; Bool csWasEntered; CCriticalSection cs; UInt32 numProcessedBlocks; } CMtSync; typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ #define kMtCacheLineDummy 128 typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); typedef struct _CMatchFinderMt { /* LZ */ const Byte *pointerToCurPos; UInt32 *btBuf; UInt32 btBufPos; UInt32 btBufPosLimit; UInt32 lzPos; UInt32 btNumAvailBytes; UInt32 *hash; UInt32 fixedHashSize; UInt32 historySize; const UInt32 *crc; Mf_Mix_Matches MixMatchesFunc; /* LZ + BT */ CMtSync btSync; Byte btDummy[kMtCacheLineDummy]; /* BT */ UInt32 *hashBuf; UInt32 hashBufPos; UInt32 hashBufPosLimit; UInt32 hashNumAvail; CLzRef *son; UInt32 matchMaxLen; UInt32 numHashBytes; UInt32 pos; Byte *buffer; UInt32 cyclicBufferPos; UInt32 cyclicBufferSize; /* it must be historySize + 1 */ UInt32 cutValue; /* BT + Hash */ CMtSync hashSync; /* Byte hashDummy[kMtCacheLineDummy]; */ /* Hash */ Mf_GetHeads GetHeadsFunc; CMatchFinder *MatchFinder; } CMatchFinderMt; void MatchFinderMt_Construct(CMatchFinderMt *p); void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzHash.h ================================================ /* LzHash.h -- HASH functions for LZ algorithms 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZHASH_H #define __LZHASH_H #define kHash2Size (1 << 10) #define kHash3Size (1 << 16) #define kHash4Size (1 << 20) #define kFix3HashSize (kHash2Size) #define kFix4HashSize (kHash2Size + kHash3Size) #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) #define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); #define HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } #define HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } #define HASH5_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ hash4Value &= (kHash4Size - 1); } /* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ #define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; #define MT_HASH2_CALC \ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); #define MT_HASH3_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } #define MT_HASH4_CALC { \ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ hash2Value = temp & (kHash2Size - 1); \ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaDec.c ================================================ /* LzmaDec.c -- LZMA Decoder 2008-11-06 : Igor Pavlov : Public domain */ #include "LzmaDec.h" #include <string.h> #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define RC_INIT_SIZE 5 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ { UPDATE_0(p); i = (i + i); A0; } else \ { UPDATE_1(p); i = (i + i) + 1; A1; } #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } #define TREE_DECODE(probs, limit, i) \ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } /* #define _LZMA_SIZE_OPT */ #ifdef _LZMA_SIZE_OPT #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) #else #define TREE_6_DECODE(probs, i) \ { i = 1; \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ TREE_GET_BIT(probs, i); \ i -= 0x40; } #endif #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) #define UPDATE_0_CHECK range = bound; #define UPDATE_1_CHECK range -= bound; code -= bound; #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ { UPDATE_0_CHECK; i = (i + i); A0; } else \ { UPDATE_1_CHECK; i = (i + i) + 1; A1; } #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) #define TREE_DECODE_CHECK(probs, limit, i) \ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } #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 kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #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) #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) #if Literal != LZMA_BASE_SIZE StopCompilingDueBUG #endif static const Byte kLiteralNextStates[kNumStates * 2] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; #define LZMA_DIC_MIN (1 << 12) /* First LZMA-symbol is always decoded. And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization Out: Result: SZ_OK - OK SZ_ERROR_DATA - Error p->remainLen: < kMatchSpecLenStart : normal remain = kMatchSpecLenStart : finished = kMatchSpecLenStart + 1 : Flush marker = kMatchSpecLenStart + 2 : State Init Marker */ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { CLzmaProb *probs = p->probs; unsigned state = p->state; UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; unsigned lc = p->prop.lc; Byte *dic = p->dic; SizeT dicBufSize = p->dicBufSize; SizeT dicPos = p->dicPos; UInt32 processedPos = p->processedPos; UInt32 checkDicSize = p->checkDicSize; unsigned len = 0; const Byte *buf = p->buf; UInt32 range = p->range; UInt32 code = p->code; do { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = processedPos & pbMask; prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { unsigned symbol; UPDATE_0(prob); prob = probs + Literal; if (checkDicSize != 0 || processedPos != 0) prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); if (state < kNumLitStates) { symbol = 1; do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned offs = 0x100; symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } dic[dicPos++] = (Byte)symbol; processedPos++; state = kLiteralNextStates[state]; /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ continue; } else { UPDATE_1(prob); prob = probs + IsRep + state; IF_BIT_0(prob) { UPDATE_0(prob); state += kNumStates; prob = probs + LenCoder; } else { UPDATE_1(prob); if (checkDicSize == 0 && processedPos == 0) return SZ_ERROR_DATA; prob = probs + IsRepG0 + state; IF_BIT_0(prob) { UPDATE_0(prob); prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0(prob) { UPDATE_0(prob); dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; processedPos++; state = state < kNumLitStates ? 9 : 11; continue; } UPDATE_1(prob); } else { UInt32 distance; UPDATE_1(prob); prob = probs + IsRepG1 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep1; } else { UPDATE_1(prob); prob = probs + IsRepG2 + state; IF_BIT_0(prob) { UPDATE_0(prob); distance = rep2; } else { UPDATE_1(prob); distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } state = state < kNumLitStates ? 8 : 11; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = (1 << kLenNumLowBits); } else { UPDATE_1(probLen); probLen = prob + LenChoice2; IF_BIT_0(probLen) { UPDATE_0(probLen); probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = (1 << kLenNumMidBits); } else { UPDATE_1(probLen); probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = (1 << kLenNumHighBits); } } TREE_DECODE(probLen, limit, len); len += offset; } if (state >= kNumStates) { UInt32 distance; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_6_DECODE(prob, distance); if (distance >= kStartPosModelIndex) { unsigned posSlot = (unsigned)distance; int numDirectBits = (int)(((distance >> 1) - 1)); distance = (2 | (distance & 1)); if (posSlot < kEndPosModelIndex) { distance <<= numDirectBits; prob = probs + SpecPos + distance - posSlot - 1; { UInt32 mask = 1; unsigned i = 1; do { GET_BIT2(prob + i, i, ; , distance |= mask); mask <<= 1; } while (--numDirectBits != 0); } } else { numDirectBits -= kNumAlignBits; do { NORMALIZE range >>= 1; { UInt32 t; code -= range; t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ distance = (distance << 1) + (t + 1); code += range & t; } /* distance <<= 1; if (code >= range) { code -= range; distance |= 1; } */ } while (--numDirectBits != 0); prob = probs + Align; distance <<= kNumAlignBits; { unsigned i = 1; GET_BIT2(prob + i, i, ; , distance |= 1); GET_BIT2(prob + i, i, ; , distance |= 2); GET_BIT2(prob + i, i, ; , distance |= 4); GET_BIT2(prob + i, i, ; , distance |= 8); } if (distance == (UInt32)0xFFFFFFFF) { len += kMatchSpecLenStart; state -= kNumStates; break; } } } rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance + 1; if (checkDicSize == 0) { if (distance >= processedPos) return SZ_ERROR_DATA; } else if (distance >= checkDicSize) return SZ_ERROR_DATA; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; /* state = kLiteralNextStates[state]; */ } len += kMatchMinLen; if (limit == dicPos) return SZ_ERROR_DATA; { SizeT rem = limit - dicPos; unsigned curLen = ((rem < len) ? (unsigned)rem : len); SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); processedPos += curLen; len -= curLen; if (pos + curLen <= dicBufSize) { Byte *dest = dic + dicPos; ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; const Byte *lim = dest + curLen; dicPos += curLen; do *(dest) = (Byte)*(dest + src); while (++dest != lim); } else { do { dic[dicPos++] = dic[pos]; if (++pos == dicBufSize) pos = 0; } while (--curLen != 0); } } } } while (dicPos < limit && buf < bufLimit); NORMALIZE; p->buf = buf; p->range = range; p->code = code; p->remainLen = len; p->dicPos = dicPos; p->processedPos = processedPos; p->reps[0] = rep0; p->reps[1] = rep1; p->reps[2] = rep2; p->reps[3] = rep3; p->state = state; return SZ_OK; } static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) { if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) { Byte *dic = p->dic; SizeT dicPos = p->dicPos; SizeT dicBufSize = p->dicBufSize; unsigned len = p->remainLen; UInt32 rep0 = p->reps[0]; if (limit - dicPos < len) len = (unsigned)(limit - dicPos); if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) p->checkDicSize = p->prop.dicSize; p->processedPos += len; p->remainLen -= len; while (len-- != 0) { dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; dicPos++; } p->dicPos = dicPos; } } static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) { do { SizeT limit2 = limit; if (p->checkDicSize == 0) { UInt32 rem = p->prop.dicSize - p->processedPos; if (limit - p->dicPos > rem) limit2 = p->dicPos + rem; } RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); if (p->processedPos >= p->prop.dicSize) p->checkDicSize = p->prop.dicSize; LzmaDec_WriteRem(p, limit); } while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); if (p->remainLen > kMatchSpecLenStart) { p->remainLen = kMatchSpecLenStart; } return 0; } typedef enum { DUMMY_ERROR, /* unexpected end of input stream */ DUMMY_LIT, DUMMY_MATCH, DUMMY_REP } ELzmaDummy; static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) { UInt32 range = p->range; UInt32 code = p->code; const Byte *bufLimit = buf + inSize; CLzmaProb *probs = p->probs; unsigned state = p->state; ELzmaDummy res; { CLzmaProb *prob; UInt32 bound; unsigned ttt; unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ prob = probs + Literal; if (p->checkDicSize != 0 || p->processedPos != 0) prob += (LZMA_LIT_SIZE * ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); if (state < kNumLitStates) { unsigned symbol = 1; do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); } else { unsigned matchByte = p->dic[p->dicPos - p->reps[0] + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; unsigned offs = 0x100; unsigned symbol = 1; do { unsigned bit; CLzmaProb *probLit; matchByte <<= 1; bit = (matchByte & offs); probLit = prob + offs + bit + symbol; GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) } while (symbol < 0x100); } res = DUMMY_LIT; } else { unsigned len; UPDATE_1_CHECK; prob = probs + IsRep + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; state = 0; prob = probs + LenCoder; res = DUMMY_MATCH; } else { UPDATE_1_CHECK; res = DUMMY_REP; prob = probs + IsRepG0 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; NORMALIZE_CHECK; return DUMMY_REP; } else { UPDATE_1_CHECK; } } else { UPDATE_1_CHECK; prob = probs + IsRepG1 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; prob = probs + IsRepG2 + state; IF_BIT_0_CHECK(prob) { UPDATE_0_CHECK; } else { UPDATE_1_CHECK; } } } state = kNumStates; prob = probs + RepLenCoder; } { unsigned limit, offset; CLzmaProb *probLen = prob + LenChoice; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenLow + (posState << kLenNumLowBits); offset = 0; limit = 1 << kLenNumLowBits; } else { UPDATE_1_CHECK; probLen = prob + LenChoice2; IF_BIT_0_CHECK(probLen) { UPDATE_0_CHECK; probLen = prob + LenMid + (posState << kLenNumMidBits); offset = kLenNumLowSymbols; limit = 1 << kLenNumMidBits; } else { UPDATE_1_CHECK; probLen = prob + LenHigh; offset = kLenNumLowSymbols + kLenNumMidSymbols; limit = 1 << kLenNumHighBits; } } TREE_DECODE_CHECK(probLen, limit, len); len += offset; } if (state < 4) { unsigned posSlot; prob = probs + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ if (posSlot < kEndPosModelIndex) { prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; } else { numDirectBits -= kNumAlignBits; do { NORMALIZE_CHECK range >>= 1; code -= range & (((code - range) >> 31) - 1); /* if (code >= range) code -= range; */ } while (--numDirectBits != 0); prob = probs + Align; numDirectBits = kNumAlignBits; } { unsigned i = 1; do { GET_BIT_CHECK(prob + i, i); } while (--numDirectBits != 0); } } } } } NORMALIZE_CHECK; return res; } static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) { p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); p->range = 0xFFFFFFFF; p->needFlush = 0; } void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; p->tempBufSize = 0; if (initDic) { p->processedPos = 0; p->checkDicSize = 0; p->needInitState = 1; } if (initState) p->needInitState = 1; } void LzmaDec_Init(CLzmaDec *p) { p->dicPos = 0; LzmaDec_InitDicAndState(p, True, True); } static void LzmaDec_InitStateReal(CLzmaDec *p) { UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); UInt32 i; CLzmaProb *probs = p->probs; for (i = 0; i < numProbs; i++) probs[i] = kBitModelTotal >> 1; p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; p->state = 0; p->needInitState = 0; } SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; (*srcLen) = 0; LzmaDec_WriteRem(p, dicLimit); *status = LZMA_STATUS_NOT_SPECIFIED; while (p->remainLen != kMatchSpecLenStart) { int checkEndMarkNow; if (p->needFlush != 0) { for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) p->tempBuf[p->tempBufSize++] = *src++; if (p->tempBufSize < RC_INIT_SIZE) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->tempBuf[0] != 0) return SZ_ERROR_DATA; LzmaDec_InitRc(p, p->tempBuf); p->tempBufSize = 0; } checkEndMarkNow = 0; if (p->dicPos >= dicLimit) { if (p->remainLen == 0 && p->code == 0) { *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; return SZ_OK; } if (finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->remainLen != 0) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } checkEndMarkNow = 1; } if (p->needInitState) LzmaDec_InitStateReal(p); if (p->tempBufSize == 0) { SizeT processed; const Byte *bufLimit; if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, src, inSize); if (dummyRes == DUMMY_ERROR) { memcpy(p->tempBuf, src, inSize); p->tempBufSize = (unsigned)inSize; (*srcLen) += inSize; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } bufLimit = src; } else bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; p->buf = src; if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) return SZ_ERROR_DATA; processed = (SizeT)(p->buf - src); (*srcLen) += processed; src += processed; inSize -= processed; } else { unsigned rem = p->tempBufSize, lookAhead = 0; while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) p->tempBuf[rem++] = src[lookAhead++]; p->tempBufSize = rem; if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) { int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); if (dummyRes == DUMMY_ERROR) { (*srcLen) += lookAhead; *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (checkEndMarkNow && dummyRes != DUMMY_MATCH) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_ERROR_DATA; } } p->buf = p->tempBuf; if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) return SZ_ERROR_DATA; lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); (*srcLen) += lookAhead; src += lookAhead; inSize -= lookAhead; p->tempBufSize = 0; } } if (p->code == 0) *status = LZMA_STATUS_FINISHED_WITH_MARK; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; } SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen; SizeT inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT inSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->dicPos == p->dicBufSize) p->dicPos = 0; dicPos = p->dicPos; if (outSize > p->dicBufSize - dicPos) { outSizeCur = p->dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); src += inSizeCur; inSize -= inSizeCur; *srcLen += inSizeCur; outSizeCur = p->dicPos - dicPos; memcpy(dest, p->dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } } void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->probs); p->probs = 0; } static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) { alloc->Free(alloc, p->dic); p->dic = 0; } void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) { LzmaDec_FreeProbs(p, alloc); LzmaDec_FreeDict(p, alloc); } SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) { UInt32 dicSize; Byte d; if (size < LZMA_PROPS_SIZE) return SZ_ERROR_UNSUPPORTED; else dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); if (dicSize < LZMA_DIC_MIN) dicSize = LZMA_DIC_MIN; p->dicSize = dicSize; d = data[0]; if (d >= (9 * 5 * 5)) return SZ_ERROR_UNSUPPORTED; p->lc = d % 9; d /= 9; p->pb = d / 5; p->lp = d % 5; return SZ_OK; } static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) { UInt32 numProbs = LzmaProps_GetNumProbs(propNew); if (p->probs == 0 || numProbs != p->numProbs) { LzmaDec_FreeProbs(p, alloc); p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); p->numProbs = numProbs; if (p->probs == 0) return SZ_ERROR_MEM; } return SZ_OK; } SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); p->prop = propNew; return SZ_OK; } SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) { CLzmaProps propNew; SizeT dicBufSize; RINOK(LzmaProps_Decode(&propNew, props, propsSize)); RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); dicBufSize = propNew.dicSize; if (p->dic == 0 || dicBufSize != p->dicBufSize) { LzmaDec_FreeDict(p, alloc); p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); if (p->dic == 0) { LzmaDec_FreeProbs(p, alloc); return SZ_ERROR_MEM; } } p->dicBufSize = dicBufSize; p->prop = propNew; return SZ_OK; } SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzmaDec p; SRes res; SizeT inSize = *srcLen; SizeT outSize = *destLen; *srcLen = *destLen = 0; if (inSize < RC_INIT_SIZE) return SZ_ERROR_INPUT_EOF; LzmaDec_Construct(&p); res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); if (res != 0) return res; p.dic = dest; p.dicBufSize = outSize; LzmaDec_Init(&p); *srcLen = inSize; res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; (*destLen) = p.dicPos; LzmaDec_FreeProbs(&p, alloc); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaDec.h ================================================ /* LzmaDec.h -- LZMA Decoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMADEC_H #define __LZMADEC_H #include "Types.h" /* #define _LZMA_PROB32 */ /* _LZMA_PROB32 can increase the speed on some CPUs, but memory usage for CLzmaDec::probs will be doubled in that case */ #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif /* ---------- LZMA Properties ---------- */ #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaProps { unsigned lc, lp, pb; UInt32 dicSize; } CLzmaProps; /* LzmaProps_Decode - decodes properties Returns: SZ_OK SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); /* ---------- LZMA Decoder state ---------- */ /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ #define LZMA_REQUIRED_INPUT_MAX 20 typedef struct { CLzmaProps prop; CLzmaProb *probs; Byte *dic; const Byte *buf; UInt32 range, code; SizeT dicPos; SizeT dicBufSize; UInt32 processedPos; UInt32 checkDicSize; unsigned state; UInt32 reps[4]; unsigned remainLen; int needFlush; int needInitState; UInt32 numProbs; unsigned tempBufSize; Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; } CLzmaDec; #define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } void LzmaDec_Init(CLzmaDec *p); /* There are two types of LZMA streams: 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ typedef enum { LZMA_FINISH_ANY, /* finish at any point */ LZMA_FINISH_END /* block must be finished at the end */ } ELzmaFinishMode; /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! You must use LZMA_FINISH_END, when you know that current output buffer covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, and output value of destLen will be less than output buffer size limit. You can check status result also. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ typedef enum { LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ } ELzmaStatus; /* ELzmaStatus is used only as output value for function call */ /* ---------- Interfaces ---------- */ /* There are 3 levels of interfaces: 1) Dictionary Interface 2) Buffer Interface 3) One Call Interface You can select any of these interfaces, but don't mix functions from different groups for same object. */ /* There are two variants to allocate state for Dictionary Interface: 1) LzmaDec_Allocate / LzmaDec_Free 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs You can use variant 2, if you set dictionary buffer manually. For Buffer Interface you must always use variant 1. LzmaDec_Allocate* can return: SZ_OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties */ SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); /* ---------- Dictionary Interface ---------- */ /* You can use it, if you want to eliminate the overhead for data copying from dictionary to some other external buffer. You must work with CLzmaDec variables directly in this interface. STEPS: LzmaDec_Constr() LzmaDec_Allocate() for (each new stream) { LzmaDec_Init() while (it needs more decompression) { LzmaDec_DecodeToDic() use data from CLzmaDec::dic and update CLzmaDec::dicPos } } LzmaDec_Free() */ /* LzmaDec_DecodeToDic The decoding to internal dictionary buffer (CLzmaDec::dic). You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! finishMode: It has meaning only if the decoding reaches output limit (dicLimit). LZMA_FINISH_ANY - Decode just dicLimit bytes. LZMA_FINISH_END - Stream must be finished after dicLimit. Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_NEEDS_MORE_INPUT LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error */ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- Buffer Interface ---------- */ /* It's zlib-like interface. See LzmaDec_DecodeToDic description for information about STEPS and return results, but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need to work with CLzmaDec variables manually. finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). */ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); /* ---------- One Call Interface ---------- */ /* LzmaDecode finishMode: It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). Returns: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). */ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaEnc.c ================================================ /* LzmaEnc.c -- LZMA Encoder 2009-02-02 : Igor Pavlov : Public domain */ #include <string.h> /* #define SHOW_STAT */ /* #define SHOW_STAT2 */ #if defined(SHOW_STAT) || defined(SHOW_STAT2) #include <stdio.h> #endif #include "LzmaEnc.h" #include "LzFind.h" #ifdef COMPRESS_MF_MT #include "LzFindMt.h" #endif #ifdef SHOW_STAT static int ttt = 0; #endif #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) #define kBlockSize (9 << 10) #define kUnpackBlockSize (1 << 18) #define kMatchArraySize (1 << 21) #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) #define kNumMaxDirectBits (31) #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) #define kNumBitModelTotalBits 11 #define kBitModelTotal (1 << kNumBitModelTotalBits) #define kNumMoveBits 5 #define kProbInitValue (kBitModelTotal >> 1) #define kNumMoveReducingBits 4 #define kNumBitPriceShiftBits 4 #define kBitPrice (1 << kNumBitPriceShiftBits) void LzmaEncProps_Init(CLzmaEncProps *p) { p->level = 5; p->dictSize = p->mc = 0; p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; p->writeEndMark = 0; } void LzmaEncProps_Normalize(CLzmaEncProps *p) { int level = p->level; if (level < 0) level = 5; p->level = level; if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); if (p->lc < 0) p->lc = 3; if (p->lp < 0) p->lp = 0; if (p->pb < 0) p->pb = 2; if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); if (p->numHashBytes < 0) p->numHashBytes = 4; if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); if (p->numThreads < 0) p->numThreads = #ifdef COMPRESS_MF_MT ((p->btMode && p->algo) ? 2 : 1); #else 1; #endif } UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) { CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); return props.dictSize; } /* #define LZMA_LOG_BSR */ /* Define it for Intel's CPU */ #ifdef LZMA_LOG_BSR #define kDicLogSizeMaxCompress 30 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } UInt32 GetPosSlot1(UInt32 pos) { UInt32 res; BSR2_RET(pos, res); return res; } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #else #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; g_FastPos[1] = 1; for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); UInt32 j; for (j = 0; j < k; j++, c++) g_FastPos[c] = (Byte)slotFast; } } #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ res = p->g_FastPos[pos >> i] + (i * 2); } /* #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ p->g_FastPos[pos >> 6] + 12 : \ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } */ #define GetPosSlot1(pos) p->g_FastPos[pos] #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } #endif #define LZMA_NUM_REPS 4 typedef unsigned CState; typedef struct _COptimal { UInt32 price; CState state; int prev1IsChar; int prev2; UInt32 posPrev2; UInt32 backPrev2; UInt32 posPrev; UInt32 backPrev; UInt32 backs[LZMA_NUM_REPS]; } COptimal; #define kNumOpts (1 << 12) #define kNumLenToPosStates 4 #define kNumPosSlotBits 6 #define kDicLogSizeMin 0 #define kDicLogSizeMax 32 #define kDistTableSizeMax (kDicLogSizeMax * 2) #define kNumAlignBits 4 #define kAlignTableSize (1 << kNumAlignBits) #define kAlignMask (kAlignTableSize - 1) #define kStartPosModelIndex 4 #define kEndPosModelIndex 14 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) #define kNumFullDistances (1 << (kEndPosModelIndex / 2)) #ifdef _LZMA_PROB32 #define CLzmaProb UInt32 #else #define CLzmaProb UInt16 #endif #define LZMA_PB_MAX 4 #define LZMA_LC_MAX 8 #define LZMA_LP_MAX 4 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) #define kLenNumLowBits 3 #define kLenNumLowSymbols (1 << kLenNumLowBits) #define kLenNumMidBits 3 #define kLenNumMidSymbols (1 << kLenNumMidBits) #define kLenNumHighBits 8 #define kLenNumHighSymbols (1 << kLenNumHighBits) #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) #define LZMA_MATCH_LEN_MIN 2 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) #define kNumStates 12 typedef struct { CLzmaProb choice; CLzmaProb choice2; CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; CLzmaProb high[kLenNumHighSymbols]; } CLenEnc; typedef struct { CLenEnc p; UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; UInt32 tableSize; UInt32 counters[LZMA_NUM_PB_STATES_MAX]; } CLenPriceEnc; typedef struct _CRangeEnc { UInt32 range; Byte cache; UInt64 low; UInt64 cacheSize; Byte *buf; Byte *bufLim; Byte *bufBase; ISeqOutStream *outStream; UInt64 processed; SRes res; } CRangeEnc; typedef struct _CSeqInStreamBuf { ISeqInStream funcTable; const Byte *data; SizeT rem; } CSeqInStreamBuf; static SRes MyRead(void *pp, void *data, size_t *size) { size_t curSize = *size; CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; if (p->rem < curSize) curSize = p->rem; memcpy(data, p->data, curSize); p->rem -= curSize; p->data += curSize; *size = curSize; return SZ_OK; } typedef struct { CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; } CSaveState; typedef struct _CLzmaEnc { IMatchFinder matchFinder; void *matchFinderObj; #ifdef COMPRESS_MF_MT Bool mtMode; CMatchFinderMt matchFinderMt; #endif CMatchFinder matchFinderBase; #ifdef COMPRESS_MF_MT Byte pad[128]; #endif UInt32 optimumEndIndex; UInt32 optimumCurrentIndex; UInt32 longestMatchLength; UInt32 numPairs; UInt32 numAvail; COptimal opt[kNumOpts]; #ifndef LZMA_LOG_BSR Byte g_FastPos[1 << kNumLogBits]; #endif UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; UInt32 numFastBytes; UInt32 additionalOffset; UInt32 reps[LZMA_NUM_REPS]; UInt32 state; UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 alignPrices[kAlignTableSize]; UInt32 alignPriceCount; UInt32 distTableSize; unsigned lc, lp, pb; unsigned lpMask, pbMask; CLzmaProb *litProbs; CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb isRep[kNumStates]; CLzmaProb isRepG0[kNumStates]; CLzmaProb isRepG1[kNumStates]; CLzmaProb isRepG2[kNumStates]; CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; CLzmaProb posAlignEncoder[1 << kNumAlignBits]; CLenPriceEnc lenEnc; CLenPriceEnc repLenEnc; unsigned lclp; Bool fastMode; CRangeEnc rc; Bool writeEndMark; UInt64 nowPos64; UInt32 matchPriceCount; Bool finished; Bool multiThread; SRes result; UInt32 dictSize; UInt32 matchFinderCycles; ISeqInStream *inStream; CSeqInStreamBuf seqBufInStream; CSaveState saveState; } CLzmaEnc; void LzmaEnc_SaveState(CLzmaEncHandle pp) { CLzmaEnc *p = (CLzmaEnc *)pp; CSaveState *dest = &p->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); } void LzmaEnc_RestoreState(CLzmaEncHandle pp) { CLzmaEnc *dest = (CLzmaEnc *)pp; const CSaveState *p = &dest->saveState; int i; dest->lenEnc = p->lenEnc; dest->repLenEnc = p->repLenEnc; dest->state = p->state; for (i = 0; i < kNumStates; i++) { memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); } for (i = 0; i < kNumLenToPosStates; i++) memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); memcpy(dest->reps, p->reps, sizeof(p->reps)); memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); } SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; CLzmaEncProps props = *props2; LzmaEncProps_Normalize(&props); if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30)) return SZ_ERROR_PARAM; p->dictSize = props.dictSize; p->matchFinderCycles = props.mc; { unsigned fb = props.fb; if (fb < 5) fb = 5; if (fb > LZMA_MATCH_LEN_MAX) fb = LZMA_MATCH_LEN_MAX; p->numFastBytes = fb; } p->lc = props.lc; p->lp = props.lp; p->pb = props.pb; p->fastMode = (props.algo == 0); p->matchFinderBase.btMode = props.btMode; { UInt32 numHashBytes = 4; if (props.btMode) { if (props.numHashBytes < 2) numHashBytes = 2; else if (props.numHashBytes < 4) numHashBytes = props.numHashBytes; } p->matchFinderBase.numHashBytes = numHashBytes; } p->matchFinderBase.cutValue = props.mc; p->writeEndMark = props.writeEndMark; #ifdef COMPRESS_MF_MT /* if (newMultiThread != _multiThread) { ReleaseMatchFinder(); _multiThread = newMultiThread; } */ p->multiThread = (props.numThreads > 1); #endif return SZ_OK; } static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; #define IsCharState(s) ((s) < 7) #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) #define kInfinityPrice (1 << 30) static void RangeEnc_Construct(CRangeEnc *p) { p->outStream = 0; p->bufBase = 0; } #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) #define RC_BUF_SIZE (1 << 16) static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) { if (p->bufBase == 0) { p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); if (p->bufBase == 0) return 0; p->bufLim = p->bufBase + RC_BUF_SIZE; } return 1; } static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->bufBase); p->bufBase = 0; } static void RangeEnc_Init(CRangeEnc *p) { /* Stream.Init(); */ p->low = 0; p->range = 0xFFFFFFFF; p->cacheSize = 1; p->cache = 0; p->buf = p->bufBase; p->processed = 0; p->res = SZ_OK; } static void RangeEnc_FlushStream(CRangeEnc *p) { size_t num; if (p->res != SZ_OK) return; num = p->buf - p->bufBase; if (num != p->outStream->Write(p->outStream, p->bufBase, num)) p->res = SZ_ERROR_WRITE; p->processed += num; p->buf = p->bufBase; } static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) { if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) { Byte temp = p->cache; do { Byte *buf = p->buf; *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); p->buf = buf; if (buf == p->bufLim) RangeEnc_FlushStream(p); temp = 0xFF; } while (--p->cacheSize != 0); p->cache = (Byte)((UInt32)p->low >> 24); } p->cacheSize++; p->low = (UInt32)p->low << 8; } static void RangeEnc_FlushData(CRangeEnc *p) { int i; for (i = 0; i < 5; i++) RangeEnc_ShiftLow(p); } static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) { do { p->range >>= 1; p->low += p->range & (0 - ((value >> --numBits) & 1)); if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } while (numBits != 0); } static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) { UInt32 ttt = *prob; UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; if (symbol == 0) { p->range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } else { p->low += newBound; p->range -= newBound; ttt -= ttt >> kNumMoveBits; } *prob = (CLzmaProb)ttt; if (p->range < kTopValue) { p->range <<= 8; RangeEnc_ShiftLow(p); } } static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) { symbol |= 0x100; do { RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); } static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) { UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); } void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) { const int kCyclesBits = kNumBitPriceShiftBits; UInt32 w = i; UInt32 bitCount = 0; int j; for (j = 0; j < kCyclesBits; j++) { w = w * w; bitCount <<= 1; while (w >= ((UInt32)1 << 16)) { w >>= 1; bitCount++; } } ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); } } #define GET_PRICE(prob, symbol) \ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICEa(prob, symbol) \ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= 0x100; do { price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); symbol <<= 1; } while (symbol < 0x10000); return price; } static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 offs = 0x100; symbol |= 0x100; do { matchByte <<= 1; price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); symbol <<= 1; offs &= ~(matchByte ^ symbol); } while (symbol < 0x10000); return price; } static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = numBitLevels; i != 0;) { UInt32 bit; i--; bit = (symbol >> i) & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; } } static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) { UInt32 m = 1; int i; for (i = 0; i < numBitLevels; i++) { UInt32 bit = symbol & 1; RangeEnc_EncodeBit(rc, probs + m, bit); m = (m << 1) | bit; symbol >>= 1; } } static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; symbol |= (1 << numBitLevels); while (symbol != 1) { price += GET_PRICEa(probs[symbol >> 1], symbol & 1); symbol >>= 1; } return price; } static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) { UInt32 price = 0; UInt32 m = 1; int i; for (i = numBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) | bit; } return price; } static void LenEnc_Init(CLenEnc *p) { unsigned i; p->choice = p->choice2 = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) p->low[i] = kProbInitValue; for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) p->mid[i] = kProbInitValue; for (i = 0; i < kLenNumHighSymbols; i++) p->high[i] = kProbInitValue; } static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) { if (symbol < kLenNumLowSymbols) { RangeEnc_EncodeBit(rc, &p->choice, 0); RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); } else { RangeEnc_EncodeBit(rc, &p->choice, 1); if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) { RangeEnc_EncodeBit(rc, &p->choice2, 0); RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); } else { RangeEnc_EncodeBit(rc, &p->choice2, 1); RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); } } } static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) { UInt32 a0 = GET_PRICE_0a(p->choice); UInt32 a1 = GET_PRICE_1a(p->choice); UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); UInt32 i = 0; for (i = 0; i < kLenNumLowSymbols; i++) { if (i >= numSymbols) return; prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); } for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) { if (i >= numSymbols) return; prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); } for (; i < numSymbols; i++) prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); } static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) { LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); p->counters[posState] = p->tableSize; } static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) { UInt32 posState; for (posState = 0; posState < numPosStates; posState++) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) { LenEnc_Encode(&p->p, rc, symbol, posState); if (updatePrice) if (--p->counters[posState] == 0) LenPriceEnc_UpdateTable(p, posState, ProbPrices); } static void MovePos(CLzmaEnc *p, UInt32 num) { #ifdef SHOW_STAT ttt += num; printf("\n MovePos %d", num); #endif if (num != 0) { p->additionalOffset += num; p->matchFinder.Skip(p->matchFinderObj, num); } } static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) { UInt32 lenRes = 0, numPairs; p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); #ifdef SHOW_STAT printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); ttt++; { UInt32 i; for (i = 0; i < numPairs; i += 2) printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); } #endif if (numPairs > 0) { lenRes = p->matches[numPairs - 2]; if (lenRes == p->numFastBytes) { const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; UInt32 distance = p->matches[numPairs - 1] + 1; UInt32 numAvail = p->numAvail; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; { const Byte *pby2 = pby - distance; for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); } } } p->additionalOffset++; *numDistancePairsRes = numPairs; return lenRes; } #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; #define IsShortRep(p) ((p)->backPrev == 0) static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) { return GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]); } static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = GET_PRICE_0(p->isRepG0[state]); price += GET_PRICE_1(p->isRep0Long[state][posState]); } else { price = GET_PRICE_1(p->isRepG0[state]); if (repIndex == 1) price += GET_PRICE_0(p->isRepG1[state]); else { price += GET_PRICE_1(p->isRepG1[state]); price += GET_PRICE(p->isRepG2[state], repIndex - 2); } } return price; } static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) { return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + GetPureRepPrice(p, repIndex, state, posState); } static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) { UInt32 posMem = p->opt[cur].posPrev; UInt32 backMem = p->opt[cur].backPrev; p->optimumEndIndex = cur; do { if (p->opt[cur].prev1IsChar) { MakeAsChar(&p->opt[posMem]) p->opt[posMem].posPrev = posMem - 1; if (p->opt[cur].prev2) { p->opt[posMem - 1].prev1IsChar = False; p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; } } { UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = p->opt[posPrev].backPrev; posMem = p->opt[posPrev].posPrev; p->opt[posPrev].backPrev = backCur; p->opt[posPrev].posPrev = cur; cur = posPrev; } } while (cur != 0); *backRes = p->opt[0].backPrev; p->optimumCurrentIndex = p->opt[0].posPrev; return p->optimumCurrentIndex; } #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; UInt32 matchPrice, repMatchPrice, normalMatchPrice; UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; UInt32 *matches; const Byte *data; Byte curByte, matchByte; if (p->optimumEndIndex != p->optimumCurrentIndex) { const COptimal *opt = &p->opt[p->optimumCurrentIndex]; UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; *backRes = opt->backPrev; p->optimumCurrentIndex = opt->posPrev; return lenRes; } p->optimumCurrentIndex = p->optimumEndIndex = 0; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; if (numAvail < 2) { *backRes = (UInt32)(-1); return 1; } if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repMaxIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 lenTest; const Byte *data2; reps[i] = p->reps[i]; data2 = data - (reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) { repLens[i] = 0; continue; } for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); repLens[i] = lenTest; if (lenTest > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= p->numFastBytes) { UInt32 lenRes; *backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; MovePos(p, lenRes - 1); return lenRes; } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } curByte = *data; matchByte = *(data - (reps[0] + 1)); if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) { *backRes = (UInt32)-1; return 1; } p->opt[0].state = (CState)p->state; posState = (position & p->pbMask); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } MakeAsChar(&p->opt[1]); matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); if (matchByte == curByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); if (shortRepPrice < p->opt[1].price) { p->opt[1].price = shortRepPrice; MakeAsShortRep(&p->opt[1]); } } lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); if (lenEnd < 2) { *backRes = p->opt[1].backPrev; return 1; } p->opt[1].posPrev = 0; for (i = 0; i < LZMA_NUM_REPS; i++) p->opt[0].backs[i] = reps[i]; len = lenEnd; do p->opt[len--].price = kInfinityPrice; while (len >= 2); for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 repLen = repLens[i]; UInt32 price; if (repLen < 2) continue; price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; COptimal *opt = &p->opt[repLen]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = i; opt->prev1IsChar = False; } } while (--repLen >= 2); } normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= mainLen) { UInt32 offs = 0; while (len > matches[offs]) offs += 2; for (; ; len++) { COptimal *opt; UInt32 distance = matches[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(len); if (distance < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][distance]; else { UInt32 slot; GetPosSlot2(distance, slot); curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; } opt = &p->opt[len]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = 0; opt->backPrev = distance + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (len == matches[offs]) { offs += 2; if (offs == numPairs) break; } } } cur = 0; #ifdef SHOW_STAT2 if (position >= 0) { unsigned i; printf("\n pos = %4X", position); for (i = cur; i <= lenEnd; i++) printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); } #endif for (;;) { UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; Bool nextIsChar; Byte curByte, matchByte; const Byte *data; COptimal *curOpt; COptimal *nextOpt; cur++; if (cur == lenEnd) return Backward(p, backRes, cur); newLen = ReadMatchDistances(p, &numPairs); if (newLen >= p->numFastBytes) { p->numPairs = numPairs; p->longestMatchLength = newLen; return Backward(p, backRes, cur); } position++; curOpt = &p->opt[cur]; posPrev = curOpt->posPrev; if (curOpt->prev1IsChar) { posPrev--; if (curOpt->prev2) { state = p->opt[curOpt->posPrev2].state; if (curOpt->backPrev2 < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } else state = p->opt[posPrev].state; state = kLiteralNextStates[state]; } else state = p->opt[posPrev].state; if (posPrev == cur - 1) { if (IsShortRep(curOpt)) state = kShortRepNextStates[state]; else state = kLiteralNextStates[state]; } else { UInt32 pos; const COptimal *prevOpt; if (curOpt->prev1IsChar && curOpt->prev2) { posPrev = curOpt->posPrev2; pos = curOpt->backPrev2; state = kRepNextStates[state]; } else { pos = curOpt->backPrev; if (pos < LZMA_NUM_REPS) state = kRepNextStates[state]; else state = kMatchNextStates[state]; } prevOpt = &p->opt[posPrev]; if (pos < LZMA_NUM_REPS) { UInt32 i; reps[0] = prevOpt->backs[pos]; for (i = 1; i <= pos; i++) reps[i] = prevOpt->backs[i - 1]; for (; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i]; } else { UInt32 i; reps[0] = (pos - LZMA_NUM_REPS); for (i = 1; i < LZMA_NUM_REPS; i++) reps[i] = prevOpt->backs[i - 1]; } } curOpt->state = (CState)state; curOpt->backs[0] = reps[0]; curOpt->backs[1] = reps[1]; curOpt->backs[2] = reps[2]; curOpt->backs[3] = reps[3]; curPrice = curOpt->price; nextIsChar = False; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; curByte = *data; matchByte = *(data - (reps[0] + 1)); posState = (position & p->pbMask); curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); { const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); curAnd1Price += (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices)); } nextOpt = &p->opt[cur + 1]; if (curAnd1Price < nextOpt->price) { nextOpt->price = curAnd1Price; nextOpt->posPrev = cur; MakeAsChar(nextOpt); nextIsChar = True; } matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); if (shortRepPrice <= nextOpt->price) { nextOpt->price = shortRepPrice; nextOpt->posPrev = cur; MakeAsShortRep(nextOpt); nextIsChar = True; } } numAvailFull = p->numAvail; { UInt32 temp = kNumOpts - 1 - cur; if (temp < numAvailFull) numAvailFull = temp; } if (numAvailFull < 2) continue; numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); if (!nextIsChar && matchByte != curByte) /* speed optimization */ { /* try Literal + rep0 */ UInt32 temp; UInt32 lenTest2; const Byte *data2 = data - (reps[0] + 1); UInt32 limit = p->numFastBytes + 1; if (limit > numAvailFull) limit = numAvailFull; for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); lenTest2 = temp - 1; if (lenTest2 >= 2) { UInt32 state2 = kLiteralNextStates[state]; UInt32 posStateNext = (position + 1) & p->pbMask; UInt32 nextRepMatchPrice = curAnd1Price + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = False; } } } } startLen = 2; /* speed optimization */ { UInt32 repIndex; for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) { UInt32 lenTest; UInt32 lenTestTemp; UInt32 price; const Byte *data2 = data - (reps[repIndex] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); while (lenEnd < cur + lenTest) p->opt[++lenEnd].price = kInfinityPrice; lenTestTemp = lenTest; price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); do { UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; COptimal *opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = repIndex; opt->prev1IsChar = False; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; /* if (_maxMode) */ { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kRepNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = price + p->repLenEnc.prices[posState][lenTest - 2] + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (position + lenTest + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 curAndLenPrice; COptimal *opt; UInt32 offset = cur + lenTest + 1 + lenTest2; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = repIndex; } } } } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ if (newLen > numAvail) { newLen = numAvail; for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); matches[numPairs] = newLen; numPairs += 2; } if (newLen >= startLen) { UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); UInt32 offs, curBack, posSlot; UInt32 lenTest; while (lenEnd < cur + newLen) p->opt[++lenEnd].price = kInfinityPrice; offs = 0; while (startLen > matches[offs]) offs += 2; curBack = matches[offs + 1]; GetPosSlot2(curBack, posSlot); for (lenTest = /*2*/ startLen; ; lenTest++) { UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; UInt32 lenToPosState = GetLenToPosState(lenTest); COptimal *opt; if (curBack < kNumFullDistances) curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; else curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; opt = &p->opt[cur + lenTest]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur; opt->backPrev = curBack + LZMA_NUM_REPS; opt->prev1IsChar = False; } if (/*_maxMode && */lenTest == matches[offs]) { /* Try Match + Literal + Rep0 */ const Byte *data2 = data - (curBack + 1); UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; if (limit > numAvailFull) limit = numAvailFull; for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { UInt32 state2 = kMatchNextStates[state]; UInt32 posStateNext = (position + lenTest) & p->pbMask; UInt32 curAndLenCharPrice = curAndLenPrice + GET_PRICE_0(p->isMatch[state2][posStateNext]) + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), data[lenTest], data2[lenTest], p->ProbPrices); state2 = kLiteralNextStates[state2]; posStateNext = (posStateNext + 1) & p->pbMask; nextRepMatchPrice = curAndLenCharPrice + GET_PRICE_1(p->isMatch[state2][posStateNext]) + GET_PRICE_1(p->isRep[state2]); /* for (; lenTest2 >= 2; lenTest2--) */ { UInt32 offset = cur + lenTest + 1 + lenTest2; UInt32 curAndLenPrice; COptimal *opt; while (lenEnd < offset) p->opt[++lenEnd].price = kInfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); opt = &p->opt[offset]; if (curAndLenPrice < opt->price) { opt->price = curAndLenPrice; opt->posPrev = cur + lenTest + 1; opt->backPrev = 0; opt->prev1IsChar = True; opt->prev2 = True; opt->posPrev2 = cur; opt->backPrev2 = curBack + LZMA_NUM_REPS; } } } offs += 2; if (offs == numPairs) break; curBack = matches[offs + 1]; if (curBack >= kNumFullDistances) GetPosSlot2(curBack, posSlot); } } } } } #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) { UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; const Byte *data; const UInt32 *matches; if (p->additionalOffset == 0) mainLen = ReadMatchDistances(p, &numPairs); else { mainLen = p->longestMatchLength; numPairs = p->numPairs; } numAvail = p->numAvail; *backRes = (UInt32)-1; if (numAvail < 2) return 1; if (numAvail > LZMA_MATCH_LEN_MAX) numAvail = LZMA_MATCH_LEN_MAX; data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; repLen = repIndex = 0; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; for (len = 2; len < numAvail && data[len] == data2[len]; len++); if (len >= p->numFastBytes) { *backRes = i; MovePos(p, len - 1); return len; } if (len > repLen) { repIndex = i; repLen = len; } } matches = p->matches; if (mainLen >= p->numFastBytes) { *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; MovePos(p, mainLen - 1); return mainLen; } mainDist = 0; /* for GCC */ if (mainLen >= 2) { mainDist = matches[numPairs - 1]; while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) { if (!ChangePair(matches[numPairs - 3], mainDist)) break; numPairs -= 2; mainLen = matches[numPairs - 2]; mainDist = matches[numPairs - 1]; } if (mainLen == 2 && mainDist >= 0x80) mainLen = 1; } if (repLen >= 2 && ( (repLen + 1 >= mainLen) || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) { *backRes = repIndex; MovePos(p, repLen - 1); return repLen; } if (mainLen < 2 || numAvail <= 2) return 1; p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); if (p->longestMatchLength >= 2) { UInt32 newDistance = matches[p->numPairs - 1]; if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || (p->longestMatchLength > mainLen + 1) || (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) return 1; } data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; for (i = 0; i < LZMA_NUM_REPS; i++) { UInt32 len, limit; const Byte *data2 = data - (p->reps[i] + 1); if (data[0] != data2[0] || data[1] != data2[1]) continue; limit = mainLen - 1; for (len = 2; len < limit && data[len] == data2[len]; len++); if (len >= limit) return 1; } *backRes = mainDist + LZMA_NUM_REPS; MovePos(p, mainLen - 2); return mainLen; } static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) { UInt32 len; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; len = LZMA_MATCH_LEN_MIN; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); } static SRes CheckErrors(CLzmaEnc *p) { if (p->result != SZ_OK) return p->result; if (p->rc.res != SZ_OK) p->result = SZ_ERROR_WRITE; if (p->matchFinderBase.result != SZ_OK) p->result = SZ_ERROR_READ; if (p->result != SZ_OK) p->finished = True; return p->result; } static SRes Flush(CLzmaEnc *p, UInt32 nowPos) { /* ReleaseMFStream(); */ p->finished = True; if (p->writeEndMark) WriteEndMarker(p, nowPos & p->pbMask); RangeEnc_FlushData(&p->rc); RangeEnc_FlushStream(&p->rc); return CheckErrors(p); } static void FillAlignPrices(CLzmaEnc *p) { UInt32 i; for (i = 0; i < kAlignTableSize; i++) p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); p->alignPriceCount = 0; } static void FillDistancesPrices(CLzmaEnc *p) { UInt32 tempPrices[kNumFullDistances]; UInt32 i, lenToPosState; for (i = kStartPosModelIndex; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot1(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); } for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; for (posSlot = 0; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); { UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) distancesPrices[i] = posSlotPrices[i]; for (; i < kNumFullDistances; i++) distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; } } p->matchPriceCount = 0; } void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); #ifdef COMPRESS_MF_MT MatchFinderMt_Construct(&p->matchFinderMt); p->matchFinderMt.MatchFinder = &p->matchFinderBase; #endif { CLzmaEncProps props; LzmaEncProps_Init(&props); LzmaEnc_SetProps(p, &props); } #ifndef LZMA_LOG_BSR LzmaEnc_FastPosInit(p->g_FastPos); #endif LzmaEnc_InitPriceTables(p->ProbPrices); p->litProbs = 0; p->saveState.litProbs = 0; } CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) { void *p; p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); if (p != 0) LzmaEnc_Construct((CLzmaEnc *)p); return p; } void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); p->litProbs = 0; p->saveState.litProbs = 0; } void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); #endif MatchFinder_Free(&p->matchFinderBase, allocBig); LzmaEnc_FreeLits(p, alloc); RangeEnc_Free(&p->rc, alloc); } void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) { LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); alloc->Free(alloc, p); } static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) { UInt32 nowPos32, startPos32; if (p->inStream != 0) { p->matchFinderBase.stream = p->inStream; p->matchFinder.Init(p->matchFinderObj); p->inStream = 0; } if (p->finished) return p->result; RINOK(CheckErrors(p)); nowPos32 = (UInt32)p->nowPos64; startPos32 = nowPos32; if (p->nowPos64 == 0) { UInt32 numPairs; Byte curByte; if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) return Flush(p, nowPos32); ReadMatchDistances(p, &numPairs); RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); p->state = kLiteralNextStates[p->state]; curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); LitEnc_Encode(&p->rc, p->litProbs, curByte); p->additionalOffset--; nowPos32++; } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) for (;;) { UInt32 pos, len, posState; if (p->fastMode) len = GetOptimumFast(p, &pos); else len = GetOptimum(p, nowPos32, &pos); #ifdef SHOW_STAT2 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); #endif posState = nowPos32 & p->pbMask; if (len == 1 && pos == (UInt32)-1) { Byte curByte; CLzmaProb *probs; const Byte *data; RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; curByte = *data; probs = LIT_PROBS(nowPos32, *(data - 1)); if (IsCharState(p->state)) LitEnc_Encode(&p->rc, probs, curByte); else LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); p->state = kLiteralNextStates[p->state]; } else { RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); if (pos < LZMA_NUM_REPS) { RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); if (pos == 0) { RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); } else { UInt32 distance = p->reps[pos]; RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); if (pos == 1) RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); else { RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); if (pos == 3) p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; } p->reps[1] = p->reps[0]; p->reps[0] = distance; } if (len == 1) p->state = kShortRepNextStates[p->state]; else { LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); p->state = kRepNextStates[p->state]; } } else { UInt32 posSlot; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); else { RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); p->alignPriceCount++; } } p->reps[3] = p->reps[2]; p->reps[2] = p->reps[1]; p->reps[1] = p->reps[0]; p->reps[0] = pos; p->matchPriceCount++; } } p->additionalOffset -= len; nowPos32 += len; if (p->additionalOffset == 0) { UInt32 processed; if (!p->fastMode) { if (p->matchPriceCount >= (1 << 7)) FillDistancesPrices(p); if (p->alignPriceCount >= kAlignTableSize) FillAlignPrices(p); } if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) break; processed = nowPos32 - startPos32; if (useLimits) { if (processed + kNumOpts + 300 >= maxUnpackSize || RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) break; } else if (processed >= (1 << 15)) { p->nowPos64 += nowPos32 - startPos32; return CheckErrors(p); } } } p->nowPos64 += nowPos32 - startPos32; return Flush(p, nowPos32); } #define kBigHashDicLimit ((UInt32)1 << 24) static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; Bool btMode; if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; btMode = (p->matchFinderBase.btMode != 0); #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); #endif { unsigned lclp = p->lc + p->lp; if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) { LzmaEnc_FreeLits(p, alloc); p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); if (p->litProbs == 0 || p->saveState.litProbs == 0) { LzmaEnc_FreeLits(p, alloc); return SZ_ERROR_MEM; } p->lclp = lclp; } } p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); if (beforeSize + p->dictSize < keepWindowSize) beforeSize = keepWindowSize - p->dictSize; #ifdef COMPRESS_MF_MT if (p->mtMode) { RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); p->matchFinderObj = &p->matchFinderMt; MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); } else #endif { if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) return SZ_ERROR_MEM; p->matchFinderObj = &p->matchFinderBase; MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); } return SZ_OK; } void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; for (i = 0 ; i < LZMA_NUM_REPS; i++) p->reps[i] = 0; RangeEnc_Init(&p->rc); for (i = 0; i < kNumStates; i++) { UInt32 j; for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) { p->isMatch[i][j] = kProbInitValue; p->isRep0Long[i][j] = kProbInitValue; } p->isRep[i] = kProbInitValue; p->isRepG0[i] = kProbInitValue; p->isRepG1[i] = kProbInitValue; p->isRepG2[i] = kProbInitValue; } { UInt32 num = 0x300 << (p->lp + p->lc); for (i = 0; i < num; i++) p->litProbs[i] = kProbInitValue; } { for (i = 0; i < kNumLenToPosStates; i++) { CLzmaProb *probs = p->posSlotEncoder[i]; UInt32 j; for (j = 0; j < (1 << kNumPosSlotBits); j++) probs[j] = kProbInitValue; } } { for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) p->posEncoders[i] = kProbInitValue; } LenEnc_Init(&p->lenEnc.p); LenEnc_Init(&p->repLenEnc.p); for (i = 0; i < (1 << kNumAlignBits); i++) p->posAlignEncoder[i] = kProbInitValue; p->optimumEndIndex = 0; p->optimumCurrentIndex = 0; p->additionalOffset = 0; p->pbMask = (1 << p->pb) - 1; p->lpMask = (1 << p->lp) - 1; } void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { FillDistancesPrices(p); FillAlignPrices(p); } p->lenEnc.tableSize = p->repLenEnc.tableSize = p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); } static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 i; for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) if (p->dictSize <= ((UInt32)1 << i)) break; p->distTableSize = i * 2; p->finished = False; p->result = SZ_OK; RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); LzmaEnc_Init(p); LzmaEnc_InitPrices(p); p->nowPos64 = 0; return SZ_OK; } static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; p->rc.outStream = outStream; return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; p->inStream = inStream; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; p->seqBufInStream.data = src; p->seqBufInStream.rem = srcLen; } SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; LzmaEnc_SetInputBuf(p, src, srcLen); p->inStream = &p->seqBufInStream.funcTable; return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); } void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; if (p->mtMode) MatchFinderMt_ReleaseStream(&p->matchFinderMt); #else pp = pp; #endif } typedef struct _CSeqOutStreamBuf { ISeqOutStream funcTable; Byte *data; SizeT rem; Bool overflow; } CSeqOutStreamBuf; static size_t MyWrite(void *pp, const void *data, size_t size) { CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; if (p->rem < size) { size = p->rem; p->overflow = True; } memcpy(p->data, data, size); p->rem -= size; p->data += size; return size; } UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); } const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) { const CLzmaEnc *p = (CLzmaEnc *)pp; return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; } SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) { CLzmaEnc *p = (CLzmaEnc *)pp; UInt64 nowPos64; SRes res; CSeqOutStreamBuf outStream; outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = False; p->finished = False; p->result = SZ_OK; if (reInit) LzmaEnc_Init(p); LzmaEnc_InitPrices(p); nowPos64 = p->nowPos64; RangeEnc_Init(&p->rc); p->rc.outStream = &outStream.funcTable; res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); *unpackSize = (UInt32)(p->nowPos64 - nowPos64); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)pp; SRes res = SZ_OK; #ifdef COMPRESS_MF_MT Byte allocaDummy[0x300]; int i = 0; for (i = 0; i < 16; i++) allocaDummy[i] = (Byte)i; #endif RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); for (;;) { res = LzmaEnc_CodeOneBlock(p, False, 0, 0); if (res != SZ_OK || p->finished != 0) break; if (progress != 0) { res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); if (res != SZ_OK) { res = SZ_ERROR_PROGRESS; break; } } } LzmaEnc_Finish(pp); return res; } SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) { CLzmaEnc *p = (CLzmaEnc *)pp; int i; UInt32 dictSize = p->dictSize; if (*size < LZMA_PROPS_SIZE) return SZ_ERROR_PARAM; *size = LZMA_PROPS_SIZE; props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); for (i = 11; i <= 30; i++) { if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } } for (i = 0; i < 4; i++) props[1 + i] = (Byte)(dictSize >> (8 * i)); return SZ_OK; } SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { SRes res; CLzmaEnc *p = (CLzmaEnc *)pp; CSeqOutStreamBuf outStream; LzmaEnc_SetInputBuf(p, src, srcLen); outStream.funcTable.Write = MyWrite; outStream.data = dest; outStream.rem = *destLen; outStream.overflow = False; p->writeEndMark = writeEndMark; res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, progress, alloc, allocBig); *destLen -= outStream.rem; if (outStream.overflow) return SZ_ERROR_OUTPUT_EOF; return res; } SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); SRes res; if (p == 0) return SZ_ERROR_MEM; res = LzmaEnc_SetProps(p, props); if (res == SZ_OK) { res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); if (res == SZ_OK) res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, writeEndMark, progress, alloc, allocBig); } LzmaEnc_Destroy(p, alloc, allocBig); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaEnc.h ================================================ /* LzmaEnc.h -- LZMA Encoder 2008-10-04 : Igor Pavlov : Public domain */ #ifndef __LZMAENC_H #define __LZMAENC_H #include "Types.h" #define LZMA_PROPS_SIZE 5 typedef struct _CLzmaEncProps { int level; /* 0 <= level <= 9 */ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version (1 << 12) <= dictSize <= (1 << 30) for 64-bit version default = (1 << 24) */ int lc; /* 0 <= lc <= 8, default = 3 */ int lp; /* 0 <= lp <= 4, default = 0 */ int pb; /* 0 <= pb <= 4, default = 2 */ int algo; /* 0 - fast, 1 - normal, default = 1 */ int fb; /* 5 <= fb <= 273, default = 32 */ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ int numHashBytes; /* 2, 3 or 4, default = 4 */ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ int numThreads; /* 1 or 2, default = 2 */ } CLzmaEncProps; void LzmaEncProps_Init(CLzmaEncProps *p); void LzmaEncProps_Normalize(CLzmaEncProps *p); UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); /* ---------- CLzmaEncHandle Interface ---------- */ /* LzmaEnc_* functions can return the following exit codes: Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater in props SZ_ERROR_WRITE - Write callback error. SZ_ERROR_PROGRESS - some break from progress callback SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ typedef void * CLzmaEncHandle; CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); /* ---------- One Call Interface ---------- */ /* LzmaEncode Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/LzmaLib.def ================================================ EXPORTS LzmaCompress LzmaUncompress ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/LzmaLib.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=LzmaLib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaLib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaLib - Win32 Release" # Name "LzmaLib - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\LzmaLib.def # End Source File # Begin Source File SOURCE=.\LzmaLibExports.c # End Source File # End Group # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\IStream.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\LzmaLib.c # End Source File # Begin Source File SOURCE=..\LzmaLib.h # End Source File # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/LzmaLib.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/LzmaLibExports.c ================================================ /* LzmaLibExports.c -- LZMA library DLL Entry point 2008-10-04 : Igor Pavlov : Public domain */ #include <windows.h> BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance = hInstance; dwReason = dwReason; lpReserved = lpReserved; return TRUE; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/makefile ================================================ MY_STATIC_LINK=1 SLIB = sLZMA.lib PROG = LZMA.dll SLIBPATH = $O\$(SLIB) DEF_FILE = LzmaLib.def CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIBS = $(LIBS) oleaut32.lib LIB_OBJS = \ $O\LzmaLibExports.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzmaLib.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../CPP/Build.mak" $(SLIBPATH): $O $(OBJS) lib -out:$(SLIBPATH) $(OBJS) $(LIBS) $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib/resource.rc ================================================ #include "../../CPP/7zip/MyVersionInfo.rc" MY_VERSION_INFO_DLL("LZMA library", "LZMA") ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib.c ================================================ /* LzmaLib.c -- LZMA library wrapper 2008-08-05 Igor Pavlov Public domain */ #include "LzmaEnc.h" #include "LzmaDec.h" #include "Alloc.h" #include "LzmaLib.h" static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ) { CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; props.lc = lc; props.lp = lp; props.pb = pb; props.fb = fb; props.numThreads = numThreads; return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); } MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, const unsigned char *props, size_t propsSize) { ELzmaStatus status; return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaLib.h ================================================ /* LzmaLib.h -- LZMA library interface 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMALIB_H #define __LZMALIB_H #include "Types.h" #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #define MY_STDAPI MY_EXTERN_C int MY_STD_CALL #define LZMA_PROPS_SIZE 5 /* RAM requirements for LZMA: for compression: (dictSize * 11.5 + 6 MB) + state_size for decompression: dictSize + state_size state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. LZMA properties (5 bytes) format Offset Size Description 0 1 lc, lp and pb in encoded form. 1 4 dictSize (little endian). */ /* LzmaCompress ------------ outPropsSize - In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. LZMA Encoder will use defult values for any parameter, if it is -1 for any from: level, loc, lp, pb, fb, numThreads 0 for dictSize level - compression level: 0 <= level <= 9; level dictSize algo fb 0: 16 KB 0 32 1: 64 KB 0 32 2: 256 KB 0 32 3: 1 MB 0 32 4: 4 MB 0 32 5: 16 MB 1 32 6: 32 MB 1 32 7+: 64 MB 1 64 The default value for "level" is 5. algo = 0 means fast method algo = 1 means normal method dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. lc - The number of literal context bits (high bits of previous literal). It can be in the range from 0 to 8. The default value is 3. Sometimes lc=4 gives the gain for big files. lp - The number of literal pos bits (low bits of current position for literals). It can be in the range from 0 to 4. The default value is 0. The lp switch is intended for periodical data when the period is equal to 2^lp. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc=0, if you change lp switch. pb - The number of pos bits (low bits of current position). It can be in the range from 0 to 4. The default value is 2. The pb switch is intended for periodical data when the period is equal 2^pb. fb - Word size (the number of fast bytes). It can be in the range from 5 to 273. The default value is 32. Usually, a big number gives a little bit better compression ratio and slower compression process. numThreads - The number of thereads. 1 or 2. The default value is 2. Fast mode (algo = 0) can use only 1 thread. Out: destLen - processed output size Returns: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ int level, /* 0 <= level <= 9, default = 5 */ unsigned dictSize, /* default = (1 << 24) */ int lc, /* 0 <= lc <= 8, default = 3 */ int lp, /* 0 <= lp <= 4, default = 0 */ int pb, /* 0 <= pb <= 4, default = 2 */ int fb, /* 5 <= fb <= 273, default = 32 */ int numThreads /* 1 or 2, default = 2 */ ); /* LzmaUncompress -------------- In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Returns: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation arror SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) */ MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, const unsigned char *props, size_t propsSize); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/Lzma86Dec.c ================================================ /* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder 2008-04-07 Igor Pavlov Public domain */ #include "Lzma86Dec.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaDec.h" #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) { unsigned i; if (srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; *unpackSize = 0; for (i = 0; i < sizeof(UInt64); i++) *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); return SZ_OK; } SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) { SRes res; int useFilter; SizeT inSizePure; ELzmaStatus status; if (*srcLen < LZMA86_HEADER_SIZE) return SZ_ERROR_INPUT_EOF; useFilter = src[0]; if (useFilter > 1) { *destLen = 0; return SZ_ERROR_UNSUPPORTED; } inSizePure = *srcLen - LZMA86_HEADER_SIZE; res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); *srcLen = inSizePure + LZMA86_HEADER_SIZE; if (res != SZ_OK) return res; if (useFilter == 1) { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(dest, *destLen, 0, &x86State, 0); } return SZ_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/Lzma86Dec.h ================================================ /* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86DEC_H #define __LZMA86DEC_H #include "../Types.h" /* Lzma86_GetUnpackSize: In: src - input data srcLen - input data size Out: unpackSize - size of uncompressed stream Return code: SZ_OK - OK SZ_ERROR_INPUT_EOF - Error in headers */ SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); /* Lzma86_Decode: In: dest - output data destLen - output data size src - input data srcLen - input data size Out: destLen - processed output size srcLen - processed input size Return code: SZ_OK - OK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - unsupported file SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer */ SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/Lzma86Enc.c ================================================ /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #include <string.h> #include "Lzma86Enc.h" #include "../Alloc.h" #include "../Bra.h" #include "../LzmaEnc.h" #define SZE_OUT_OVERFLOW SZE_DATA_ERROR static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; #define LZMA86_SIZE_OFFSET (1 + LZMA_PROPS_SIZE) #define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode) { size_t outSize2 = *destLen; Byte *filteredStream; Bool useFilter; int mainResult = SZ_ERROR_OUTPUT_EOF; CLzmaEncProps props; LzmaEncProps_Init(&props); props.level = level; props.dictSize = dictSize; *destLen = 0; if (outSize2 < LZMA86_HEADER_SIZE) return SZ_ERROR_OUTPUT_EOF; { int i; UInt64 t = srcLen; for (i = 0; i < 8; i++, t >>= 8) dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; } filteredStream = 0; useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (srcLen != 0) { filteredStream = (Byte *)MyAlloc(srcLen); if (filteredStream == 0) return SZ_ERROR_MEM; memcpy(filteredStream, src, srcLen); } { UInt32 x86State; x86_Convert_Init(x86State); x86_Convert(filteredStream, srcLen, 0, &x86State, 1); } } { size_t minSize = 0; Bool bestIsFiltered = False; /* passes for SZ_FILTER_AUTO: 0 - BCJ + LZMA 1 - LZMA 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. */ int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; int i; for (i = 0; i < numPasses; i++) { size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; size_t outPropsSize = 5; SRes curRes; Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); if (curModeIsFiltered && !bestIsFiltered) break; if (useFilter && i == 0) curModeIsFiltered = True; curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, curModeIsFiltered ? filteredStream : src, srcLen, &props, dest + 1, &outPropsSize, 0, NULL, &g_Alloc, &g_Alloc); if (curRes != SZ_ERROR_OUTPUT_EOF) { if (curRes != SZ_OK) { mainResult = curRes; break; } if (outSizeProcessed <= minSize || mainResult != SZ_OK) { minSize = outSizeProcessed; bestIsFiltered = curModeIsFiltered; mainResult = SZ_OK; } } } dest[0] = (bestIsFiltered ? 1 : 0); *destLen = LZMA86_HEADER_SIZE + minSize; } if (useFilter) MyFree(filteredStream); return mainResult; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/Lzma86Enc.h ================================================ /* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder 2008-08-05 Igor Pavlov Public domain */ #ifndef __LZMA86ENC_H #define __LZMA86ENC_H #include "../Types.h" /* It's an example for LZMA + x86 Filter use. You can use .lzma86 extension, if you write that stream to file. .lzma86 header adds one additional byte to standard .lzma header. .lzma86 header (14 bytes): Offset Size Description 0 1 = 0 - no filter, = 1 - x86 filter 1 1 lc, lp and pb in encoded form 2 4 dictSize (little endian) 6 8 uncompressed size (little endian) Lzma86_Encode ------------- level - compression level: 0 <= level <= 9, the default value for "level" is 5. dictSize - The dictionary size in bytes. The maximum value is 128 MB = (1 << 27) bytes for 32-bit version 1 GB = (1 << 30) bytes for 64-bit version The default value is 16 MB = (1 << 24) bytes, for level = 5. It's recommended to use the dictionary that is larger than 4 KB and that can be calculated as (1 << N) or (3 << N) sizes. For better compression ratio dictSize must be >= inSize. filterMode: SZ_FILTER_NO - no Filter SZ_FILTER_YES - x86 Filter SZ_FILTER_AUTO - it tries both alternatives to select best. Encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. Lzma86Encode allocates Data with MyAlloc functions. RAM Requirements for compressing: RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize filterMode FilterBlockSize SZ_FILTER_NO 0 SZ_FILTER_YES inSize SZ_FILTER_AUTO inSize Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, int level, UInt32 dictSize, int filterMode); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/LzmaUtil.c ================================================ /* LzmaUtil.c -- Test application for LZMA compression 2008-11-23 : Igor Pavlov : Public domain */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include "../Alloc.h" #include "../7zFile.h" #include "../7zVersion.h" #include "../LzmaDec.h" #include "../LzmaEnc.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; const char *kDataErrorMessage = "Data error"; static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; void PrintHelp(char *buffer) { strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" "\nUsage: lzma <e|d> inputFile outputFile\n" " e: encode file\n" " d: decode file\n"); } int PrintError(char *buffer, const char *message) { strcat(buffer, "\nError: "); strcat(buffer, message); strcat(buffer, "\n"); return 1; } int PrintErrorNumber(char *buffer, SRes val) { sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); return 1; } int PrintUserError(char *buffer) { return PrintError(buffer, "Incorrect command"); } #define IN_BUF_SIZE (1 << 16) #define OUT_BUF_SIZE (1 << 16) static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize) { int thereIsSize = (unpackSize != (UInt64)(Int64)-1); Byte inBuf[IN_BUF_SIZE]; Byte outBuf[OUT_BUF_SIZE]; size_t inPos = 0, inSize = 0, outPos = 0; LzmaDec_Init(state); for (;;) { if (inPos == inSize) { inSize = IN_BUF_SIZE; RINOK(inStream->Read(inStream, inBuf, &inSize)); inPos = 0; } { SRes res; SizeT inProcessed = inSize - inPos; SizeT outProcessed = OUT_BUF_SIZE - outPos; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; ELzmaStatus status; if (thereIsSize && outProcessed > unpackSize) { outProcessed = (SizeT)unpackSize; finishMode = LZMA_FINISH_END; } res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, inBuf + inPos, &inProcessed, finishMode, &status); inPos += inProcessed; outPos += outProcessed; unpackSize -= outProcessed; if (outStream) if (outStream->Write(outStream, outBuf, outPos) != outPos) return SZ_ERROR_WRITE; outPos = 0; if (res != SZ_OK || thereIsSize && unpackSize == 0) return res; if (inProcessed == 0 && outProcessed == 0) { if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) return SZ_ERROR_DATA; return res; } } } } static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) { UInt64 unpackSize; int i; SRes res = 0; CLzmaDec state; /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ unsigned char header[LZMA_PROPS_SIZE + 8]; /* Read and parse header */ RINOK(SeqInStream_Read(inStream, header, sizeof(header))); unpackSize = 0; for (i = 0; i < 8; i++) unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); LzmaDec_Construct(&state); RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); res = Decode2(&state, outStream, inStream, unpackSize); LzmaDec_Free(&state, &g_Alloc); return res; } static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) { CLzmaEncHandle enc; SRes res; CLzmaEncProps props; rs = rs; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; LzmaEncProps_Init(&props); res = LzmaEnc_SetProps(enc, &props); if (res == SZ_OK) { Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); if (outStream->Write(outStream, header, headerSize) != headerSize) res = SZ_ERROR_WRITE; else { if (res == SZ_OK) res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); } } LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); return res; } int main2(int numArgs, const char *args[], char *rs) { CFileSeqInStream inStream; CFileOutStream outStream; char c; int res; int encodeMode; Bool useOutFile = False; FileSeqInStream_CreateVTable(&inStream); File_Construct(&inStream.file); FileOutStream_CreateVTable(&outStream); File_Construct(&outStream.file); if (numArgs == 1) { PrintHelp(rs); return 0; } if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) return PrintUserError(rs); c = args[1][0]; encodeMode = (c == 'e' || c == 'E'); if (!encodeMode && c != 'd' && c != 'D') return PrintUserError(rs); { size_t t4 = sizeof(UInt32); size_t t8 = sizeof(UInt64); if (t4 != 4 || t8 != 8) return PrintError(rs, "Incorrect UInt32 or UInt64"); } if (InFile_Open(&inStream.file, args[2]) != 0) return PrintError(rs, "Can not open input file"); if (numArgs > 3) { useOutFile = True; if (OutFile_Open(&outStream.file, args[3]) != 0) return PrintError(rs, "Can not open output file"); } else if (encodeMode) PrintUserError(rs); if (encodeMode) { UInt64 fileSize; File_GetLength(&inStream.file, &fileSize); res = Encode(&outStream.s, &inStream.s, fileSize, rs); } else { res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); } if (useOutFile) File_Close(&outStream.file); File_Close(&inStream.file); if (res != SZ_OK) { if (res == SZ_ERROR_MEM) return PrintError(rs, kCantAllocateMessage); else if (res == SZ_ERROR_DATA) return PrintError(rs, kDataErrorMessage); else if (res == SZ_ERROR_WRITE) return PrintError(rs, kCantWriteMessage); else if (res == SZ_ERROR_READ) return PrintError(rs, kCantReadMessage); return PrintErrorNumber(rs, res); } return 0; } int MY_CDECL main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/LzmaUtil.dsp ================================================ # Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=LzmaUtil - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "LzmaUtil - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\lzmac.exe" !ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\lzmac.exe" /pdbtype:sept !ENDIF # Begin Target # Name "LzmaUtil - Win32 Release" # Name "LzmaUtil - Win32 Debug" # Begin Source File SOURCE=..\7zFile.c # End Source File # Begin Source File SOURCE=..\7zFile.h # End Source File # Begin Source File SOURCE=..\7zStream.c # End Source File # Begin Source File SOURCE=..\7zVersion.h # End Source File # Begin Source File SOURCE=..\Alloc.c # End Source File # Begin Source File SOURCE=..\Alloc.h # End Source File # Begin Source File SOURCE=..\CpuArch.h # End Source File # Begin Source File SOURCE=..\LzFind.c # End Source File # Begin Source File SOURCE=..\LzFind.h # End Source File # Begin Source File SOURCE=..\LzFindMt.c # End Source File # Begin Source File SOURCE=..\LzFindMt.h # End Source File # Begin Source File SOURCE=..\LzHash.h # End Source File # Begin Source File SOURCE=..\LzmaDec.c # End Source File # Begin Source File SOURCE=..\LzmaDec.h # End Source File # Begin Source File SOURCE=..\LzmaEnc.c # End Source File # Begin Source File SOURCE=..\LzmaEnc.h # End Source File # Begin Source File SOURCE=.\LzmaUtil.c # End Source File # Begin Source File SOURCE=..\Threads.c # End Source File # Begin Source File SOURCE=..\Threads.h # End Source File # Begin Source File SOURCE=..\Types.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/LzmaUtil.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/makefile ================================================ MY_STATIC_LINK=1 PROG = LZMAc.exe CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ LIB_OBJS = \ $O\LzmaUtil.obj \ C_OBJS = \ $O\Alloc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\7zFile.obj \ $O\7zStream.obj \ $O\Threads.obj \ OBJS = \ $(LIB_OBJS) \ $(C_OBJS) \ !include "../../CPP/Build.mak" $(LIB_OBJS): $(*B).c $(COMPL_O2) $(C_OBJS): ../$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/LzmaUtil/makefile.gcc ================================================ PROG = lzma CC = gcc LIB = liblzma.a RM = rm -f CFLAGS = -c -O2 -Wall AR = ar RANLIB = ranlib OBJS = \ Alloc.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ LzmaLib.o \ 7zFile.o \ 7zStream.o \ all: $(PROG) $(PROG): LzmaUtil.o $(LIB) $(CC) -o $(PROG) $(LDFLAGS) $< $(LIB) LzmaUtil.o: LzmaUtil.c $(CC) $(CFLAGS) LzmaUtil.c $(LIB): $(OBJS) rm -f $@ $(AR) rcu $@ $(OBJS) $(RANLIB) $@ Alloc.o: ../Alloc.c $(CC) $(CFLAGS) ../Alloc.c LzFind.o: ../LzFind.c $(CC) $(CFLAGS) ../LzFind.c LzmaDec.o: ../LzmaDec.c $(CC) $(CFLAGS) ../LzmaDec.c LzmaEnc.o: ../LzmaEnc.c $(CC) $(CFLAGS) ../LzmaEnc.c LzmaLib.o: ../LzmaLib.c $(CC) $(CFLAGS) ../LzmaLib.c 7zFile.o: ../7zFile.c $(CC) $(CFLAGS) ../7zFile.c 7zStream.o: ../7zStream.c $(CC) $(CFLAGS) ../7zStream.c clean: -$(RM) $(PROG) *.o *.a ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Threads.c ================================================ /* Threads.c -- multithreading library 2008-08-05 Igor Pavlov Public domain */ #include "Threads.h" #include <process.h> static WRes GetError() { DWORD res = GetLastError(); return (res) ? (WRes)(res) : 1; } WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } static WRes MyCloseHandle(HANDLE *h) { if (*h != NULL) if (!CloseHandle(*h)) return GetError(); *h = NULL; return 0; } WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ thread->handle = /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */ (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId); /* maybe we must use errno here, but probably GetLastError() is also OK. */ return HandleToWRes(thread->handle); } WRes WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } WRes Thread_Wait(CThread *thread) { if (thread->handle == NULL) return 1; return WaitObject(thread->handle); } WRes Thread_Close(CThread *thread) { return MyCloseHandle(&thread->handle); } WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled) { p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL); return HandleToWRes(p->handle); } WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled) { return Event_Create(p, TRUE, initialSignaled); } WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled) { return Event_Create(p, FALSE, initialSignaled); } WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); } WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); } WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); } WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); } WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount) { p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL); return HandleToWRes(p->handle); } WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) { return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); } WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount) { return Semaphore_Release(p, (LONG)releaseCount, NULL); } WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); } WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); } WRes CriticalSection_Init(CCriticalSection *p) { /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ __try { InitializeCriticalSection(p); /* InitializeCriticalSectionAndSpinCount(p, 0); */ } __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } return 0; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Threads.h ================================================ /* Threads.h -- multithreading library 2008-11-22 : Igor Pavlov : Public domain */ #ifndef __7Z_THRESDS_H #define __7Z_THRESDS_H #include "Types.h" typedef struct _CThread { HANDLE handle; } CThread; #define Thread_Construct(thread) (thread)->handle = NULL #define Thread_WasCreated(thread) ((thread)->handle != NULL) typedef unsigned THREAD_FUNC_RET_TYPE; #define THREAD_FUNC_CALL_TYPE MY_STD_CALL #define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter); WRes Thread_Wait(CThread *thread); WRes Thread_Close(CThread *thread); typedef struct _CEvent { HANDLE handle; } CEvent; typedef CEvent CAutoResetEvent; typedef CEvent CManualResetEvent; #define Event_Construct(event) (event)->handle = NULL #define Event_IsCreated(event) ((event)->handle != NULL) WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled); WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event); WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled); WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event); WRes Event_Set(CEvent *event); WRes Event_Reset(CEvent *event); WRes Event_Wait(CEvent *event); WRes Event_Close(CEvent *event); typedef struct _CSemaphore { HANDLE handle; } CSemaphore; #define Semaphore_Construct(p) (p)->handle = NULL WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount); WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); WRes Semaphore_Release1(CSemaphore *p); WRes Semaphore_Wait(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p); typedef CRITICAL_SECTION CCriticalSection; WRes CriticalSection_Init(CCriticalSection *p); #define CriticalSection_Delete(p) DeleteCriticalSection(p) #define CriticalSection_Enter(p) EnterCriticalSection(p) #define CriticalSection_Leave(p) LeaveCriticalSection(p) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/C/Types.h ================================================ /* Types.h -- Basic types 2008-11-23 : Igor Pavlov : Public domain */ #ifndef __7Z_TYPES_H #define __7Z_TYPES_H #include <stddef.h> #ifdef _WIN32 #include <windows.h> #endif #define SZ_OK 0 #define SZ_ERROR_DATA 1 #define SZ_ERROR_MEM 2 #define SZ_ERROR_CRC 3 #define SZ_ERROR_UNSUPPORTED 4 #define SZ_ERROR_PARAM 5 #define SZ_ERROR_INPUT_EOF 6 #define SZ_ERROR_OUTPUT_EOF 7 #define SZ_ERROR_READ 8 #define SZ_ERROR_WRITE 9 #define SZ_ERROR_PROGRESS 10 #define SZ_ERROR_FAIL 11 #define SZ_ERROR_THREAD 12 #define SZ_ERROR_ARCHIVE 16 #define SZ_ERROR_NO_ARCHIVE 17 typedef int SRes; #ifdef _WIN32 typedef DWORD WRes; #else typedef int WRes; #endif #ifndef RINOK #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #endif typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; #ifdef _LZMA_UINT32_IS_ULONG typedef long Int32; typedef unsigned long UInt32; #else typedef int Int32; typedef unsigned int UInt32; #endif #ifdef _SZ_NO_INT_64 /* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. NOTES: Some code will work incorrectly in that case! */ typedef long Int64; typedef unsigned long UInt64; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif #ifdef _LZMA_NO_SYSTEM_SIZE_T typedef UInt32 SizeT; #else typedef size_t SizeT; #endif typedef int Bool; #define True 1 #define False 0 #ifdef _MSC_VER #if _MSC_VER >= 1300 #define MY_NO_INLINE __declspec(noinline) #else #define MY_NO_INLINE #endif #define MY_CDECL __cdecl #define MY_STD_CALL __stdcall #define MY_FAST_CALL MY_NO_INLINE __fastcall #else #define MY_CDECL #define MY_STD_CALL #define MY_FAST_CALL #endif /* The following interfaces use first parameter as pointer to structure */ typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) < input(*size)) is allowed */ } ISeqInStream; /* it can return SZ_ERROR_INPUT_EOF */ SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); typedef struct { size_t (*Write)(void *p, const void *buf, size_t size); /* Returns: result - the number of actually written bytes. (result < size) means error */ } ISeqOutStream; typedef enum { SZ_SEEK_SET = 0, SZ_SEEK_CUR = 1, SZ_SEEK_END = 2 } ESzSeek; typedef struct { SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ISeekInStream; typedef struct { SRes (*Look)(void *p, void **buf, size_t *size); /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. (output(*size) > input(*size)) is not allowed (output(*size) < input(*size)) is allowed */ SRes (*Skip)(void *p, size_t offset); /* offset must be <= output(*size) of Look */ SRes (*Read)(void *p, void *buf, size_t *size); /* reads directly (without buffer). It's same as ISeqInStream::Read */ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); } ILookInStream; SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); /* reads via ILookInStream::Read */ SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); #define LookToRead_BUF_SIZE (1 << 14) typedef struct { ILookInStream s; ISeekInStream *realStream; size_t pos; size_t size; Byte buf[LookToRead_BUF_SIZE]; } CLookToRead; void LookToRead_CreateVTable(CLookToRead *p, int lookahead); void LookToRead_Init(CLookToRead *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToLook; void SecToLook_CreateVTable(CSecToLook *p); typedef struct { ISeqInStream s; ILookInStream *realStream; } CSecToRead; void SecToRead_CreateVTable(CSecToRead *p); typedef struct { SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); /* Returns: result. (result != SZ_OK) means break. Value (UInt64)(Int64)-1 for size means unknown value. */ } ICompressProgress; typedef struct { void *(*Alloc)(void *p, size_t size); void (*Free)(void *p, void *address); /* address can be 0 */ } ISzAlloc; #define IAlloc_Alloc(p, size) (p)->Alloc((p), size) #define IAlloc_Free(p, a) (p)->Free((p), a) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zCompressionMode.cpp ================================================ // CompressionMethod.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zCompressionMode.h ================================================ // 7zCompressionMode.h #ifndef __7Z_COMPRESSION_MODE_H #define __7Z_COMPRESSION_MODE_H #include "../../../Common/MyString.h" #include "../../../Windows/PropVariant.h" #include "../../Common/MethodProps.h" namespace NArchive { namespace N7z { struct CMethodFull: public CMethod { UInt32 NumInStreams; UInt32 NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBind { UInt32 InCoder; UInt32 InStream; UInt32 OutCoder; UInt32 OutStream; }; struct CCompressionMethodMode { CObjectVector<CMethodFull> Methods; CRecordVector<CBind> Binds; #ifdef COMPRESS_MT UInt32 NumThreads; #endif bool PasswordIsDefined; UString Password; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): PasswordIsDefined(false) #ifdef COMPRESS_MT , NumThreads(1) #endif {} }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zDecode.cpp ================================================ // 7zDecode.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/LockedStream.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamObjects.h" #include "7zDecode.h" namespace NArchive { namespace N7z { static void ConvertFolderItemInfoToBindInfo(const CFolder &folder, CBindInfoEx &bindInfo) { bindInfo.Clear(); int i; for (i = 0; i < folder.BindPairs.Size(); i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex; bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex; bindInfo.BindPairs.Add(bindPair); } UInt32 outStreamIndex = 0; for (i = 0; i < folder.Coders.Size(); i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; const CCoderInfo &coderInfo = folder.Coders[i]; coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams; coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams; bindInfo.Coders.Add(coderStreamsInfo); bindInfo.CoderMethodIDs.Add(coderInfo.MethodID); for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++) if (folder.FindBindPairForOutStream(outStreamIndex) < 0) bindInfo.OutStreams.Add(outStreamIndex); } for (i = 0; i < folder.PackStreams.Size(); i++) bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]); } static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, const NCoderMixer::CCoderStreamsInfo &a2) { return (a1.NumInStreams == a2.NumInStreams) && (a1.NumOutStreams == a2.NumOutStreams); } static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2) { return (a1.InIndex == a2.InIndex) && (a1.OutIndex == a2.OutIndex); } static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2) { if (a1.Coders.Size() != a2.Coders.Size()) return false; int i; for (i = 0; i < a1.Coders.Size(); i++) if (!AreCodersEqual(a1.Coders[i], a2.Coders[i])) return false; if (a1.BindPairs.Size() != a2.BindPairs.Size()) return false; for (i = 0; i < a1.BindPairs.Size(); i++) if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i])) return false; for (i = 0; i < a1.CoderMethodIDs.Size(); i++) if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i]) return false; if (a1.InStreams.Size() != a2.InStreams.Size()) return false; if (a1.OutStreams.Size() != a2.OutStreams.Size()) return false; return true; } CDecoder::CDecoder(bool multiThread) { #ifndef _ST_MODE multiThread = true; #endif _multiThread = multiThread; _bindInfoExPrevIsDefined = false; } HRESULT CDecoder::Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folderInfo, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ) { if (!folderInfo.CheckStructure()) return E_NOTIMPL; #ifndef _NO_CRYPTO passwordIsDefined = false; #endif CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CLockedInStream lockedInStream; lockedInStream.Init(inStream); for (int j = 0; j < folderInfo.PackStreams.Size(); j++) { CLockedSequentialInStreamImp *lockedStreamImpSpec = new CLockedSequentialInStreamImp; CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec; lockedStreamImpSpec->Init(&lockedInStream, startPos); startPos += packSizes[j]; CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<ISequentialInStream> inStream = streamSpec; streamSpec->SetStream(lockedStreamImp); streamSpec->Init(packSizes[j]); inStreams.Add(inStream); } int numCoders = folderInfo.Coders.Size(); CBindInfoEx bindInfo; ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo); bool createNewCoders; if (!_bindInfoExPrevIsDefined) createNewCoders = true; else createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev); if (createNewCoders) { int i; _decoders.Clear(); // _decoders2.Clear(); _mixerCoder.Release(); if (_multiThread) { _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderMTSpec; _mixerCoderCommon = _mixerCoderMTSpec; } else { #ifdef _ST_MODE _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST; _mixerCoder = _mixerCoderSTSpec; _mixerCoderCommon = _mixerCoderSTSpec; #endif } RINOK(_mixerCoderCommon->SetBindInfo(bindInfo)); for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<ICompressCoder> decoder; CMyComPtr<ICompressCoder2> decoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS coderInfo.MethodID, decoder, decoder2, false)); CMyComPtr<IUnknown> decoderUnknown; if (coderInfo.IsSimpleCoder()) { if (decoder == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder; if (_multiThread) _mixerCoderMTSpec->AddCoder(decoder); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder(decoder, false); #endif } else { if (decoder2 == 0) return E_NOTIMPL; decoderUnknown = (IUnknown *)decoder2; if (_multiThread) _mixerCoderMTSpec->AddCoder2(decoder2); #ifdef _ST_MODE else _mixerCoderSTSpec->AddCoder2(decoder2, false); #endif } _decoders.Add(decoderUnknown); #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif } _bindInfoExPrev = bindInfo; _bindInfoExPrevIsDefined = true; } int i; _mixerCoderCommon->ReInit(); UInt32 packStreamIndex = 0, unpackStreamIndex = 0; UInt32 coderIndex = 0; // UInt32 coder2Index = 0; for (i = 0; i < numCoders; i++) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; CMyComPtr<IUnknown> &decoder = _decoders[coderIndex]; { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (setDecoderProperties) { const CByteBuffer &props = coderInfo.Props; size_t size = props.GetCapacity(); if (size > 0xFFFFFFFF) return E_NOTIMPL; if (size > 0) { RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size)); } } } #ifdef COMPRESS_MT if (mtMode) { CMyComPtr<ICompressSetCoderMt> setCoderMt; decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(numThreads)); } } #endif #ifndef _NO_CRYPTO { CMyComPtr<ICryptoSetPassword> cryptoSetPassword; decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { if (getTextPassword == 0) return E_FAIL; CMyComBSTR passwordBSTR; RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR)); CByteBuffer buffer; passwordIsDefined = true; const UString password(passwordBSTR); const UInt32 sizeInBytes = password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < password.Length(); i++) { wchar_t c = password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } } #endif coderIndex++; UInt32 numInStreams = (UInt32)coderInfo.NumInStreams; UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams; CRecordVector<const UInt64 *> packSizesPointers; CRecordVector<const UInt64 *> unpackSizesPointers; packSizesPointers.Reserve(numInStreams); unpackSizesPointers.Reserve(numOutStreams); UInt32 j; for (j = 0; j < numOutStreams; j++, unpackStreamIndex++) unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]); for (j = 0; j < numInStreams; j++, packStreamIndex++) { int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex); if (bindPairIndex >= 0) packSizesPointers.Add( &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]); else { int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex); if (index < 0) return E_FAIL; packSizesPointers.Add(&packSizes[index]); } } _mixerCoderCommon->SetCoderInfo(i, &packSizesPointers.Front(), &unpackSizesPointers.Front()); } UInt32 mainCoder, temp; bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp); if (_multiThread) _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder); /* else _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);; */ if (numCoders == 0) return 0; CRecordVector<ISequentialInStream *> inStreamPointers; inStreamPointers.Reserve(inStreams.Size()); for (i = 0; i < inStreams.Size(); i++) inStreamPointers.Add(inStreams[i]); ISequentialOutStream *outStreamPointer = outStream; return _mixerCoder->Code(&inStreamPointers.Front(), NULL, inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress); } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zDecode.h ================================================ // 7zDecode.h #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "../../IStream.h" #include "../../IPassword.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "../../Common/CreateCoder.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CBindInfoEx: public NCoderMixer::CBindInfo { CRecordVector<CMethodId> CoderMethodIDs; void Clear() { CBindInfo::Clear(); CoderMethodIDs.Clear(); } }; class CDecoder { bool _bindInfoExPrevIsDefined; CBindInfoEx _bindInfoExPrev; bool _multiThread; #ifdef _ST_MODE NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec; #endif NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec; NCoderMixer::CCoderMixer2 *_mixerCoderCommon; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CMyComPtr<IUnknown> > _decoders; // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2; public: CDecoder(bool multiThread); HRESULT Decode( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, UInt64 startPos, const UInt64 *packSizes, const CFolder &folder, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPasswordSpec, bool &passwordIsDefined #endif #ifdef COMPRESS_MT , bool mtMode, UInt32 numThreads #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zEncode.cpp ================================================ // Encode.cpp #include "StdAfx.h" #include "7zEncode.h" #include "7zSpecStream.h" #include "../../IPassword.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" #include "../../Common/InOutTempBuffer.h" #include "../../Common/StreamObjects.h" #include "../../Common/CreateCoder.h" #include "../../Common/FilterCoder.h" static const UInt64 k_AES = 0x06F10701; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; namespace NArchive { namespace N7z { static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, const CRecordVector<CMethodId> decompressionMethods, CFolder &folder) { folder.Coders.Clear(); // bindInfo.CoderMethodIDs.Clear(); // folder.OutStreams.Clear(); folder.PackStreams.Clear(); folder.BindPairs.Clear(); int i; for (i = 0; i < bindInfo.BindPairs.Size(); i++) { CBindPair bindPair; bindPair.InIndex = bindInfo.BindPairs[i].InIndex; bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; folder.BindPairs.Add(bindPair); } for (i = 0; i < bindInfo.Coders.Size(); i++) { CCoderInfo coderInfo; const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; coderInfo.MethodID = decompressionMethods[i]; folder.Coders.Add(coderInfo); } for (i = 0; i < bindInfo.InStreams.Size(); i++) folder.PackStreams.Add(bindInfo.InStreams[i]); } HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; _mixerCoder = _mixerCoderSpec; RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); for (int i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; _codersInfo.Add(CCoderInfo()); CCoderInfo &encodingInfo = _codersInfo.Back(); encodingInfo.MethodID = methodFull.Id; CMyComPtr<ICompressCoder> encoder; CMyComPtr<ICompressCoder2> encoder2; RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS methodFull.Id, encoder, encoder2, true)); if (!encoder && !encoder2) return E_FAIL; CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; #ifdef COMPRESS_MT { CMyComPtr<ICompressSetCoderMt> setCoderMt; encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); if (setCoderMt) { RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads)); } } #endif RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon)); /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); if (resetSalt != NULL) { resetSalt->ResetSalt(); } */ #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); } #endif CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { CByteBuffer buffer; const UInt32 sizeInBytes = _options.Password.Length() * 2; buffer.SetCapacity(sizeInBytes); for (int i = 0; i < _options.Password.Length(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); } if (encoder) _mixerCoderSpec->AddCoder(encoder); else _mixerCoderSpec->AddCoder2(encoder2); } return S_OK; } HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); if (_mixerCoderSpec == NULL) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } _mixerCoderSpec->ReInit(); // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); CObjectVector<CInOutTempBuffer> inOutTempBuffers; CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; int numMethods = _bindInfo.Coders.Size(); int i; for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { inOutTempBuffers.Add(CInOutTempBuffer()); inOutTempBuffers.Back().Create(); inOutTempBuffers.Back().InitWriting(); } for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); tempBufferSpecs.Add(tempBufferSpec); } for (i = 0; i < numMethods; i++) _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); if (_bindInfo.InStreams.IsEmpty()) return E_FAIL; UInt32 mainCoderIndex, mainStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); if (inStreamSize != NULL) { CRecordVector<const UInt64 *> sizePointers; for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) if (i == mainStreamIndex) sizePointers.Add(inStreamSize); else sizePointers.Add(NULL); _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); } // UInt64 outStreamStartPos; // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; inStreamSizeCountSpec->Init(inStream); outStreamSizeCountSpec->SetStream(outStream); outStreamSizeCountSpec->Init(); CRecordVector<ISequentialInStream *> inStreamPointers; CRecordVector<ISequentialOutStream *> outStreamPointers; inStreamPointers.Add(inStreamSizeCount); outStreamPointers.Add(outStreamSizeCount); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) outStreamPointers.Add(tempBuffers[i - 1]); for (i = 0; i < _codersInfo.Size(); i++) { CCoderInfo &encodingInfo = _codersInfo[i]; CMyComPtr<ICryptoResetInitVector> resetInitVector; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); if (resetInitVector != NULL) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); writeCoderProperties->WriteCoderProperties(outStream); size_t size = outStreamSpec->GetSize(); encodingInfo.Props.SetCapacity(size); memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size); } } UInt32 progressIndex = mainCoderIndex; for (i = 0; i < _codersInfo.Size(); i++) { const CCoderInfo &e = _codersInfo[i]; if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size()) progressIndex = i + 1; } _mixerCoderSpec->SetProgressCoderIndex(progressIndex); RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); packSizes.Add(outStreamSizeCountSpec->GetSize()); for (i = 1; i < _bindInfo.OutStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; inOutTempBuffer.FlushWrite(); inOutTempBuffer.InitReading(); inOutTempBuffer.WriteToStream(outStream); packSizes.Add(inOutTempBuffer.GetDataSize()); } for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) { int binder = _bindInfo.FindBinderForInStream( _bindReverseConverter->DestOutToSrcInMap[i]); UInt64 streamSize; if (binder < 0) streamSize = inStreamSizeCountSpec->GetSize(); else streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); folderItem.UnpackSizes.Add(streamSize); } for (i = numMethods - 1; i >= 0; i--) folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): _bindReverseConverter(0), _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; _mixerCoderSpec = NULL; } HRESULT CEncoder::EncoderConstr() { if (_constructed) return S_OK; if (_options.Methods.IsEmpty()) { // it has only password method; if (!_options.PasswordIsDefined) throw 1; if (!_options.Binds.IsEmpty()) throw 1; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = 1; coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.InStreams.Add(0); _bindInfo.OutStreams.Add(0); } else { UInt32 numInStreams = 0, numOutStreams = 0; int i; for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; NCoderMixer::CCoderStreamsInfo coderStreamsInfo; coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; if (_options.Binds.IsEmpty()) { if (i < _options.Methods.Size() - 1) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; bindPair.OutIndex = numOutStreams; _bindInfo.BindPairs.Add(bindPair); } else _bindInfo.OutStreams.Insert(0, numOutStreams); for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) _bindInfo.OutStreams.Add(numOutStreams + j); } numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; _bindInfo.Coders.Add(coderStreamsInfo); } if (!_options.Binds.IsEmpty()) { for (i = 0; i < _options.Binds.Size(); i++) { NCoderMixer::CBindPair bindPair; const CBind &bind = _options.Binds[i]; bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; _bindInfo.BindPairs.Add(bindPair); } for (i = 0; i < (int)numOutStreams; i++) if (_bindInfo.FindBinderForOutStream(i) == -1) _bindInfo.OutStreams.Add(i); } for (i = 0; i < (int)numInStreams; i++) if (_bindInfo.FindBinderForInStream(i) == -1) _bindInfo.InStreams.Add(i); if (_bindInfo.InStreams.IsEmpty()) throw 1; // this is error // Make main stream first in list int inIndex = _bindInfo.InStreams[0]; for (;;) { UInt32 coderIndex, coderStreamIndex; _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); int binder = _bindInfo.FindBinderForOutStream(outIndex); if (binder >= 0) { inIndex = _bindInfo.BindPairs[binder].InIndex; continue; } for (i = 0; i < _bindInfo.OutStreams.Size(); i++) if (_bindInfo.OutStreams[i] == outIndex) { _bindInfo.OutStreams.Delete(i); _bindInfo.OutStreams.Insert(0, outIndex); break; } break; } if (_options.PasswordIsDefined) { int numCryptoStreams = _bindInfo.OutStreams.Size(); for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CBindPair bindPair; bindPair.InIndex = numInStreams + i; bindPair.OutIndex = _bindInfo.OutStreams[i]; _bindInfo.BindPairs.Add(bindPair); } _bindInfo.OutStreams.Clear(); /* if (numCryptoStreams == 0) numCryptoStreams = 1; */ for (i = 0; i < numCryptoStreams; i++) { NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; method.NumInStreams = 1; method.NumOutStreams = 1; coderStreamsInfo.NumInStreams = method.NumOutStreams; coderStreamsInfo.NumOutStreams = method.NumInStreams; method.Id = k_AES; _options.Methods.Add(method); _bindInfo.Coders.Add(coderStreamsInfo); _bindInfo.OutStreams.Add(numOutStreams + i); } } } for (int i = _options.Methods.Size() - 1; i >= 0; i--) { const CMethodFull &methodFull = _options.Methods[i]; _decompressionMethods.Add(methodFull.Id); } _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); _constructed = true; return S_OK; } CEncoder::~CEncoder() { delete _bindReverseConverter; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zEncode.h ================================================ // 7zEncode.h #ifndef __7Z_ENCODE_H #define __7Z_ENCODE_H // #include "../../Common/StreamObjects.h" #include "7zCompressionMode.h" #include "../Common/CoderMixer2.h" #include "../Common/CoderMixer2MT.h" #ifdef _ST_MODE #include "../Common/CoderMixer2ST.h" #endif #include "7zItem.h" #include "../../Common/CreateCoder.h" namespace NArchive { namespace N7z { class CEncoder { NCoderMixer::CCoderMixer2MT *_mixerCoderSpec; CMyComPtr<ICompressCoder2> _mixerCoder; CObjectVector<CCoderInfo> _codersInfo; CCompressionMethodMode _options; NCoderMixer::CBindInfo _bindInfo; NCoderMixer::CBindInfo _decompressBindInfo; NCoderMixer::CBindReverseConverter *_bindReverseConverter; CRecordVector<CMethodId> _decompressionMethods; HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce); bool _constructed; public: CEncoder(const CCompressionMethodMode &options); ~CEncoder(); HRESULT EncoderConstr(); HRESULT Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zExtract.cpp ================================================ // 7zExtract.cpp #include "StdAfx.h" #include "7zHandler.h" #include "7zFolderOutStream.h" #include "7zDecode.h" // #include "7z1Decode.h" #include "../../../Common/ComTry.h" #include "../../Common/StreamObjects.h" #include "../../Common/ProgressUtils.h" #include "../../Common/LimitedStreams.h" namespace NArchive { namespace N7z { struct CExtractFolderInfo { #ifdef _7Z_VOL int VolumeIndex; #endif CNum FileIndex; CNum FolderIndex; CBoolVector ExtractStatuses; UInt64 UnpackSize; CExtractFolderInfo( #ifdef _7Z_VOL int volumeIndex, #endif CNum fileIndex, CNum folderIndex): #ifdef _7Z_VOL VolumeIndex(volumeIndex), #endif FileIndex(fileIndex), FolderIndex(folderIndex), UnpackSize(0) { if (fileIndex != kNumNoIndex) { ExtractStatuses.Reserve(1); ExtractStatuses.Add(true); } }; }; STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) { COM_TRY_BEGIN bool testMode = (testModeSpec != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; UInt64 importantTotalUnpacked = 0; bool allFilesMode = (numItems == UInt32(-1)); if (allFilesMode) numItems = #ifdef _7Z_VOL _refs.Size(); #else _db.Files.Size(); #endif if(numItems == 0) return S_OK; /* if(_volumes.Size() != 1) return E_FAIL; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; IInStream *_inStream = volume.Stream; */ CObjectVector<CExtractFolderInfo> extractFolderInfoVector; for(UInt32 ii = 0; ii < numItems; ii++) { // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; UInt32 ref2Index = allFilesMode ? ii : indices[ii]; // const CRef2 &ref2 = _refs[ref2Index]; // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) { #ifdef _7Z_VOL // const CRef &ref = ref2.Refs[ri]; const CRef &ref = _refs[ref2Index]; int volumeIndex = ref.VolumeIndex; const CVolume &volume = _volumes[volumeIndex]; const CArchiveDatabaseEx &db = volume.Database; UInt32 fileIndex = ref.ItemIndex; #else const CArchiveDatabaseEx &db = _db; UInt32 fileIndex = ref2Index; #endif CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; if (folderIndex == kNumNoIndex) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif fileIndex, kNumNoIndex)); continue; } if (extractFolderInfoVector.IsEmpty() || folderIndex != extractFolderInfoVector.Back().FolderIndex #ifdef _7Z_VOL || volumeIndex != extractFolderInfoVector.Back().VolumeIndex #endif ) { extractFolderInfoVector.Add(CExtractFolderInfo( #ifdef _7Z_VOL volumeIndex, #endif kNumNoIndex, folderIndex)); const CFolder &folderInfo = db.Folders[folderIndex]; UInt64 unpackSize = folderInfo.GetUnpackSize(); importantTotalUnpacked += unpackSize; extractFolderInfoVector.Back().UnpackSize = unpackSize; } CExtractFolderInfo &efi = extractFolderInfoVector.Back(); // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; CNum startIndex = db.FolderStartFileIndex[folderIndex]; for (CNum index = efi.ExtractStatuses.Size(); index <= fileIndex - startIndex; index++) { // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; // Count partial_folder_size // efi.UnpackSize += unpackSize; // importantTotalUnpacked += unpackSize; efi.ExtractStatuses.Add(index == fileIndex - startIndex); } } } extractCallback->SetTotal(importantTotalUnpacked); CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); // CDecoder1 decoder; UInt64 currentTotalPacked = 0; UInt64 currentTotalUnpacked = 0; UInt64 totalFolderUnpacked; UInt64 totalFolderPacked; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for(int i = 0; i < extractFolderInfoVector.Size(); i++, currentTotalUnpacked += totalFolderUnpacked, currentTotalPacked += totalFolderPacked) { lps->OutSize = currentTotalUnpacked; lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); const CExtractFolderInfo &efi = extractFolderInfoVector[i]; totalFolderUnpacked = efi.UnpackSize; totalFolderPacked = 0; CFolderOutStream *folderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(folderOutStream); #ifdef _7Z_VOL const CVolume &volume = _volumes[efi.VolumeIndex]; const CArchiveDatabaseEx &db = volume.Database; #else const CArchiveDatabaseEx &db = _db; #endif CNum startIndex; if (efi.FileIndex != kNumNoIndex) startIndex = efi.FileIndex; else startIndex = db.FolderStartFileIndex[efi.FolderIndex]; HRESULT result = folderOutStream->Init(&db, #ifdef _7Z_VOL volume.StartRef2Index, #else 0, #endif startIndex, &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); RINOK(result); if (efi.FileIndex != kNumNoIndex) continue; CNum folderIndex = efi.FolderIndex; const CFolder &folderInfo = db.Folders[folderIndex]; totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (extractCallback) extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); #endif try { #ifndef _NO_CRYPTO bool passwordIsDefined; #endif HRESULT result = decoder.Decode( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume.Stream, #else _inStream, #endif folderStartPackPos, &db.PackSizes[packStreamIndex], folderInfo, outStream, progress #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , true, _numThreads #endif ); if (result == S_FALSE) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } if (result == E_NOTIMPL) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); continue; } if (result != S_OK) return result; if (folderOutStream->WasWritingFinished() != S_OK) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } catch(...) { RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); continue; } } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zFolderInStream.cpp ================================================ // 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { CFolderInStream::CFolderInStream() { _inStreamWithHashSpec = new CSequentialInStreamWithCRC; _inStreamWithHash = _inStreamWithHashSpec; } void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles) { _updateCallback = updateCallback; _numFiles = numFiles; _fileIndex = 0; _fileIndices = fileIndices; Processed.Clear(); CRCs.Clear(); Sizes.Clear(); _fileIsOpen = false; _currentSizeIsDefined = false; } HRESULT CFolderInStream::OpenStream() { _filePos = 0; while (_fileIndex < _numFiles) { _currentSizeIsDefined = false; CMyComPtr<ISequentialInStream> stream; HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); if (result != S_OK && result != S_FALSE) return result; _fileIndex++; _inStreamWithHashSpec->SetStream(stream); _inStreamWithHashSpec->Init(); if (!stream) { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); Sizes.Add(0); Processed.Add(result == S_OK); AddDigest(); continue; } CMyComPtr<IStreamGetSize> streamGetSize; if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK) { if(streamGetSize) { _currentSizeIsDefined = true; RINOK(streamGetSize->GetSize(&_currentSize)); } } _fileIsOpen = true; return S_OK; } return S_OK; } void CFolderInStream::AddDigest() { CRCs.Add(_inStreamWithHashSpec->GetCRC()); } HRESULT CFolderInStream::CloseStream() { RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); _inStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; Processed.Add(true); Sizes.Add(_filePos); AddDigest(); return S_OK; } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0) { if (_fileIsOpen) { UInt32 localProcessedSize; RINOK(_inStreamWithHash->Read( ((Byte *)data) + realProcessedSize, size, &localProcessedSize)); if (localProcessedSize == 0) { RINOK(CloseStream()); continue; } realProcessedSize += localProcessedSize; _filePos += localProcessedSize; size -= localProcessedSize; break; } else { RINOK(OpenStream()); } } if (processedSize != 0) *processedSize = realProcessedSize; return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; int subStreamIndex = (int)subStream; if (subStreamIndex < 0 || subStream > Sizes.Size()) return E_FAIL; if (subStreamIndex < Sizes.Size()) { *value= Sizes[subStreamIndex]; return S_OK; } if (!_currentSizeIsDefined) return S_FALSE; *value = _currentSize; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zFolderInStream.h ================================================ // 7z/FolderInStream.h #ifndef __7Z_FOLDERINSTREAM_H #define __7Z_FOLDERINSTREAM_H #include "7zItem.h" #include "7zHeader.h" #include "../IArchive.h" #include "../Common/InStreamWithCRC.h" #include "../../IStream.h" #include "../../ICoder.h" namespace NArchive { namespace N7z { class CFolderInStream: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) CFolderInStream(); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); private: CSequentialInStreamWithCRC *_inStreamWithHashSpec; CMyComPtr<ISequentialInStream> _inStreamWithHash; CMyComPtr<IArchiveUpdateCallback> _updateCallback; bool _currentSizeIsDefined; UInt64 _currentSize; bool _fileIsOpen; UInt64 _filePos; const UInt32 *_fileIndices; UInt32 _numFiles; UInt32 _fileIndex; HRESULT OpenStream(); HRESULT CloseStream(); void AddDigest(); public: void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles); CRecordVector<bool> Processed; CRecordVector<UInt32> CRCs; CRecordVector<UInt64> Sizes; UInt64 GetFullSize() const { UInt64 size = 0; for (int i = 0; i < Sizes.Size(); i++) size += Sizes[i]; return size; } }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zFolderOutStream.cpp ================================================ // 7zFolderOutStream.cpp #include "StdAfx.h" #include "7zFolderOutStream.h" namespace NArchive { namespace N7z { CFolderOutStream::CFolderOutStream() { _outStreamWithHashSpec = new COutStreamWithCRC; _outStreamWithHash = _outStreamWithHashSpec; } HRESULT CFolderOutStream::Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc) { _archiveDatabase = archiveDatabase; _ref2Offset = ref2Offset; _startIndex = startIndex; _extractStatuses = extractStatuses; _extractCallback = extractCallback; _testMode = testMode; _checkCrc = checkCrc; _currentIndex = 0; _fileIsOpen = false; return WriteEmptyFiles(); } HRESULT CFolderOutStream::OpenFile() { Int32 askMode; if((*_extractStatuses)[_currentIndex]) askMode = _testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; else askMode = NArchive::NExtract::NAskMode::kSkip; CMyComPtr<ISequentialOutStream> realOutStream; UInt32 index = _startIndex + _currentIndex; RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode)); _outStreamWithHashSpec->SetStream(realOutStream); _outStreamWithHashSpec->Init(_checkCrc); if (askMode == NArchive::NExtract::NAskMode::kExtract && (!realOutStream)) { const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir) askMode = NArchive::NExtract::NAskMode::kSkip; } return _extractCallback->PrepareOperation(askMode); } HRESULT CFolderOutStream::WriteEmptyFiles() { for(;_currentIndex < _extractStatuses->Size(); _currentIndex++) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0) return S_OK; RINOK(OpenFile()); RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); _outStreamWithHashSpec->ReleaseStream(); } return S_OK; } STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { UInt32 index = _startIndex + _currentIndex; const CFileItem &fi = _archiveDatabase->Files[index]; UInt64 fileSize = fi.Size; UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, UInt64(size - realProcessedSize)); UInt32 processedSizeLocal; RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal)); _filePos += processedSizeLocal; realProcessedSize += processedSizeLocal; if (_filePos == fileSize) { bool digestsAreEqual; if (fi.CrcDefined && _checkCrc) digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC(); else digestsAreEqual = true; RINOK(_extractCallback->SetOperationResult( digestsAreEqual ? NArchive::NExtract::NOperationResult::kOK : NArchive::NExtract::NOperationResult::kCRCError)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } if (realProcessedSize == size) { if (processedSize != NULL) *processedSize = realProcessedSize; return WriteEmptyFiles(); } } else { RINOK(OpenFile()); _fileIsOpen = true; _filePos = 0; } } if (processedSize != NULL) *processedSize = size; return S_OK; } HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult) { while(_currentIndex < _extractStatuses->Size()) { if (_fileIsOpen) { RINOK(_extractCallback->SetOperationResult(resultEOperationResult)); _outStreamWithHashSpec->ReleaseStream(); _fileIsOpen = false; _currentIndex++; } else { RINOK(OpenFile()); _fileIsOpen = true; } } return S_OK; } HRESULT CFolderOutStream::WasWritingFinished() { if (_currentIndex == _extractStatuses->Size()) return S_OK; return E_FAIL; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zFolderOutStream.h ================================================ // 7zFolderOutStream.h #ifndef __7Z_FOLDEROUTSTREAM_H #define __7Z_FOLDEROUTSTREAM_H #include "7zIn.h" #include "../../IStream.h" #include "../IArchive.h" #include "../Common/OutStreamWithCRC.h" namespace NArchive { namespace N7z { class CFolderOutStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP CFolderOutStream(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: COutStreamWithCRC *_outStreamWithHashSpec; CMyComPtr<ISequentialOutStream> _outStreamWithHash; const CArchiveDatabaseEx *_archiveDatabase; const CBoolVector *_extractStatuses; UInt32 _startIndex; UInt32 _ref2Offset; int _currentIndex; // UInt64 _currentDataPos; CMyComPtr<IArchiveExtractCallback> _extractCallback; bool _testMode; bool _fileIsOpen; bool _checkCrc; UInt64 _filePos; HRESULT OpenFile(); HRESULT WriteEmptyFiles(); public: HRESULT Init( const CArchiveDatabaseEx *archiveDatabase, UInt32 ref2Offset, UInt32 startIndex, const CBoolVector *extractStatuses, IArchiveExtractCallback *extractCallback, bool testMode, bool checkCrc); HRESULT FlushCorrupted(Int32 resultEOperationResult); HRESULT WasWritingFinished(); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zHandler.cpp ================================================ // 7zHandler.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/CpuArch.h" } #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../Common/ItemNameUtils.h" #include "7zHandler.h" #include "7zProperties.h" #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #include "../Common/ParseProperties.h" #endif #endif using namespace NWindows; extern UString ConvertMethodIdToString(UInt64 id); namespace NArchive { namespace N7z { CHandler::CHandler() { _crcSize = 4; #ifndef _NO_CRYPTO _passwordIsDefined = false; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT _numThreads = NSystem::GetNumberOfProcessors(); #endif #else Init(); #endif } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _db.Files.Size(); return S_OK; } #ifdef _SFX IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) { return E_NOTIMPL; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) { return E_NOTIMPL; } #else STATPROPSTG kArcProps[] = { { NULL, kpidMethod, VT_BSTR}, { NULL, kpidSolid, VT_BOOL}, { NULL, kpidNumBlocks, VT_UI4}, { NULL, kpidPhySize, VT_UI8}, { NULL, kpidHeadersSize, VT_UI8}, { NULL, kpidOffset, VT_UI8} }; STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; switch(propID) { case kpidMethod: { UString resString; CRecordVector<UInt64> ids; int i; for (i = 0; i < _db.Folders.Size(); i++) { const CFolder &f = _db.Folders[i]; for (int j = f.Coders.Size() - 1; j >= 0; j--) ids.AddToUniqueSorted(f.Coders[j].MethodID); } for (i = 0; i < ids.Size(); i++) { UInt64 id = ids[i]; UString methodName; /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); if (methodName.IsEmpty()) methodName = ConvertMethodIdToString(id); if (!resString.IsEmpty()) resString += L' '; resString += methodName; } prop = resString; break; } case kpidSolid: prop = _db.IsSolid(); break; case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; case kpidHeadersSize: prop = _db.HeadersSize; break; case kpidPhySize: prop = _db.PhySize; break; case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; } prop.Detach(value); return S_OK; COM_TRY_END } IMP_IInArchive_ArcProps #endif static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) { UInt64 value; if (v.GetItem(index, value)) { FILETIME ft; ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); prop = ft; } } #ifndef _SFX static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString GetStringForSizeValue(UInt32 value) { for (int i = 31; i >= 0; i--) if ((UInt32(1) << i) == value) return ConvertUInt32ToString(i); UString result; if (value % (1 << 20) == 0) { result += ConvertUInt32ToString(value >> 20); result += L"m"; } else if (value % (1 << 10) == 0) { result += ConvertUInt32ToString(value >> 10); result += L"k"; } else { result += ConvertUInt32ToString(value); result += L"b"; } return result; } static const UInt64 k_Copy = 0x0; static const UInt64 k_LZMA = 0x030101; static const UInt64 k_PPMD = 0x030401; static wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); } static inline UString GetHex2(Byte value) { UString result; result += GetHex((Byte)(value >> 4)); result += GetHex((Byte)(value & 0xF)); return result; } #endif static const UInt64 k_AES = 0x06F10701; bool CHandler::IsEncrypted(UInt32 index2) const { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) if (folderInfo.Coders[i].MethodID == k_AES) return true; } return false; } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; /* const CRef2 &ref2 = _refs[index]; if (ref2.Refs.IsEmpty()) return E_FAIL; const CRef &ref = ref2.Refs.Front(); */ const CFileItem &item = _db.Files[index]; UInt32 index2 = index; switch(propID) { case kpidPath: if (!item.Name.IsEmpty()) prop = NItemName::GetOSName(item.Name); break; case kpidIsDir: prop = item.IsDir; break; case kpidSize: { prop = item.Size; // prop = ref2.Size; break; } case kpidPackSize: { // prop = ref2.PackSize; { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) prop = _db.GetFolderFullPackSize(folderIndex); /* else prop = (UInt64)0; */ } else prop = (UInt64)0; } break; } case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; case kpidEncrypted: prop = IsEncrypted(index2); break; case kpidIsAnti: prop = _db.IsItemAnti(index2); break; #ifndef _SFX case kpidMethod: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; UString methodsString; for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderInfo &coderInfo = folderInfo.Coders[i]; if (!methodsString.IsEmpty()) methodsString += L' '; { UString methodName; bool methodIsKnown = FindMethod( EXTERNAL_CODECS_VARS coderInfo.MethodID, methodName); if (methodIsKnown) { methodsString += methodName; if (coderInfo.MethodID == k_LZMA) { if (coderInfo.Props.GetCapacity() >= 5) { methodsString += L":"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_PPMD) { if (coderInfo.Props.GetCapacity() >= 5) { Byte order = *(const Byte *)coderInfo.Props; methodsString += L":o"; methodsString += ConvertUInt32ToString(order); methodsString += L":mem"; UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); methodsString += GetStringForSizeValue(dicSize); } } else if (coderInfo.MethodID == k_AES) { if (coderInfo.Props.GetCapacity() >= 1) { methodsString += L":"; const Byte *data = (const Byte *)coderInfo.Props; Byte firstByte = *data++; UInt32 numCyclesPower = firstByte & 0x3F; methodsString += ConvertUInt32ToString(numCyclesPower); /* if ((firstByte & 0xC0) != 0) { methodsString += L":"; return S_OK; UInt32 saltSize = (firstByte >> 7) & 1; UInt32 ivSize = (firstByte >> 6) & 1; if (coderInfo.Props.GetCapacity() >= 2) { Byte secondByte = *data++; saltSize += (secondByte >> 4); ivSize += (secondByte & 0x0F); } } */ } } else { if (coderInfo.Props.GetCapacity() > 0) { methodsString += L":["; for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) { if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) { methodsString += L".."; break; } else methodsString += GetHex2(coderInfo.Props[bi]); } methodsString += L"]"; } } } else { methodsString += ConvertMethodIdToString(coderInfo.MethodID); } } } prop = methodsString; } } break; case kpidBlock: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) prop = (UInt32)folderIndex; } break; case kpidPackedSize0: case kpidPackedSize1: case kpidPackedSize2: case kpidPackedSize3: case kpidPackedSize4: { CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; if (folderIndex != kNumNoIndex) { const CFolder &folderInfo = _db.Folders[folderIndex]; if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) { prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); } else prop = (UInt64)0; } else prop = (UInt64)0; } break; #endif } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); #ifndef _SFX _fileInfoPopIDs.Clear(); #endif try { CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; #ifndef _NO_CRYPTO CMyComPtr<ICryptoGetTextPassword> getTextPassword; if (openArchiveCallback) { openArchiveCallbackTemp.QueryInterface( IID_ICryptoGetTextPassword, &getTextPassword); } #endif CInArchive archive; RINOK(archive.Open(stream, maxCheckStartPosition)); #ifndef _NO_CRYPTO _passwordIsDefined = false; UString password; #endif HRESULT result = archive.ReadDatabase( EXTERNAL_CODECS_VARS _db #ifndef _NO_CRYPTO , getTextPassword, _passwordIsDefined #endif ); RINOK(result); _db.Fill(); _inStream = stream; } catch(...) { Close(); return S_FALSE; } // _inStream = stream; #ifndef _SFX FillPopIDs(); #endif return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { COM_TRY_BEGIN _inStream.Release(); _db.Clear(); return S_OK; COM_TRY_END } #ifdef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN #ifdef COMPRESS_MT const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); _numThreads = numProcessors; #endif for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; UInt32 number; int index = ParseStringToUInt32(name, number); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif continue; } else return E_INVALIDARG; } } return S_OK; COM_TRY_END } #endif #endif IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zHandler.h ================================================ // 7z/Handler.h #ifndef __7Z_HANDLER_H #define __7Z_HANDLER_H #include "../../ICoder.h" #include "../IArchive.h" #include "7zIn.h" #include "7zCompressionMode.h" #include "../../Common/CreateCoder.h" #ifndef EXTRACT_ONLY #include "../Common/HandlerOut.h" #endif namespace NArchive { namespace N7z { #ifndef __7Z_SET_PROPERTIES #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT #define __7Z_SET_PROPERTIES #endif #else #define __7Z_SET_PROPERTIES #endif #endif class CHandler: #ifndef EXTRACT_ONLY public NArchive::COutHandler, #endif public IInArchive, #ifdef __7Z_SET_PROPERTIES public ISetProperties, #endif #ifndef EXTRACT_ONLY public IOutArchive, #endif PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IInArchive) #ifdef __7Z_SET_PROPERTIES MY_QUERYINTERFACE_ENTRY(ISetProperties) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY(IOutArchive) #endif QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE INTERFACE_IInArchive(;) #ifdef __7Z_SET_PROPERTIES STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); #endif #ifndef EXTRACT_ONLY INTERFACE_IOutArchive(;) #endif DECL_ISetCompressCodecsInfo CHandler(); private: CMyComPtr<IInStream> _inStream; NArchive::N7z::CArchiveDatabaseEx _db; #ifndef _NO_CRYPTO bool _passwordIsDefined; #endif #ifdef EXTRACT_ONLY #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; #else CRecordVector<CBind> _binds; HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback); HRESULT SetCompressionMethod(CCompressionMethodMode &method, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); HRESULT SetCompressionMethod( CCompressionMethodMode &method, CCompressionMethodMode &headerMethod); #endif bool IsEncrypted(UInt32 index2) const; #ifndef _SFX CRecordVector<UInt64> _fileInfoPopIDs; void FillPopIDs(); #endif DECL_EXTERNAL_CODECS_VARS }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zHandlerOut.cpp ================================================ // 7zHandlerOut.cpp #include "StdAfx.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" #include "../../ICoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/ParseProperties.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" using namespace NWindows; namespace NArchive { namespace N7z { static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const UInt32 kLzmaAlgorithmX5 = 1; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5; static inline bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); } STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback) { CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); methodMode.PasswordIsDefined = IntToBool(passwordIsDefined); if (methodMode.PasswordIsDefined) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod) { HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = (UInt32)kNumFastBytesForHeaders; oneMethodInfo.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = (UInt32)kDictionaryForHeaders; oneMethodInfo.Props.Add(prop); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK; } HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; SetCompressionMethod2(oneMethodInfo #ifdef COMPRESS_MT , numThreads #endif ); if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; CMethodFull methodFull; if (!FindMethod( EXTERNAL_CODECS_VARS oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams)) return E_INVALIDARG; methodFull.Props = oneMethodInfo.Props; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.Props.Size(); j++) { const CProp &prop = methodFull.Props[j]; if ((prop.Id == NCoderPropID::kDictionarySize || prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK; } static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, bool writeTime, PROPID propID, UInt64 &ft, bool &ftDefined) { ft = 0; ftDefined = false; if (!writeTime) return S_OK; NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32); ftDefined = true; } else if (prop.vt != VT_EMPTY) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN const CArchiveDatabaseEx *db = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); db = &volume->Database; } #else if (_inStream != 0) db = &_db; #endif CObjectVector<CUpdateItem> updateItems; for (UInt32 i = 0; i < numItems; i++) { Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive)); CUpdateItem ui; ui.NewProperties = IntToBool(newProperties); ui.NewData = IntToBool(newData); ui.IndexInArchive = indexInArchive; ui.IndexInClient = i; ui.IsAnti = false; ui.Size = 0; if (ui.IndexInArchive != -1) { const CFileItem &fi = db->Files[ui.IndexInArchive]; ui.Name = fi.Name; ui.IsDir = fi.IsDir; ui.Size = fi.Size; ui.IsAnti = db->IsItemAnti(ui.IndexInArchive); ui.CTimeDefined = db->CTime.GetItem(ui.IndexInArchive, ui.CTime); ui.ATimeDefined = db->ATime.GetItem(ui.IndexInArchive, ui.ATime); ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime); } if (ui.NewProperties) { bool nameIsDefined; bool folderStatusIsDefined; { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) ui.AttribDefined = false; else if (prop.vt != VT_UI4) return E_INVALIDARG; else { ui.Attrib = prop.ulVal; ui.AttribDefined = true; } } // we need MTime to sort files. RINOK(GetTime(updateCallback, i, WriteCTime, kpidCTime, ui.CTime, ui.CTimeDefined)); RINOK(GetTime(updateCallback, i, WriteATime, kpidATime, ui.ATime, ui.ATimeDefined)); RINOK(GetTime(updateCallback, i, true, kpidMTime, ui.MTime, ui.MTimeDefined)); { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidPath, &prop)); if (prop.vt == VT_EMPTY) nameIsDefined = false; else if (prop.vt != VT_BSTR) return E_INVALIDARG; else { ui.Name = NItemName::MakeLegalName(prop.bstrVal); nameIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop)); if (prop.vt == VT_EMPTY) folderStatusIsDefined = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { ui.IsDir = (prop.boolVal != VARIANT_FALSE); folderStatusIsDefined = true; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) ui.IsAnti = false; else if (prop.vt != VT_BOOL) return E_INVALIDARG; else ui.IsAnti = (prop.boolVal != VARIANT_FALSE); } if (ui.IsAnti) { ui.AttribDefined = false; ui.CTimeDefined = false; ui.ATimeDefined = false; ui.MTimeDefined = false; ui.Size = 0; } if (!folderStatusIsDefined && ui.AttribDefined) ui.SetDirStatusFromAttrib(); } if (ui.NewData) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(i, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; ui.Size = (UInt64)prop.uhVal.QuadPart; if (ui.Size != 0 && ui.IsAnti) return E_INVALIDARG; } updateItems.Add(ui); } CCompressionMethodMode methodMode, headerMethod; RINOK(SetCompressionMethod(methodMode, headerMethod)); #ifdef COMPRESS_MT methodMode.NumThreads = _numThreads; headerMethod.NumThreads = 1; #endif RINOK(SetPassword(methodMode, updateCallback)); bool compressMainHeader = _compressHeaders; // check it bool encryptHeaders = false; if (methodMode.PasswordIsDefined) { if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef _NO_CRYPTO else encryptHeaders = _passwordIsDefined; #endif compressMainHeader = true; if(encryptHeaders) RINOK(SetPassword(headerMethod, updateCallback)); } if (numItems < 2) compressMainHeader = false; CUpdateOptions options; options.Method = &methodMode; options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : 0; options.UseFilters = _level != 0 && _autoFilter; options.MaxFilter = _level >= 8; options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.WriteCTime = WriteCTime; options.HeaderOptions.WriteATime = WriteATime; options.HeaderOptions.WriteMTime = WriteMTime; options.NumSolidFiles = _numSolidFiles; options.NumSolidBytes = _numSolidBytes; options.SolidExtension = _solidExtension; options.RemoveSfxBlock = _removeSfxBlock; options.VolumeMode = _volumeMode; COutArchive archive; CArchiveDatabase newDatabase; HRESULT res = Update( EXTERNAL_CODECS_VARS #ifdef _7Z_VOL volume ? volume->Stream: 0, volume ? db : 0, #else _inStream, db, #endif updateItems, archive, newDatabase, outStream, updateCallback, options); RINOK(res); updateItems.ClearAndFree(); return archive.WriteDatabase(EXTERNAL_CODECS_VARS newDatabase, options.HeaderMethod, options.HeaderOptions); COM_TRY_END } static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream) { stream = 0; int index = ParseStringToUInt32(srcString, coder); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); if (srcString[0] == 'S') { srcString.Delete(0); int index = ParseStringToUInt32(srcString, stream); if (index == 0) return E_INVALIDARG; srcString.Delete(0, index); } return S_OK; } static HRESULT GetBindInfo(UString &srcString, CBind &bind) { RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream)); if (srcString[0] != ':') return E_INVALIDARG; srcString.Delete(0); RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream)); if (!srcString.IsEmpty()) return E_INVALIDARG; return S_OK; } STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) { COM_TRY_BEGIN _binds.Clear(); BeforeSetProperty(); for (int i = 0; i < numProperties; i++) { UString name = names[i]; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; const PROPVARIANT &value = values[i]; if (name[0] == 'B') { name.Delete(0); CBind bind; RINOK(GetBindInfo(name, bind)); _binds.Add(bind); continue; } RINOK(SetProperty(name, value)); } return S_OK; COM_TRY_END } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zHeader.cpp ================================================ // 7z/Header.cpp #include "StdAfx.h" #include "7zHeader.h" namespace NArchive { namespace N7z { Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C}; #ifdef _7Z_VOL Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1}; #endif class SignatureInitializer { public: SignatureInitializer() { kSignature[0]--; #ifdef _7Z_VOL kFinishSignature[0]--; #endif }; } g_SignatureInitializer; }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zHeader.h ================================================ // 7z/7zHeader.h #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "../../../Common/Types.h" namespace NArchive { namespace N7z { const int kSignatureSize = 6; extern Byte kSignature[kSignatureSize]; // #define _7Z_VOL // 7z-MultiVolume is not finished yet. // It can work already, but I still do not like some // things of that new multivolume format. // So please keep it commented. #ifdef _7Z_VOL extern Byte kFinishSignature[kSignatureSize]; #endif struct CArchiveVersion { Byte Major; Byte Minor; }; const Byte kMajorVersion = 0; struct CStartHeader { UInt64 NextHeaderOffset; UInt64 NextHeaderSize; UInt32 NextHeaderCRC; }; const UInt32 kStartHeaderSize = 20; #ifdef _7Z_VOL struct CFinishHeader: public CStartHeader { UInt64 ArchiveStartOffset; // data offset from end if that struct UInt64 AdditionalStartBlockSize; // start signature & start header size }; const UInt32 kFinishHeaderSize = kStartHeaderSize + 16; #endif namespace NID { enum EEnum { kEnd, kHeader, kArchiveProperties, kAdditionalStreamsInfo, kMainStreamsInfo, kFilesInfo, kPackInfo, kUnpackInfo, kSubStreamsInfo, kSize, kCRC, kFolder, kCodersUnpackSize, kNumUnpackStream, kEmptyStream, kEmptyFile, kAnti, kName, kCTime, kATime, kMTime, kWinAttributes, kComment, kEncodedHeader, kStartPos, kDummy }; } }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zIn.cpp ================================================ // 7zIn.cpp #include "StdAfx.h" extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/CpuArch.h" } #include "../../Common/StreamObjects.h" #include "../../Common/StreamUtils.h" #include "7zDecode.h" #include "7zIn.h" #define Get16(p) GetUi16(p) #define Get32(p) GetUi32(p) #define Get64(p) GetUi64(p) // define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader #ifndef _SFX #define FORMAT_7Z_RECOVERY #endif namespace NArchive { namespace N7z { static void BoolVector_Fill_False(CBoolVector &v, int size) { v.Clear(); v.Reserve(size); for (int i = 0; i < size; i++) v.Add(false); } static bool BoolVector_GetAndSet(CBoolVector &v, UInt32 index) { if (index >= (UInt32)v.Size()) return true; bool res = v[index]; v[index] = true; return res; } bool CFolder::CheckStructure() const { const int kNumCodersMax = sizeof(UInt32) * 8; // don't change it const int kMaskSize = sizeof(UInt32) * 8; // it must be >= kNumCodersMax const int kNumBindsMax = 32; if (Coders.Size() > kNumCodersMax || BindPairs.Size() > kNumBindsMax) return false; { CBoolVector v; BoolVector_Fill_False(v, BindPairs.Size() + PackStreams.Size()); int i; for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].InIndex)) return false; for (i = 0; i < PackStreams.Size(); i++) if (BoolVector_GetAndSet(v, PackStreams[i])) return false; BoolVector_Fill_False(v, UnpackSizes.Size()); for (i = 0; i < BindPairs.Size(); i++) if (BoolVector_GetAndSet(v, BindPairs[i].OutIndex)) return false; } UInt32 mask[kMaskSize]; int i; for (i = 0; i < kMaskSize; i++) mask[i] = 0; { CIntVector inStreamToCoder, outStreamToCoder; for (i = 0; i < Coders.Size(); i++) { CNum j; const CCoderInfo &coder = Coders[i]; for (j = 0; j < coder.NumInStreams; j++) inStreamToCoder.Add(i); for (j = 0; j < coder.NumOutStreams; j++) outStreamToCoder.Add(i); } for (i = 0; i < BindPairs.Size(); i++) { const CBindPair &bp = BindPairs[i]; mask[inStreamToCoder[bp.InIndex]] |= (1 << outStreamToCoder[bp.OutIndex]); } } for (i = 0; i < kMaskSize; i++) for (int j = 0; j < kMaskSize; j++) if (((1 << j) & mask[i]) != 0) mask[i] |= mask[j]; for (i = 0; i < kMaskSize; i++) if (((1 << i) & mask[i]) != 0) return false; return true; } class CInArchiveException {}; static void ThrowException() { throw CInArchiveException(); } static inline void ThrowEndOfData() { ThrowException(); } static inline void ThrowUnsupported() { ThrowException(); } static inline void ThrowIncorrect() { ThrowException(); } static inline void ThrowUnsupportedVersion() { ThrowException(); } /* class CInArchiveException { public: enum CCauseType { kUnsupportedVersion = 0, kUnsupported, kIncorrect, kEndOfData, } Cause; CInArchiveException(CCauseType cause): Cause(cause) {}; }; static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); } static void ThrowEndOfData() { ThrowException(CInArchiveException::kEndOfData); } static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); } static void ThrowIncorrect() { ThrowException(CInArchiveException::kIncorrect); } static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); } */ class CStreamSwitch { CInArchive *_archive; bool _needRemove; public: CStreamSwitch(): _needRemove(false) {} ~CStreamSwitch() { Remove(); } void Remove(); void Set(CInArchive *archive, const Byte *data, size_t size); void Set(CInArchive *archive, const CByteBuffer &byteBuffer); void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector); }; void CStreamSwitch::Remove() { if (_needRemove) { _archive->DeleteByteStream(); _needRemove = false; } } void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size) { Remove(); _archive = archive; _archive->AddByteStream(data, size); _needRemove = true; } void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer) { Set(archive, byteBuffer, byteBuffer.GetCapacity()); } void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector) { Remove(); Byte external = archive->ReadByte(); if (external != 0) { int dataIndex = (int)archive->ReadNum(); if (dataIndex < 0 || dataIndex >= dataVector->Size()) ThrowIncorrect(); Set(archive, (*dataVector)[dataIndex]); } } Byte CInByte2::ReadByte() { if (_pos >= _size) ThrowEndOfData(); return _buffer[_pos++]; } void CInByte2::ReadBytes(Byte *data, size_t size) { if (size > _size - _pos) ThrowEndOfData(); for (size_t i = 0; i < size; i++) data[i] = _buffer[_pos++]; } void CInByte2::SkeepData(UInt64 size) { if (size > _size - _pos) ThrowEndOfData(); _pos += (size_t)size; } void CInByte2::SkeepData() { SkeepData(ReadNumber()); } UInt64 CInByte2::ReadNumber() { if (_pos >= _size) ThrowEndOfData(); Byte firstByte = _buffer[_pos++]; Byte mask = 0x80; UInt64 value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } if (_pos >= _size) ThrowEndOfData(); value |= ((UInt64)_buffer[_pos++] << (8 * i)); mask >>= 1; } return value; } CNum CInByte2::ReadNum() { UInt64 value = ReadNumber(); if (value > kNumMax) ThrowUnsupported(); return (CNum)value; } UInt32 CInByte2::ReadUInt32() { if (_pos + 4 > _size) ThrowEndOfData(); UInt32 res = Get32(_buffer + _pos); _pos += 4; return res; } UInt64 CInByte2::ReadUInt64() { if (_pos + 8 > _size) ThrowEndOfData(); UInt64 res = Get64(_buffer + _pos); _pos += 8; return res; } void CInByte2::ReadString(UString &s) { const Byte *buf = _buffer + _pos; size_t rem = (_size - _pos) / 2 * 2; { size_t i; for (i = 0; i < rem; i += 2) if (buf[i] == 0 && buf[i + 1] == 0) break; if (i == rem) ThrowEndOfData(); rem = i; } int len = (int)(rem / 2); if (len < 0 || (size_t)len * 2 != rem) ThrowUnsupported(); wchar_t *p = s.GetBuffer(len); int i; for (i = 0; i < len; i++, buf += 2) p[i] = (wchar_t)Get16(buf); s.ReleaseBuffer(len); _pos += rem + 2; } static inline bool TestSignatureCandidate(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return (p[0x1A] == 0 && p[0x1B] == 0); } HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; } // S_FALSE means that file is not archive HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { HeadersSize = 0; Close(); RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition)) RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit)); _stream = stream; return S_OK; } void CInArchive::Close() { _stream.Release(); } void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */) { for (;;) { if (ReadID() == NID::kEnd) break; SkeepData(); } } void CInArchive::GetNextFolderItem(CFolder &folder) { CNum numCoders = ReadNum(); folder.Coders.Clear(); folder.Coders.Reserve((int)numCoders); CNum numInStreams = 0; CNum numOutStreams = 0; CNum i; for (i = 0; i < numCoders; i++) { folder.Coders.Add(CCoderInfo()); CCoderInfo &coder = folder.Coders.Back(); { Byte mainByte = ReadByte(); int idSize = (mainByte & 0xF); Byte longID[15]; ReadBytes(longID, idSize); if (idSize > 8) ThrowUnsupported(); UInt64 id = 0; for (int j = 0; j < idSize; j++) id |= (UInt64)longID[idSize - 1 - j] << (8 * j); coder.MethodID = id; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { CNum propsSize = ReadNum(); coder.Props.SetCapacity((size_t)propsSize); ReadBytes((Byte *)coder.Props, (size_t)propsSize); } if ((mainByte & 0x80) != 0) ThrowUnsupported(); } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } CNum numBindPairs = numOutStreams - 1; folder.BindPairs.Clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { CBindPair bp; bp.InIndex = ReadNum(); bp.OutIndex = ReadNum(); folder.BindPairs.Add(bp); } if (numInStreams < numBindPairs) ThrowUnsupported(); CNum numPackStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackStreams); if (numPackStreams == 1) { for (i = 0; i < numInStreams; i++) if (folder.FindBindPairForInStream(i) < 0) { folder.PackStreams.Add(i); break; } if (folder.PackStreams.Size() != 1) ThrowUnsupported(); } else for (i = 0; i < numPackStreams; i++) folder.PackStreams.Add(ReadNum()); } void CInArchive::WaitAttribute(UInt64 attribute) { for (;;) { UInt64 type = ReadID(); if (type == attribute) return; if (type == NID::kEnd) ThrowIncorrect(); SkeepData(); } } void CInArchive::ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { ReadBoolVector2(numItems, digestsDefined); digests.Clear(); digests.Reserve(numItems); for (int i = 0; i < numItems; i++) { UInt32 crc = 0; if (digestsDefined[i]) crc = ReadUInt32(); digests.Add(crc); } } void CInArchive::ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs) { dataOffset = ReadNumber(); CNum numPackStreams = ReadNum(); WaitAttribute(NID::kSize); packSizes.Clear(); packSizes.Reserve(numPackStreams); for (CNum i = 0; i < numPackStreams; i++) packSizes.Add(ReadNumber()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kEnd) break; if (type == NID::kCRC) { ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); continue; } SkeepData(); } if (packCRCsDefined.IsEmpty()) { BoolVector_Fill_False(packCRCsDefined, numPackStreams); packCRCs.Reserve(numPackStreams); packCRCs.Clear(); for (CNum i = 0; i < numPackStreams; i++) packCRCs.Add(0); } } void CInArchive::ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders) { WaitAttribute(NID::kFolder); CNum numFolders = ReadNum(); { CStreamSwitch streamSwitch; streamSwitch.Set(this, dataVector); folders.Clear(); folders.Reserve(numFolders); for (CNum i = 0; i < numFolders; i++) { folders.Add(CFolder()); GetNextFolderItem(folders.Back()); } } WaitAttribute(NID::kCodersUnpackSize); CNum i; for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; CNum numOutStreams = folder.GetNumOutStreams(); folder.UnpackSizes.Reserve(numOutStreams); for (CNum j = 0; j < numOutStreams; j++) folder.UnpackSizes.Add(ReadNumber()); } for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) { CBoolVector crcsDefined; CRecordVector<UInt32> crcs; ReadHashDigests(numFolders, crcsDefined, crcs); for (i = 0; i < numFolders; i++) { CFolder &folder = folders[i]; folder.UnpackCRCDefined = crcsDefined[i]; folder.UnpackCRC = crcs[i]; } continue; } SkeepData(); } } void CInArchive::ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { numUnpackStreamsInFolders.Clear(); numUnpackStreamsInFolders.Reserve(folders.Size()); UInt64 type; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(ReadNum()); continue; } if (type == NID::kCRC || type == NID::kSize) break; if (type == NID::kEnd) break; SkeepData(); } if (numUnpackStreamsInFolders.IsEmpty()) for (int i = 0; i < folders.Size(); i++) numUnpackStreamsInFolders.Add(1); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams == 0) continue; UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) if (type == NID::kSize) { UInt64 size = ReadNumber(); unpackSizes.Add(size); sum += size; } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if (type == NID::kSize) type = ReadID(); int numDigests = 0; int numDigestsTotal = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID::kCRC) { CBoolVector digestsDefined2; CRecordVector<UInt32> digests2; ReadHashDigests(numDigests, digestsDefined2, digests2); int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { CNum numSubstreams = numUnpackStreamsInFolders[i]; const CFolder &folder = folders[i]; if (numSubstreams == 1 && folder.UnpackCRCDefined) { digestsDefined.Add(true); digests.Add(folder.UnpackCRC); } else for (CNum j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.Add(digestsDefined2[digestIndex]); digests.Add(digests2[digestIndex]); } } } else if (type == NID::kEnd) { if (digestsDefined.IsEmpty()) { BoolVector_Fill_False(digestsDefined, numDigestsTotal); digests.Clear(); for (int i = 0; i < numDigestsTotal; i++) digests.Add(0); } return; } else SkeepData(); type = ReadID(); } } void CInArchive::ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests) { for (;;) { UInt64 type = ReadID(); if (type > ((UInt32)1 << 30)) ThrowIncorrect(); switch((UInt32)type) { case NID::kEnd: return; case NID::kPackInfo: { ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); break; } case NID::kUnpackInfo: { ReadUnpackInfo(dataVector, folders); break; } case NID::kSubStreamsInfo: { ReadSubStreamsInfo(folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); break; } default: ThrowIncorrect(); } } } void CInArchive::ReadBoolVector(int numItems, CBoolVector &v) { v.Clear(); v.Reserve(numItems); Byte b = 0; Byte mask = 0; for (int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.Add((b & mask) != 0); mask >>= 1; } } void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v) { Byte allAreDefined = ReadByte(); if (allAreDefined == 0) { ReadBoolVector(numItems, v); return; } v.Clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.Add(true); } void CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles) { ReadBoolVector2(numFiles, v.Defined); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); v.Values.Reserve(numFiles); for (int i = 0; i < numFiles; i++) { UInt64 t = 0; if (v.Defined[i]) t = ReadUInt64(); v.Values.Add(t); } } HRESULT CInArchive::ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { CRecordVector<UInt64> packSizes; CBoolVector packCRCsDefined; CRecordVector<UInt32> packCRCs; CObjectVector<CFolder> folders; CRecordVector<CNum> numUnpackStreamsInFolders; CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; ReadStreamsInfo(NULL, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnpackStreamsInFolders, unpackSizes, digestsDefined, digests); // db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; CNum packIndex = 0; CDecoder decoder( #ifdef _ST_MODE false #else true #endif ); UInt64 dataStartPos = baseOffset + dataOffset; for (int i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; dataVector.Add(CByteBuffer()); CByteBuffer &data = dataVector.Back(); UInt64 unpackSize64 = folder.GetUnpackSize(); size_t unpackSize = (size_t)unpackSize64; if (unpackSize != unpackSize64) ThrowUnsupported(); data.SetCapacity(unpackSize); CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; outStreamSpec->Init(data, unpackSize); HRESULT result = decoder.Decode( EXTERNAL_CODECS_LOC_VARS _stream, dataStartPos, &packSizes[packIndex], folder, outStream, NULL #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif #ifdef COMPRESS_MT , false, 1 #endif ); RINOK(result); if (folder.UnpackCRCDefined) if (CrcCalc(data, unpackSize) != folder.UnpackCRC) ThrowIncorrect(); for (int j = 0; j < folder.PackStreams.Size(); j++) { UInt64 packSize = packSizes[packIndex++]; dataStartPos += packSize; HeadersSize += packSize; } } return S_OK; } HRESULT CInArchive::ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { UInt64 type = ReadID(); if (type == NID::kArchiveProperties) { ReadArchiveProperties(db.ArchiveInfo); type = ReadID(); } CObjectVector<CByteBuffer> dataVector; if (type == NID::kAdditionalStreamsInfo) { HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } CRecordVector<UInt64> unpackSizes; CBoolVector digestsDefined; CRecordVector<UInt32> digests; if (type == NID::kMainStreamsInfo) { ReadStreamsInfo(&dataVector, db.ArchiveInfo.DataStartPosition, db.PackSizes, db.PackCRCsDefined, db.PackCRCs, db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for (int i = 0; i < db.Folders.Size(); i++) { db.NumUnpackStreamsVector.Add(1); CFolder &folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digestsDefined.Add(folder.UnpackCRCDefined); digests.Add(folder.UnpackCRC); } } db.Files.Clear(); if (type == NID::kEnd) return S_OK; if (type != NID::kFilesInfo) ThrowIncorrect(); CNum numFiles = ReadNum(); db.Files.Reserve(numFiles); CNum i; for (i = 0; i < numFiles; i++) db.Files.Add(CFileItem()); db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize); if (!db.PackSizes.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo); if (numFiles > 0 && !digests.IsEmpty()) db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC); CBoolVector emptyStreamVector; BoolVector_Fill_False(emptyStreamVector, (int)numFiles); CBoolVector emptyFileVector; CBoolVector antiFileVector; CNum numEmptyStreams = 0; for (;;) { UInt64 type = ReadID(); if (type == NID::kEnd) break; UInt64 size = ReadNumber(); size_t ppp = _inByteBack->_pos; bool addPropIdToList = true; bool isKnownType = true; if (type > ((UInt32)1 << 30)) isKnownType = false; else switch((UInt32)type) { case NID::kName: { CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (int i = 0; i < db.Files.Size(); i++) _inByteBack->ReadString(db.Files[i].Name); break; } case NID::kWinAttributes: { CBoolVector boolVector; ReadBoolVector2(db.Files.Size(), boolVector); CStreamSwitch streamSwitch; streamSwitch.Set(this, &dataVector); for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; file.AttribDefined = boolVector[i]; if (file.AttribDefined) file.Attrib = ReadUInt32(); } break; } case NID::kEmptyStream: { ReadBoolVector(numFiles, emptyStreamVector); for (i = 0; i < (CNum)emptyStreamVector.Size(); i++) if (emptyStreamVector[i]) numEmptyStreams++; BoolVector_Fill_False(emptyFileVector, numEmptyStreams); BoolVector_Fill_False(antiFileVector, numEmptyStreams); break; } case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break; case NID::kAnti: ReadBoolVector(numEmptyStreams, antiFileVector); break; case NID::kStartPos: ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break; case NID::kCTime: ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break; case NID::kATime: ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break; case NID::kMTime: ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break; case NID::kDummy: { for (UInt64 j = 0; j < size; j++) if (ReadByte() != 0) ThrowIncorrect(); addPropIdToList = false; break; } default: addPropIdToList = isKnownType = false; } if (isKnownType) { if(addPropIdToList) db.ArchiveInfo.FileInfoPopIDs.Add(type); } else SkeepData(size); bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 || db.ArchiveInfo.Version.Minor > 2); if (checkRecordsSize && _inByteBack->_pos - ppp != size) ThrowIncorrect(); } CNum emptyFileIndex = 0; CNum sizeIndex = 0; CNum numAntiItems = 0; for (i = 0; i < numEmptyStreams; i++) if (antiFileVector[i]) numAntiItems++; for (i = 0; i < numFiles; i++) { CFileItem &file = db.Files[i]; bool isAnti; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; isAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; file.CrcDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; isAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.CrcDefined = false; } if (numAntiItems != 0) db.IsAnti.Add(isAnti); } return S_OK; } void CArchiveDatabaseEx::FillFolderStartPackStream() { FolderStartPackStreamIndex.Clear(); FolderStartPackStreamIndex.Reserve(Folders.Size()); CNum startPos = 0; for (int i = 0; i < Folders.Size(); i++) { FolderStartPackStreamIndex.Add(startPos); startPos += (CNum)Folders[i].PackStreams.Size(); } } void CArchiveDatabaseEx::FillStartPos() { PackStreamStartPositions.Clear(); PackStreamStartPositions.Reserve(PackSizes.Size()); UInt64 startPos = 0; for (int i = 0; i < PackSizes.Size(); i++) { PackStreamStartPositions.Add(startPos); startPos += PackSizes[i]; } } void CArchiveDatabaseEx::FillFolderStartFileIndex() { FolderStartFileIndex.Clear(); FolderStartFileIndex.Reserve(Folders.Size()); FileIndexToFolderIndexMap.Clear(); FileIndexToFolderIndexMap.Reserve(Files.Size()); int folderIndex = 0; CNum indexInFolder = 0; for (int i = 0; i < Files.Size(); i++) { const CFileItem &file = Files[i]; bool emptyStream = !file.HasStream; if (emptyStream && indexInFolder == 0) { FileIndexToFolderIndexMap.Add(kNumNoIndex); continue; } if (indexInFolder == 0) { // v3.13 incorrectly worked with empty folders // v4.07: Loop for skipping empty folders for (;;) { if (folderIndex >= Folders.Size()) ThrowIncorrect(); FolderStartFileIndex.Add(i); // check it if (NumUnpackStreamsVector[folderIndex] != 0) break; folderIndex++; } } FileIndexToFolderIndexMap.Add(folderIndex); if (emptyStream) continue; indexInFolder++; if (indexInFolder >= NumUnpackStreamsVector[folderIndex]) { folderIndex++; indexInFolder = 0; } } } HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } #endif #ifdef FORMAT_7Z_RECOVERY crcFromArchive = crc; #endif db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (crc != crcFromArchive) ThrowIncorrect(); if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } HRESULT CInArchive::ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { try { return ReadDatabase2( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); } catch(CInArchiveException &) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zIn.h ================================================ // 7zIn.h #ifndef __7Z_IN_H #define __7Z_IN_H #include "../../../Common/MyCom.h" #include "../../IPassword.h" #include "../../IStream.h" #include "../../Common/CreateCoder.h" #include "../../Common/InBuffer.h" #include "7zItem.h" namespace NArchive { namespace N7z { struct CInArchiveInfo { CArchiveVersion Version; UInt64 StartPosition; UInt64 StartPositionAfterHeader; UInt64 DataStartPosition; UInt64 DataStartPosition2; CRecordVector<UInt64> FileInfoPopIDs; void Clear() { FileInfoPopIDs.Clear(); } }; struct CArchiveDatabaseEx: public CArchiveDatabase { CInArchiveInfo ArchiveInfo; CRecordVector<UInt64> PackStreamStartPositions; CRecordVector<CNum> FolderStartPackStreamIndex; CRecordVector<CNum> FolderStartFileIndex; CRecordVector<CNum> FileIndexToFolderIndexMap; UInt64 HeadersSize; UInt64 PhySize; void Clear() { CArchiveDatabase::Clear(); ArchiveInfo.Clear(); PackStreamStartPositions.Clear(); FolderStartPackStreamIndex.Clear(); FolderStartFileIndex.Clear(); FileIndexToFolderIndexMap.Clear(); HeadersSize = 0; PhySize = 0; } void FillFolderStartPackStream(); void FillStartPos(); void FillFolderStartFileIndex(); void Fill() { FillFolderStartPackStream(); FillStartPos(); FillFolderStartFileIndex(); } UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const { return ArchiveInfo.DataStartPosition + PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } UInt64 GetFolderFullPackSize(int folderIndex) const { CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex]; const CFolder &folder = Folders[folderIndex]; UInt64 size = 0; for (int i = 0; i < folder.PackStreams.Size(); i++) size += PackSizes[packStreamIndex + i]; return size; } UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } UInt64 GetFilePackSize(CNum fileIndex) const { CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex != kNumNoIndex) if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); return 0; } }; class CInByte2 { const Byte *_buffer; size_t _size; public: size_t _pos; void Init(const Byte *buffer, size_t size) { _buffer = buffer; _size = size; _pos = 0; } Byte ReadByte(); void ReadBytes(Byte *data, size_t size); void SkeepData(UInt64 size); void SkeepData(); UInt64 ReadNumber(); CNum ReadNum(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); void ReadString(UString &s); }; class CStreamSwitch; const UInt32 kHeaderSize = 32; class CInArchive { friend class CStreamSwitch; CMyComPtr<IInStream> _stream; CObjectVector<CInByte2> _inByteVector; CInByte2 *_inByteBack; UInt64 _arhiveBeginStreamPosition; Byte _header[kHeaderSize]; UInt64 HeadersSize; void AddByteStream(const Byte *buffer, size_t size) { _inByteVector.Add(CInByte2()); _inByteBack = &_inByteVector.Back(); _inByteBack->Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.IsEmpty()) _inByteBack = &_inByteVector.Back(); } private: HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } Byte ReadByte() { return _inByteBack->ReadByte(); } UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } CNum ReadNum() { return _inByteBack->ReadNum(); } UInt64 ReadID() { return _inByteBack->ReadNumber(); } UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); } void SkeepData() { _inByteBack->SkeepData(); } void WaitAttribute(UInt64 attribute); void ReadArchiveProperties(CInArchiveInfo &archiveInfo); void GetNextFolderItem(CFolder &itemInfo); void ReadHashDigests(int numItems, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadPackInfo( UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs); void ReadUnpackInfo( const CObjectVector<CByteBuffer> *dataVector, CObjectVector<CFolder> &folders); void ReadSubStreamsInfo( const CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadStreamsInfo( const CObjectVector<CByteBuffer> *dataVector, UInt64 &dataOffset, CRecordVector<UInt64> &packSizes, CBoolVector &packCRCsDefined, CRecordVector<UInt32> &packCRCs, CObjectVector<CFolder> &folders, CRecordVector<CNum> &numUnpackStreamsInFolders, CRecordVector<UInt64> &unpackSizes, CBoolVector &digestsDefined, CRecordVector<UInt32> &digests); void ReadBoolVector(int numItems, CBoolVector &v); void ReadBoolVector2(int numItems, CBoolVector &v); void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, CUInt64DefVector &v, int numFiles); HRESULT ReadAndDecodePackedStreams( DECL_EXTERNAL_CODECS_LOC_VARS UInt64 baseOffset, UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadHeader( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); HRESULT ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); public: HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive void Close(); HRESULT ReadDatabase( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO ,ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zItem.h ================================================ // 7zItem.h #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "../../../Common/Buffer.h" #include "../../../Common/MyString.h" #include "../../Common/MethodId.h" #include "7zHeader.h" namespace NArchive { namespace N7z { typedef UInt32 CNum; const CNum kNumMax = 0x7FFFFFFF; const CNum kNumNoIndex = 0xFFFFFFFF; struct CCoderInfo { CMethodId MethodID; CByteBuffer Props; CNum NumInStreams; CNum NumOutStreams; bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); } }; struct CBindPair { CNum InIndex; CNum OutIndex; }; struct CFolder { CObjectVector<CCoderInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<CNum> PackStreams; CRecordVector<UInt64> UnpackSizes; UInt32 UnpackCRC; bool UnpackCRCDefined; CFolder(): UnpackCRCDefined(false) {} UInt64 GetUnpackSize() const // test it { if (UnpackSizes.IsEmpty()) return 0; for (int i = UnpackSizes.Size() - 1; i >= 0; i--) if (FindBindPairForOutStream(i) < 0) return UnpackSizes[i]; throw 1; } CNum GetNumOutStreams() const { CNum result = 0; for (int i = 0; i < Coders.Size(); i++) result += Coders[i].NumOutStreams; return result; } int FindBindPairForInStream(CNum inStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int FindBindPairForOutStream(CNum outStreamIndex) const { for(int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } int FindPackStreamArrayIndex(CNum inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } bool CheckStructure() const; }; struct CUInt64DefVector { CRecordVector<UInt64> Values; CRecordVector<bool> Defined; void Clear() { Values.Clear(); Defined.Clear(); } void ReserveDown() { Values.ReserveDown(); Values.ReserveDown(); } bool GetItem(int index, UInt64 &value) const { if (index < Defined.Size() && Defined[index]) { value = Values[index]; return true; } value = 0; return false; } void SetItem(int index, bool defined, UInt64 value) { while (index >= Defined.Size()) Defined.Add(false); Defined[index] = defined; if (!defined) return; while (index >= Values.Size()) Values.Add(0); Values[index] = value; } bool CheckSize(int size) const { return Defined.Size() == size || Defined.Size() == 0; } }; struct CFileItem { UInt64 Size; UInt32 Attrib; UInt32 Crc; UString Name; bool HasStream; // Test it !!! it means that there is // stream in some folder. It can be empty stream bool IsDir; bool CrcDefined; bool AttribDefined; CFileItem(): HasStream(true), IsDir(false), CrcDefined(false), AttribDefined(false) {} void SetAttrib(UInt32 attrib) { AttribDefined = true; Attrib = attrib; } }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; }; struct CArchiveDatabase { CRecordVector<UInt64> PackSizes; CRecordVector<bool> PackCRCsDefined; CRecordVector<UInt32> PackCRCs; CObjectVector<CFolder> Folders; CRecordVector<CNum> NumUnpackStreamsVector; CObjectVector<CFileItem> Files; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector<bool> IsAnti; void Clear() { PackSizes.Clear(); PackCRCsDefined.Clear(); PackCRCs.Clear(); Folders.Clear(); NumUnpackStreamsVector.Clear(); Files.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); } void ReserveDown() { PackSizes.ReserveDown(); PackCRCsDefined.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); Files.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); } bool IsEmpty() const { return (PackSizes.IsEmpty() && PackCRCsDefined.IsEmpty() && PackCRCs.IsEmpty() && Folders.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { int size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsSolid() const { for (int i = 0; i < NumUnpackStreamsVector.Size(); i++) if (NumUnpackStreamsVector[i] > 1) return true; return false; } bool IsItemAnti(int index) const { return (index < IsAnti.Size() && IsAnti[index]); } void SetItemAnti(int index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } void GetFile(int index, CFileItem &file, CFileItem2 &file2) const; void AddFile(const CFileItem &file, const CFileItem2 &file2); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zOut.cpp ================================================ // 7zOut.cpp #include "StdAfx.h" #include "../../../Common/AutoPtr.h" #include "../../Common/StreamObjects.h" #include "7zOut.h" extern "C" { #include "../../../../C/7zCrc.h" } static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size) { while (size > 0) { UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF); UInt32 processedSize; RINOK(stream->Write(data, curSize, &processedSize)); if (processedSize == 0) return E_FAIL; data = (const void *)((const Byte *)data + processedSize); size -= processedSize; } return S_OK; } namespace NArchive { namespace N7z { HRESULT COutArchive::WriteDirect(const void *data, UInt32 size) { return ::WriteBytes(SeqStream, data, size); } HRESULT COutArchive::WriteSignature() { Byte buf[8]; memcpy(buf, kSignature, kSignatureSize); buf[kSignatureSize] = kMajorVersion; buf[kSignatureSize + 1] = 3; return WriteDirect(buf, 8); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishSignature() { RINOK(WriteDirect(kFinishSignature, kSignatureSize)); CArchiveVersion av; av.Major = kMajorVersion; av.Minor = 2; RINOK(WriteDirectByte(av.Major)); return WriteDirectByte(av.Minor); } #endif static void SetUInt32(Byte *p, UInt32 d) { for (int i = 0; i < 4; i++, d >>= 8) p[i] = (Byte)d; } static void SetUInt64(Byte *p, UInt64 d) { for (int i = 0; i < 8; i++, d >>= 8) p[i] = (Byte)d; } HRESULT COutArchive::WriteStartHeader(const CStartHeader &h) { Byte buf[24]; SetUInt64(buf + 4, h.NextHeaderOffset); SetUInt64(buf + 12, h.NextHeaderSize); SetUInt32(buf + 20, h.NextHeaderCRC); SetUInt32(buf, CrcCalc(buf + 4, 20)); return WriteDirect(buf, 24); } #ifdef _7Z_VOL HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h) { CCRC crc; crc.UpdateUInt64(h.NextHeaderOffset); crc.UpdateUInt64(h.NextHeaderSize); crc.UpdateUInt32(h.NextHeaderCRC); crc.UpdateUInt64(h.ArchiveStartOffset); crc.UpdateUInt64(h.AdditionalStartBlockSize); RINOK(WriteDirectUInt32(crc.GetDigest())); RINOK(WriteDirectUInt64(h.NextHeaderOffset)); RINOK(WriteDirectUInt64(h.NextHeaderSize)); RINOK(WriteDirectUInt32(h.NextHeaderCRC)); RINOK(WriteDirectUInt64(h.ArchiveStartOffset)); return WriteDirectUInt64(h.AdditionalStartBlockSize); } #endif HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker) { Close(); #ifdef _7Z_VOL // endMarker = false; _endMarker = endMarker; #endif SeqStream = stream; if (!endMarker) { SeqStream.QueryInterface(IID_IOutStream, &Stream); if (!Stream) { return E_NOTIMPL; // endMarker = true; } } #ifdef _7Z_VOL if (endMarker) { /* CStartHeader sh; sh.NextHeaderOffset = (UInt32)(Int32)-1; sh.NextHeaderSize = (UInt32)(Int32)-1; sh.NextHeaderCRC = 0; WriteStartHeader(sh); */ } else #endif { if (!Stream) return E_FAIL; RINOK(WriteSignature()); RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos)); } return S_OK; } void COutArchive::Close() { SeqStream.Release(); Stream.Release(); } HRESULT COutArchive::SkeepPrefixArchiveHeader() { #ifdef _7Z_VOL if (_endMarker) return S_OK; #endif return Stream->Seek(24, STREAM_SEEK_CUR, NULL); } UInt64 COutArchive::GetPos() const { if (_countMode) return _countSize; if (_writeToStream) return _outByte.GetProcessedSize(); return _outByte2.GetPos(); } void COutArchive::WriteBytes(const void *data, size_t size) { if (_countMode) _countSize += size; else if (_writeToStream) { _outByte.WriteBytes(data, size); _crc = CrcUpdate(_crc, data, size); } else _outByte2.WriteBytes(data, size); } void COutArchive::WriteByte(Byte b) { if (_countMode) _countSize++; else if (_writeToStream) { _outByte.WriteByte(b); _crc = CRC_UPDATE_BYTE(_crc, b); } else _outByte2.WriteByte(b); } void COutArchive::WriteUInt32(UInt32 value) { for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteUInt64(UInt64 value) { for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; } } void COutArchive::WriteNumber(UInt64 value) { Byte firstByte = 0; Byte mask = 0x80; int i; for (i = 0; i < 8; i++) { if (value < ((UInt64(1) << ( 7 * (i + 1))))) { firstByte |= Byte(value >> (8 * i)); break; } firstByte |= mask; mask >>= 1; } WriteByte(firstByte); for (;i > 0; i--) { WriteByte((Byte)value); value >>= 8; } } static UInt32 GetBigNumberSize(UInt64 value) { int i; for (i = 1; i < 9; i++) if (value < (((UInt64)1 << (i * 7)))) break; return i; } #ifdef _7Z_VOL UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props) { UInt32 result = GetBigNumberSize(dataSize) * 2 + 41; if (nameLength != 0) { nameLength = (nameLength + 1) * 2; result += nameLength + GetBigNumberSize(nameLength) + 2; } if (props) { result += 20; } if (result >= 128) result++; result += kSignatureSize + 2 + kFinishHeaderSize; return result; } UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props) { UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props); int testSize; if (volSize > headersSizeBase) testSize = volSize - headersSizeBase; else testSize = 1; UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props); UInt64 pureSize = 1; if (volSize > headersSize) pureSize = volSize - headersSize; return pureSize; } #endif void COutArchive::WriteFolder(const CFolder &folder) { WriteNumber(folder.Coders.Size()); int i; for (i = 0; i < folder.Coders.Size(); i++) { const CCoderInfo &coder = folder.Coders[i]; { size_t propsSize = coder.Props.GetCapacity(); UInt64 id = coder.MethodID; int idSize; for (idSize = 1; idSize < sizeof(id); idSize++) if ((id >> (8 * idSize)) == 0) break; BYTE longID[15]; for (int t = idSize - 1; t >= 0 ; t--, id >>= 8) longID[t] = (Byte)(id & 0xFF); Byte b; b = (Byte)(idSize & 0xF); bool isComplex = !coder.IsSimpleCoder(); b |= (isComplex ? 0x10 : 0); b |= ((propsSize != 0) ? 0x20 : 0 ); WriteByte(b); WriteBytes(longID, idSize); if (isComplex) { WriteNumber(coder.NumInStreams); WriteNumber(coder.NumOutStreams); } if (propsSize == 0) continue; WriteNumber(propsSize); WriteBytes(coder.Props, propsSize); } } for (i = 0; i < folder.BindPairs.Size(); i++) { const CBindPair &bindPair = folder.BindPairs[i]; WriteNumber(bindPair.InIndex); WriteNumber(bindPair.OutIndex); } if (folder.PackStreams.Size() > 1) for (i = 0; i < folder.PackStreams.Size(); i++) { WriteNumber(folder.PackStreams[i]); } } void COutArchive::WriteBoolVector(const CBoolVector &boolVector) { Byte b = 0; Byte mask = 0x80; for (int i = 0; i < boolVector.Size(); i++) { if (boolVector[i]) b |= mask; mask >>= 1; if (mask == 0) { WriteByte(b); mask = 0x80; b = 0; } } if (mask != 0x80) WriteByte(b); } void COutArchive::WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { int numDefined = 0; int i; for (i = 0; i < digestsDefined.Size(); i++) if (digestsDefined[i]) numDefined++; if (numDefined == 0) return; WriteByte(NID::kCRC); if (numDefined == digestsDefined.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(digestsDefined); } for (i = 0; i < digests.Size(); i++) if (digestsDefined[i]) WriteUInt32(digests[i]); } void COutArchive::WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs) { if (packSizes.IsEmpty()) return; WriteByte(NID::kPackInfo); WriteNumber(dataOffset); WriteNumber(packSizes.Size()); WriteByte(NID::kSize); for (int i = 0; i < packSizes.Size(); i++) WriteNumber(packSizes[i]); WriteHashDigests(packCRCsDefined, packCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders) { if (folders.IsEmpty()) return; WriteByte(NID::kUnpackInfo); WriteByte(NID::kFolder); WriteNumber(folders.Size()); { WriteByte(0); for (int i = 0; i < folders.Size(); i++) WriteFolder(folders[i]); } WriteByte(NID::kCodersUnpackSize); int i; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; for (int j = 0; j < folder.UnpackSizes.Size(); j++) WriteNumber(folder.UnpackSizes[j]); } CRecordVector<bool> unpackCRCsDefined; CRecordVector<UInt32> unpackCRCs; for (i = 0; i < folders.Size(); i++) { const CFolder &folder = folders[i]; unpackCRCsDefined.Add(folder.UnpackCRCDefined); unpackCRCs.Add(folder.UnpackCRC); } WriteHashDigests(unpackCRCsDefined, unpackCRCs); WriteByte(NID::kEnd); } void COutArchive::WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &digests) { WriteByte(NID::kSubStreamsInfo); int i; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) { if (numUnpackStreamsInFolders[i] != 1) { WriteByte(NID::kNumUnpackStream); for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) WriteNumber(numUnpackStreamsInFolders[i]); break; } } bool needFlag = true; CNum index = 0; for (i = 0; i < numUnpackStreamsInFolders.Size(); i++) for (CNum j = 0; j < numUnpackStreamsInFolders[i]; j++) { if (j + 1 != numUnpackStreamsInFolders[i]) { if (needFlag) WriteByte(NID::kSize); needFlag = false; WriteNumber(unpackSizes[index]); } index++; } CRecordVector<bool> digestsDefined2; CRecordVector<UInt32> digests2; int digestIndex = 0; for (i = 0; i < folders.Size(); i++) { int numSubStreams = (int)numUnpackStreamsInFolders[i]; if (numSubStreams == 1 && folders[i].UnpackCRCDefined) digestIndex++; else for (int j = 0; j < numSubStreams; j++, digestIndex++) { digestsDefined2.Add(digestsDefined[digestIndex]); digests2.Add(digests[digestIndex]); } } WriteHashDigests(digestsDefined2, digests2); WriteByte(NID::kEnd); } void COutArchive::SkipAlign(unsigned /* pos */, unsigned /* alignSize */) { return; } /* 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field. void COutArchive::SkipAlign(unsigned pos, unsigned alignSize) { pos += (unsigned)GetPos(); pos &= (alignSize - 1); if (pos == 0) return; unsigned skip = alignSize - pos; if (skip < 2) skip += alignSize; skip -= 2; WriteByte(NID::kDummy); WriteByte((Byte)skip); for (unsigned i = 0; i < skip; i++) WriteByte(0); } */ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize) { const UInt64 bvSize = (numDefined == v.Size()) ? 0 : (v.Size() + 7) / 8; const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2; SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize); WriteByte(type); WriteNumber(dataSize); if (numDefined == v.Size()) WriteByte(1); else { WriteByte(0); WriteBoolVector(v); } WriteByte(0); } void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type) { int numDefined = 0; int i; for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) numDefined++; if (numDefined == 0) return; WriteAlignedBoolHeader(v.Defined, numDefined, type, 8); for (i = 0; i < v.Defined.Size(); i++) if (v.Defined[i]) WriteUInt64(v.Values[i]); } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnpackCRCDefined = true; folderItem.UnpackCRC = CrcCalc(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)) folders.Add(folderItem); return S_OK; } HRESULT COutArchive::EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders) { return EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, data, data.GetCapacity(), packSizes, folders); } void COutArchive::WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset) { int i; UInt64 packedSize = 0; for (i = 0; i < db.PackSizes.Size(); i++) packedSize += db.PackSizes[i]; headerOffset = packedSize; WriteByte(NID::kHeader); // Archive Properties if (db.Folders.Size() > 0) { WriteByte(NID::kMainStreamsInfo); WritePackInfo(0, db.PackSizes, db.PackCRCsDefined, db.PackCRCs); WriteUnpackInfo(db.Folders); CRecordVector<UInt64> unpackSizes; CRecordVector<bool> digestsDefined; CRecordVector<UInt32> digests; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) continue; unpackSizes.Add(file.Size); digestsDefined.Add(file.CrcDefined); digests.Add(file.Crc); } WriteSubStreamsInfo( db.Folders, db.NumUnpackStreamsVector, unpackSizes, digestsDefined, digests); WriteByte(NID::kEnd); } if (db.Files.IsEmpty()) { WriteByte(NID::kEnd); return; } WriteByte(NID::kFilesInfo); WriteNumber(db.Files.Size()); { /* ---------- Empty Streams ---------- */ CBoolVector emptyStreamVector; emptyStreamVector.Reserve(db.Files.Size()); int numEmptyStreams = 0; for (i = 0; i < db.Files.Size(); i++) if (db.Files[i].HasStream) emptyStreamVector.Add(false); else { emptyStreamVector.Add(true); numEmptyStreams++; } if (numEmptyStreams > 0) { WriteByte(NID::kEmptyStream); WriteNumber((emptyStreamVector.Size() + 7) / 8); WriteBoolVector(emptyStreamVector); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum numEmptyFiles = 0, numAntiItems = 0; for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (!file.HasStream) { emptyFileVector.Add(!file.IsDir); if (!file.IsDir) numEmptyFiles++; bool isAnti = db.IsItemAnti(i); antiVector.Add(isAnti); if (isAnti) numAntiItems++; } } if (numEmptyFiles > 0) { WriteByte(NID::kEmptyFile); WriteNumber((emptyFileVector.Size() + 7) / 8); WriteBoolVector(emptyFileVector); } if (numAntiItems > 0) { WriteByte(NID::kAnti); WriteNumber((antiVector.Size() + 7) / 8); WriteBoolVector(antiVector); } } } { /* ---------- Names ---------- */ int numDefined = 0; size_t namesDataSize = 0; for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; if (!name.IsEmpty()) numDefined++; namesDataSize += (name.Length() + 1) * 2; } if (numDefined > 0) { namesDataSize++; SkipAlign(2 + GetBigNumberSize(namesDataSize), 2); WriteByte(NID::kName); WriteNumber(namesDataSize); WriteByte(0); for (int i = 0; i < db.Files.Size(); i++) { const UString &name = db.Files[i].Name; for (int t = 0; t <= name.Length(); t++) { wchar_t c = name[t]; WriteByte((Byte)c); WriteByte((Byte)(c >> 8)); } } } } if (headerOptions.WriteCTime) WriteUInt64DefVector(db.CTime, NID::kCTime); if (headerOptions.WriteATime) WriteUInt64DefVector(db.ATime, NID::kATime); if (headerOptions.WriteMTime) WriteUInt64DefVector(db.MTime, NID::kMTime); WriteUInt64DefVector(db.StartPos, NID::kStartPos); { /* ---------- Write Attrib ---------- */ CBoolVector boolVector; boolVector.Reserve(db.Files.Size()); int numDefined = 0; for (i = 0; i < db.Files.Size(); i++) { bool defined = db.Files[i].AttribDefined; boolVector.Add(defined); if (defined) numDefined++; } if (numDefined > 0) { WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttributes, 4); for (i = 0; i < db.Files.Size(); i++) { const CFileItem &file = db.Files[i]; if (file.AttribDefined) WriteUInt32(file.Attrib); } } } WriteByte(NID::kEnd); // for files WriteByte(NID::kEnd); // for headers } HRESULT COutArchive::WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions) { if (!db.CheckNumFiles()) return E_FAIL; UInt64 headerOffset; UInt32 headerCRC; UInt64 headerSize; if (db.IsEmpty()) { headerSize = 0; headerOffset = 0; headerCRC = CrcCalc(0, 0); } else { bool encodeHeaders = false; if (options != 0) if (options->IsEmpty()) options = 0; if (options != 0) if (options->PasswordIsDefined || headerOptions.CompressMainHeader) encodeHeaders = true; _outByte.SetStream(SeqStream); _outByte.Init(); _crc = CRC_INIT_VAL; _countMode = encodeHeaders; _writeToStream = true; _countSize = 0; WriteHeader(db, headerOptions, headerOffset); if (encodeHeaders) { CByteBuffer buf; buf.SetCapacity(_countSize); _outByte2.Init((Byte *)buf, _countSize); _countMode = false; _writeToStream = false; WriteHeader(db, headerOptions, headerOffset); if (_countSize != _outByte2.GetPos()) return E_FAIL; CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector<UInt64> packSizes; CObjectVector<CFolder> folders; RINOK(EncodeStream( EXTERNAL_CODECS_LOC_VARS encoder, (const Byte *)buf, _countSize, packSizes, folders)); _writeToStream = true; if (folders.Size() == 0) throw 1; WriteID(NID::kEncodedHeader); WritePackInfo(headerOffset, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>()); WriteUnpackInfo(folders); WriteByte(NID::kEnd); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; } RINOK(_outByte.Flush()); headerCRC = CRC_GET_DIGEST(_crc); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); } } void CArchiveDatabase::GetFile(int index, CFileItem &file, CFileItem2 &file2) const { file = Files[index]; file2.CTimeDefined = CTime.GetItem(index, file2.CTime); file2.ATimeDefined = ATime.GetItem(index, file2.ATime); file2.MTimeDefined = MTime.GetItem(index, file2.MTime); file2.StartPosDefined = StartPos.GetItem(index, file2.StartPos); file2.IsAnti = IsItemAnti(index); } void CArchiveDatabase::AddFile(const CFileItem &file, const CFileItem2 &file2) { int index = Files.Size(); CTime.SetItem(index, file2.CTimeDefined, file2.CTime); ATime.SetItem(index, file2.ATimeDefined, file2.ATime); MTime.SetItem(index, file2.MTimeDefined, file2.MTime); StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos); SetItemAnti(index, file2.IsAnti); Files.Add(file); } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zOut.h ================================================ // 7z/Out.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zHeader.h" #include "7zItem.h" #include "7zCompressionMode.h" #include "7zEncode.h" #include "../../Common/OutBuffer.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; bool WriteCTime; bool WriteATime; bool WriteMTime; CHeaderOptions(): CompressMainHeader(true), WriteCTime(false), WriteATime(false), WriteMTime(true) {} }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size); UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.GetCapacity()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WriteHashDigests( const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void WritePackInfo( UInt64 dataOffset, const CRecordVector<UInt64> &packSizes, const CRecordVector<bool> &packCRCsDefined, const CRecordVector<UInt32> &packCRCs); void WriteUnpackInfo(const CObjectVector<CFolder> &folders); void WriteSubStreamsInfo( const CObjectVector<CFolder> &folders, const CRecordVector<CNum> &numUnpackStreamsInFolders, const CRecordVector<UInt64> &unpackSizes, const CRecordVector<bool> &digestsDefined, const CRecordVector<UInt32> &hashDigests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, int numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders); void WriteHeader( const CArchiveDatabase &db, const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr<IOutStream> Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr<ISequentialOutStream> SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkeepPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabase &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zProperties.cpp ================================================ // 7zProperties.cpp #include "StdAfx.h" #include "7zProperties.h" #include "7zHeader.h" #include "7zHandler.h" // #define _MULTI_PACK namespace NArchive { namespace N7z { struct CPropMap { UInt64 FilePropID; STATPROPSTG StatPROPSTG; }; CPropMap kPropMap[] = { { NID::kName, NULL, kpidPath, VT_BSTR}, { NID::kSize, NULL, kpidSize, VT_UI8}, { NID::kPackInfo, NULL, kpidPackSize, VT_UI8}, #ifdef _MULTI_PACK { 100, L"Pack0", kpidPackedSize0, VT_UI8}, { 101, L"Pack1", kpidPackedSize1, VT_UI8}, { 102, L"Pack2", kpidPackedSize2, VT_UI8}, { 103, L"Pack3", kpidPackedSize3, VT_UI8}, { 104, L"Pack4", kpidPackedSize4, VT_UI8}, #endif { NID::kCTime, NULL, kpidCTime, VT_FILETIME}, { NID::kMTime, NULL, kpidMTime, VT_FILETIME}, { NID::kATime, NULL, kpidATime, VT_FILETIME}, { NID::kWinAttributes, NULL, kpidAttrib, VT_UI4}, { NID::kStartPos, NULL, kpidPosition, VT_UI4}, { NID::kCRC, NULL, kpidCRC, VT_UI4}, { NID::kAnti, NULL, kpidIsAnti, VT_BOOL}, #ifndef _SFX { 97, NULL, kpidEncrypted, VT_BOOL}, { 98, NULL, kpidMethod, VT_BSTR}, { 99, NULL, kpidBlock, VT_UI4} #endif }; static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]); static int FindPropInMap(UInt64 filePropID) { for (int i = 0; i < kPropMapSize; i++) if (kPropMap[i].FilePropID == filePropID) return i; return -1; } static void CopyOneItem(CRecordVector<UInt64> &src, CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { dest.Add(item); src.Delete(i); return; } } static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item) { for (int i = 0; i < src.Size(); i++) if (src[i] == item) { src.Delete(i); return; } } static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item) { for (int i = 0; i < dest.Size(); i++) if (dest[i] == item) { dest.Delete(i); break; } dest.Insert(0, item); } void CHandler::FillPopIDs() { _fileInfoPopIDs.Clear(); #ifdef _7Z_VOL if(_volumes.Size() < 1) return; const CVolume &volume = _volumes.Front(); const CArchiveDatabaseEx &_db = volume.Database; #endif CRecordVector<UInt64> fileInfoPopIDs = _db.ArchiveInfo.FileInfoPopIDs; RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream); RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kMTime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kATime); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC); CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment); _fileInfoPopIDs += fileInfoPopIDs; #ifndef _SFX _fileInfoPopIDs.Add(97); _fileInfoPopIDs.Add(98); _fileInfoPopIDs.Add(99); #endif #ifdef _MULTI_PACK _fileInfoPopIDs.Add(100); _fileInfoPopIDs.Add(101); _fileInfoPopIDs.Add(102); _fileInfoPopIDs.Add(103); _fileInfoPopIDs.Add(104); #endif #ifndef _SFX InsertToHead(_fileInfoPopIDs, NID::kMTime); InsertToHead(_fileInfoPopIDs, NID::kPackInfo); InsertToHead(_fileInfoPopIDs, NID::kSize); InsertToHead(_fileInfoPopIDs, NID::kName); #endif } STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) { *numProperties = _fileInfoPopIDs.Size(); return S_OK; } STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) { if ((int)index >= _fileInfoPopIDs.Size()) return E_INVALIDARG; int indexInMap = FindPropInMap(_fileInfoPopIDs[index]); if (indexInMap == -1) return E_INVALIDARG; const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG; *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zProperties.h ================================================ // 7zProperties.h #ifndef __7Z_PROPERTIES_H #define __7Z_PROPERTIES_H #include "../../PropID.h" namespace NArchive { namespace N7z { enum { kpidPackedSize0 = kpidUserDefined, kpidPackedSize1, kpidPackedSize2, kpidPackedSize3, kpidPackedSize4 }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zRegister.cpp ================================================ // 7zRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "7zHandler.h" static IInArchive *CreateArc() { return new NArchive::N7z::CHandler; } #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler; } #else #define CreateArcOut 0 #endif static CArcInfo g_ArcInfo = { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut }; REGISTER_ARC_DEC_SIG(7z) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zSpecStream.cpp ================================================ // 7zSpecStream.cpp #include "StdAfx.h" #include "7zSpecStream.h" STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize( UInt64 subStream, UInt64 *value) { if (_getSubStreamSize == NULL) return E_NOTIMPL; return _getSubStreamSize->GetSubStreamSize(subStream, value); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zSpecStream.h ================================================ // 7zSpecStream.h #ifndef __7Z_SPEC_STREAM_H #define __7Z_SPEC_STREAM_H #include "../../IStream.h" #include "../../ICoder.h" #include "../../../Common/MyCom.h" class CSequentialInStreamSizeCount2: public ISequentialInStream, public ICompressGetSubStreamSize, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _getSubStreamSize = 0; _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize); _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP1(ICompressGetSubStreamSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zUpdate.cpp ================================================ // 7zUpdate.cpp #include "StdAfx.h" #include "../../Common/LimitedStreams.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "7zEncode.h" #include "7zFolderInStream.h" #include "7zHandler.h" #include "7zOut.h" #include "7zUpdate.h" namespace NArchive { namespace N7z { static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2"; static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20; static const UInt32 kAlgorithmForBCJ2_LZMA = 1; static const UInt32 kNumFastBytesForBCJ2_LZMA = 64; static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, UInt64 position, UInt64 size, ICompressProgressInfo *progress) { RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0)); CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); streamSpec->SetStream(inStream); streamSpec->Init(size); NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)); return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); } static int GetReverseSlashPos(const UString &name) { int slashPos = name.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = name.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif return slashPos; } int CUpdateItem::GetExtensionPos() const { int slashPos = GetReverseSlashPos(Name); int dotPos = Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) return Name.Length(); return dotPos + 1; } UString CUpdateItem::GetExtension() const { return Name.Mid(GetExtensionPos()); } #define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; } static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2) { size_t c1 = a1.GetCapacity(); size_t c2 = a2.GetCapacity(); RINOZ(MyCompare(c1, c2)); for (size_t i = 0; i < c1; i++) RINOZ(MyCompare(a1[i], a2[i])); return 0; } static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2) { RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams)); RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams)); RINOZ(MyCompare(c1.MethodID, c2.MethodID)); return CompareBuffers(c1.Props, c2.Props); } static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2) { RINOZ(MyCompare(b1.InIndex, b2.InIndex)); return MyCompare(b1.OutIndex, b2.OutIndex); } static int CompareFolders(const CFolder &f1, const CFolder &f2) { int s1 = f1.Coders.Size(); int s2 = f2.Coders.Size(); RINOZ(MyCompare(s1, s2)); int i; for (i = 0; i < s1; i++) RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i])); s1 = f1.BindPairs.Size(); s2 = f2.BindPairs.Size(); RINOZ(MyCompare(s1, s2)); for (i = 0; i < s1; i++) RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i])); return 0; } static int CompareFiles(const CFileItem &f1, const CFileItem &f2) { return MyStringCompareNoCase(f1.Name, f2.Name); } static int CompareFolderRefs(const int *p1, const int *p2, void *param) { int i1 = *p1; int i2 = *p2; const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param; RINOZ(CompareFolders( db.Folders[i1], db.Folders[i2])); RINOZ(MyCompare( db.NumUnpackStreamsVector[i1], db.NumUnpackStreamsVector[i2])); if (db.NumUnpackStreamsVector[i1] == 0) return 0; return CompareFiles( db.Files[db.FolderStartFileIndex[i1]], db.Files[db.FolderStartFileIndex[i2]]); } //////////////////////////////////////////////////////////// static int CompareEmptyItems(const int *p1, const int *p2, void *param) { const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param; const CUpdateItem &u1 = updateItems[*p1]; const CUpdateItem &u2 = updateItems[*p2]; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); int n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); return MyStringCompareNoCase(u1.Name, u2.Name); } static const char *g_Exts = " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" " zip jar ear war msi" " 3gp avi mov mpeg mpg mpe wmv" " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav" " swf " " chm hxi hxs" " gif jpeg jpg jp2 png tiff bmp ico psd psp" " awg ps eps cgm dxf svg vrml wmf emf ai md" " cad dwg pps key sxi" " max 3ds" " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" " asm sql manifest dep " " mak clw csproj vcproj sln dsp dsw " " class " " bat cmd" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" " abf afm bdf fon mgf otf pcf pfa snf ttf" " dbf mdb nsf ntf wdb db fdb gdb" " exe dll ocx vbx sfx sys tlb awx com obj lib out o so " " pdb pch idb ncb opt"; int GetExtIndex(const char *ext) { int extIndex = 1; const char *p = g_Exts; for (;;) { char c = *p++; if (c == 0) return extIndex; if (c == ' ') continue; int pos = 0; for (;;) { char c2 = ext[pos++]; if (c2 == 0 && (c == 0 || c == ' ')) return extIndex; if (c != c2) break; c = *p++; } extIndex++; for (;;) { if (c == 0) return extIndex; if (c == ' ') break; c = *p++; } } } struct CRefItem { const CUpdateItem *UpdateItem; UInt32 Index; UInt32 ExtensionPos; UInt32 NamePos; int ExtensionIndex; CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): UpdateItem(&ui), Index(index), ExtensionPos(0), NamePos(0), ExtensionIndex(0) { if (sortByType) { int slashPos = GetReverseSlashPos(ui.Name); NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0); int dotPos = ui.Name.ReverseFind(L'.'); if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0)) ExtensionPos = ui.Name.Length(); else { ExtensionPos = dotPos + 1; UString us = ui.Name.Mid(ExtensionPos); if (!us.IsEmpty()) { us.MakeLower(); int i; AString s; for (i = 0; i < us.Length(); i++) { wchar_t c = us[i]; if (c >= 0x80) break; s += (char)c; } if (i == us.Length()) ExtensionIndex = GetExtIndex(s); else ExtensionIndex = 0; } } } } }; static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param) { const CRefItem &a1 = *p1; const CRefItem &a2 = *p2; const CUpdateItem &u1 = *a1.UpdateItem; const CUpdateItem &u2 = *a2.UpdateItem; int n; if (u1.IsDir != u2.IsDir) return (u1.IsDir) ? 1 : -1; if (u1.IsDir) { if (u1.IsAnti != u2.IsAnti) return (u1.IsAnti ? 1 : -1); n = MyStringCompareNoCase(u1.Name, u2.Name); return -n; } bool sortByType = *(bool *)param; if (sortByType) { RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex)) RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos)); RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos)); if (!u1.MTimeDefined && u2.MTimeDefined) return 1; if (u1.MTimeDefined && !u2.MTimeDefined) return -1; if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime)); RINOZ(MyCompare(u1.Size, u2.Size)) } return MyStringCompareNoCase(u1.Name, u2.Name); } struct CSolidGroup { CCompressionMethodMode Method; CRecordVector<UInt32> Indices; }; static wchar_t *g_ExeExts[] = { L"dll", L"exe", L"ocx", L"sfx", L"sys" }; static bool IsExeFile(const UString &ext) { for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++) if (ext.CompareNoCase(g_ExeExts[i]) == 0) return true; return false; } static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; static const UInt64 k_BCJ2 = 0x0303011B; static bool GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult) { methodResult.Id = methodID; methodResult.NumInStreams = numInStreams; methodResult.NumOutStreams = 1; return true; } static bool MakeExeMethod(const CCompressionMethodMode &method, bool bcj2Filter, CCompressionMethodMode &exeMethod) { exeMethod = method; if (bcj2Filter) { CMethodFull methodFull; if (!GetMethodFull(k_BCJ2, 4, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); if (!GetMethodFull(k_LZMA, 1, methodFull)) return false; { CProp prop; prop.Id = NCoderPropID::kAlgorithm; prop.Value = kAlgorithmForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kMatchFinder; prop.Value = kMatchFinderForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kDictionarySize; prop.Value = kDictionaryForBCJ2_LZMA; methodFull.Props.Add(prop); } { CProp prop; prop.Id = NCoderPropID::kNumFastBytes; prop.Value = kNumFastBytesForBCJ2_LZMA; methodFull.Props.Add(prop); } exeMethod.Methods.Add(methodFull); exeMethod.Methods.Add(methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); bind.InCoder = 2; bind.OutStream = 1; exeMethod.Binds.Add(bind); bind.InCoder = 3; bind.OutStream = 2; exeMethod.Binds.Add(bind); } else { CMethodFull methodFull; if (!GetMethodFull(k_BCJ, 1, methodFull)) return false; exeMethod.Methods.Insert(0, methodFull); CBind bind; bind.OutCoder = 0; bind.InStream = 0; bind.InCoder = 1; bind.OutStream = 0; exeMethod.Binds.Add(bind); } return true; } static void SplitFilesToGroups( const CCompressionMethodMode &method, bool useFilters, bool maxFilter, const CObjectVector<CUpdateItem> &updateItems, CObjectVector<CSolidGroup> &groups) { if (method.Methods.Size() != 1 || method.Binds.Size() != 0) useFilters = false; groups.Clear(); groups.Add(CSolidGroup()); groups.Add(CSolidGroup()); CSolidGroup &generalGroup = groups[0]; CSolidGroup &exeGroup = groups[1]; generalGroup.Method = method; int i; for (i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (!ui.NewData) continue; if (!ui.HasStream()) continue; if (useFilters) { const UString name = ui.Name; int dotPos = name.ReverseFind(L'.'); if (dotPos >= 0) { UString ext = name.Mid(dotPos + 1); if (IsExeFile(ext)) { exeGroup.Indices.Add(i); continue; } } } generalGroup.Indices.Add(i); } if (exeGroup.Indices.Size() > 0) if (!MakeExeMethod(method, maxFilter, exeGroup.Method)) exeGroup.Method = method; for (i = 0; i < groups.Size();) if (groups[i].Indices.Size() == 0) groups.Delete(i); else i++; } static void FromUpdateItemToFileItem(const CUpdateItem &ui, CFileItem &file, CFileItem2 &file2) { file.Name = NItemName::MakeLegalName(ui.Name); if (ui.AttribDefined) file.SetAttrib(ui.Attrib); file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined; file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined; file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined; file2.IsAnti = ui.IsAnti; file2.StartPosDefined = false; file.Size = ui.Size; file.IsDir = ui.IsDir; file.HasStream = ui.HasStream(); } static HRESULT Update2( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { UInt64 numSolidFiles = options.NumSolidFiles; if (numSolidFiles == 0) numSolidFiles = 1; /* CMyComPtr<IOutStream> outStream; RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); if (!outStream) return E_NOTIMPL; */ UInt64 startBlockSize = db != 0 ? db->ArchiveInfo.StartPosition: 0; if (startBlockSize > 0 && !options.RemoveSfxBlock) { RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL)); } CRecordVector<int> fileIndexToUpdateIndexMap; if (db != 0) { fileIndexToUpdateIndexMap.Reserve(db->Files.Size()); for (int i = 0; i < db->Files.Size(); i++) fileIndexToUpdateIndexMap.Add(-1); } int i; for(i = 0; i < updateItems.Size(); i++) { int index = updateItems[i].IndexInArchive; if (index != -1) fileIndexToUpdateIndexMap[index] = i; } CRecordVector<int> folderRefs; if (db != 0) { for(i = 0; i < db->Folders.Size(); i++) { CNum indexInFolder = 0; CNum numCopyItems = 0; CNum numUnpackStreams = db->NumUnpackStreamsVector[i]; for (CNum fileIndex = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fileIndex++) { if (db->Files[fileIndex].HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fileIndex]; if (updateIndex >= 0) if (!updateItems[updateIndex].NewData) numCopyItems++; } } if (numCopyItems != numUnpackStreams && numCopyItems != 0) return E_NOTIMPL; // It needs repacking !!! if (numCopyItems > 0) folderRefs.Add(i); } folderRefs.Sort(CompareFolderRefs, (void *)db); } //////////////////////////// RINOK(archive.Create(seqOutStream, false)); RINOK(archive.SkeepPrefixArchiveHeader()); UInt64 complexity = 0; for(i = 0; i < folderRefs.Size(); i++) complexity += db->GetFolderFullPackSize(folderRefs[i]); UInt64 inSizeForReduce = 0; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { complexity += ui.Size; if (numSolidFiles == 1) { if (ui.Size > inSizeForReduce) inSizeForReduce = ui.Size; } else inSizeForReduce += ui.Size; } } RINOK(updateCallback->SetTotal(complexity)); complexity = 0; RINOK(updateCallback->SetCompleted(&complexity)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); ///////////////////////////////////////// // Write Copy Items for(i = 0; i < folderRefs.Size(); i++) { int folderIndex = folderRefs[i]; lps->ProgressOffset = complexity; UInt64 packSize = db->GetFolderFullPackSize(folderIndex); RINOK(WriteRange(inStream, archive.SeqStream, db->GetFolderStreamPos(folderIndex, 0), packSize, progress)); complexity += packSize; const CFolder &folder = db->Folders[folderIndex]; CNum startIndex = db->FolderStartPackStreamIndex[folderIndex]; for (int j = 0; j < folder.PackStreams.Size(); j++) { newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]); // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]); // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]); } newDatabase.Folders.Add(folder); CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex]; newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); CNum indexInFolder = 0; for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++) { CFileItem file; CFileItem2 file2; db->GetFile(fi, file, file2); if (file.HasStream) { indexInFolder++; int updateIndex = fileIndexToUpdateIndexMap[fi]; if (updateIndex >= 0) { const CUpdateItem &ui = updateItems[updateIndex]; if (ui.NewProperties) { CFileItem uf; FromUpdateItemToFileItem(ui, uf, file2); uf.Size = file.Size; uf.Crc = file.Crc; uf.CrcDefined = file.CrcDefined; uf.HasStream = file.HasStream; file = uf; } } newDatabase.AddFile(file, file2); } } } folderRefs.ClearAndFree(); fileIndexToUpdateIndexMap.ClearAndFree(); ///////////////////////////////////////// // Compress New Files CObjectVector<CSolidGroup> groups; SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, updateItems, groups); const UInt32 kMinReduceSize = (1 << 16); if (inSizeForReduce < kMinReduceSize) inSizeForReduce = kMinReduceSize; for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++) { const CSolidGroup &group = groups[groupIndex]; int numFiles = group.Indices.Size(); if (numFiles == 0) continue; CRecordVector<CRefItem> refItems; refItems.Reserve(numFiles); bool sortByType = (numSolidFiles > 1); for (i = 0; i < numFiles; i++) refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType)); refItems.Sort(CompareUpdateItems, (void *)&sortByType); CRecordVector<UInt32> indices; indices.Reserve(numFiles); for (i = 0; i < numFiles; i++) { UInt32 index = refItems[i].Index; indices.Add(index); /* const CUpdateItem &ui = updateItems[index]; CFileItem file; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file); else file = db.Files[ui.IndexInArchive]; if (file.IsAnti || file.IsDir) return E_FAIL; newDatabase.Files.Add(file); */ } CEncoder encoder(group.Method); for (i = 0; i < numFiles;) { UInt64 totalSize = 0; int numSubFiles; UString prevExtension; for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++) { const CUpdateItem &ui = updateItems[indices[i + numSubFiles]]; totalSize += ui.Size; if (totalSize > options.NumSolidBytes) break; if (options.SolidExtension) { UString ext = ui.GetExtension(); if (numSubFiles == 0) prevExtension = ext; else if (ext.CompareNoCase(prevExtension) != 0) break; } } if (numSubFiles < 1) numSubFiles = 1; CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); inStreamSpec->Init(updateCallback, &indices[i], numSubFiles); CFolder folderItem; int startPackIndex = newDatabase.PackSizes.Size(); RINOK(encoder.Encode( EXTERNAL_CODECS_LOC_VARS solidInStream, NULL, &inSizeForReduce, folderItem, archive.SeqStream, newDatabase.PackSizes, progress)); for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++) lps->OutSize += newDatabase.PackSizes[startPackIndex]; lps->InSize += folderItem.GetUnpackSize(); // for() // newDatabase.PackCRCsDefined.Add(false); // newDatabase.PackCRCs.Add(0); newDatabase.Folders.Add(folderItem); CNum numUnpackStreams = 0; for (int subIndex = 0; subIndex < numSubFiles; subIndex++) { const CUpdateItem &ui = updateItems[indices[i + subIndex]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); if (file2.IsAnti || file.IsDir) return E_FAIL; /* CFileItem &file = newDatabase.Files[ startFileIndexInDatabase + i + subIndex]; */ if (!inStreamSpec->Processed[subIndex]) { continue; // file.Name += L".locked"; } file.Crc = inStreamSpec->CRCs[subIndex]; file.Size = inStreamSpec->Sizes[subIndex]; if (file.Size != 0) { file.CrcDefined = true; file.HasStream = true; numUnpackStreams++; } else { file.CrcDefined = false; file.HasStream = false; } newDatabase.AddFile(file, file2); } // numUnpackStreams = 0 is very bad case for locked files // v3.13 doesn't understand it. newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams); i += numSubFiles; } } groups.ClearAndFree(); { ///////////////////////////////////////// // Write Empty Files & Folders CRecordVector<int> emptyRefs; for(i = 0; i < updateItems.Size(); i++) { const CUpdateItem &ui = updateItems[i]; if (ui.NewData) { if (ui.HasStream()) continue; } else if (ui.IndexInArchive != -1) if (db->Files[ui.IndexInArchive].HasStream) continue; emptyRefs.Add(i); } emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems); for (i = 0; i < emptyRefs.Size(); i++) { const CUpdateItem &ui = updateItems[emptyRefs[i]]; CFileItem file; CFileItem2 file2; if (ui.NewProperties) FromUpdateItemToFileItem(ui, file, file2); else db->GetFile(ui.IndexInArchive, file, file2); newDatabase.AddFile(file, file2); } } newDatabase.ReserveDown(); return S_OK; } HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options) { return Update2( EXTERNAL_CODECS_LOC_VARS inStream, db, updateItems, archive, newDatabase, seqOutStream, updateCallback, options); } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/7zUpdate.h ================================================ // 7zUpdate.h #ifndef __7Z_UPDATE_H #define __7Z_UPDATE_H #include "7zIn.h" #include "7zOut.h" #include "7zCompressionMode.h" #include "../IArchive.h" namespace NArchive { namespace N7z { struct CUpdateItem { int IndexInArchive; int IndexInClient; UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 Size; UString Name; UInt32 Attrib; bool NewData; bool NewProperties; bool IsAnti; bool IsDir; bool AttribDefined; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool HasStream() const { return !IsDir && !IsAnti && Size != 0; } CUpdateItem(): IsAnti(false), IsDir(false), AttribDefined(false), CTimeDefined(false), ATimeDefined(false), MTimeDefined(false) {} void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }; int GetExtensionPos() const; UString GetExtension() const; }; struct CUpdateOptions { const CCompressionMethodMode *Method; const CCompressionMethodMode *HeaderMethod; bool UseFilters; bool MaxFilter; CHeaderOptions HeaderOptions; UInt64 NumSolidFiles; UInt64 NumSolidBytes; bool SolidExtension; bool RemoveSfxBlock; bool VolumeMode; }; HRESULT Update( DECL_EXTERNAL_CODECS_LOC_VARS IInStream *inStream, const CArchiveDatabaseEx *db, const CObjectVector<CUpdateItem> &updateItems, COutArchive &archive, CArchiveDatabase &newDatabase, ISequentialOutStream *seqOutStream, IArchiveUpdateCallback *updateCallback, const CUpdateOptions &options); }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Archive.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Archive2.def ================================================ EXPORTS CreateObject PRIVATE GetHandlerProperty PRIVATE GetNumberOfFormats PRIVATE GetHandlerProperty2 PRIVATE CreateObject PRIVATE GetNumberOfMethods PRIVATE GetMethodProperty PRIVATE SetLargePageMode PRIVATE ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/ArchiveExports.cpp ================================================ // ArchiveExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterArc.h" #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); #define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5]) static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } int FindFormatCalssId(const GUID *clsID) { GUID cls = *clsID; CLS_ARC_ID_ITEM(cls) = 0; if (cls != CLSID_CArchiveHandler) return -1; Byte id = CLS_ARC_ID_ITEM(*clsID); for (unsigned i = 0; i < g_NumArcs; i++) if (g_Arcs[i]->ClassId == id) return (int)i; return -1; } STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject) { COM_TRY_BEGIN { int needIn = (*iid == IID_IInArchive); int needOut = (*iid == IID_IOutArchive); if (!needIn && !needOut) return E_NOINTERFACE; int formatIndex = FindFormatCalssId(clsid); if (formatIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; const CArcInfo &arc = *g_Arcs[formatIndex]; if (needIn) { *outObject = arc.CreateInArchive(); ((IInArchive *)*outObject)->AddRef(); } else { if (!arc.CreateOutArchive) return CLASS_E_CLASSNOTAVAILABLE; *outObject = arc.CreateOutArchive(); ((IOutArchive *)*outObject)->AddRef(); } } COM_TRY_END return S_OK; } STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value) { if (formatIndex >= g_NumArcs) return E_INVALIDARG; const CArcInfo &arc = *g_Arcs[formatIndex]; NWindows::NCOM::CPropVariant prop; switch(propID) { case NArchive::kName: prop = arc.Name; break; case NArchive::kClassID: { GUID clsId = CLSID_CArchiveHandler; CLS_ARC_ID_ITEM(clsId) = arc.ClassId; return SetPropGUID(clsId, value); } case NArchive::kExtension: if (arc.Ext != 0) prop = arc.Ext; break; case NArchive::kAddExtension: if (arc.AddExt != 0) prop = arc.AddExt; break; case NArchive::kUpdate: prop = (bool)(arc.CreateOutArchive != 0); break; case NArchive::kKeepName: prop = arc.KeepName; break; case NArchive::kStartSignature: return SetPropString((const char *)arc.Signature, arc.SignatureSize, value); } prop.Detach(value); return S_OK; } STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) { return GetHandlerProperty2(0, propID, value); } STDAPI GetNumberOfFormats(UINT32 *numFormats) { *numFormats = g_NumArcs; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CoderMixer2.cpp ================================================ // CoderMixer2.cpp #include "StdAfx.h" #include "CoderMixer2.h" namespace NCoderMixer { CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): _srcBindInfo(srcBindInfo) { srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); UInt32 j; for (j = 0; j < NumSrcInStreams; j++) { _srcInToDestOutMap.Add(0); DestOutToSrcInMap.Add(0); } for (j = 0; j < _numSrcOutStreams; j++) { _srcOutToDestInMap.Add(0); _destInToSrcOutMap.Add(0); } UInt32 destInOffset = 0; UInt32 destOutOffset = 0; UInt32 srcInOffset = NumSrcInStreams; UInt32 srcOutOffset = _numSrcOutStreams; for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; srcInOffset -= srcCoderInfo.NumInStreams; srcOutOffset -= srcCoderInfo.NumOutStreams; UInt32 j; for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) { UInt32 index = srcInOffset + j; _srcInToDestOutMap[index] = destOutOffset; DestOutToSrcInMap[destOutOffset] = index; } for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) { UInt32 index = srcOutOffset + j; _srcOutToDestInMap[index] = destInOffset; _destInToSrcOutMap[destInOffset] = index; } } } void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) { destBindInfo.Coders.Clear(); destBindInfo.BindPairs.Clear(); destBindInfo.InStreams.Clear(); destBindInfo.OutStreams.Clear(); int i; for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--) { const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; CCoderStreamsInfo destCoderInfo; destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; destBindInfo.Coders.Add(destCoderInfo); } for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--) { const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; CBindPair destBindPair; destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; destBindInfo.BindPairs.Add(destBindPair); } for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); } CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): NumInStreams(numInStreams), NumOutStreams(numOutStreams) { InSizes.Reserve(NumInStreams); InSizePointers.Reserve(NumInStreams); OutSizePointers.Reserve(NumOutStreams); OutSizePointers.Reserve(NumOutStreams); } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CoderMixer2.h ================================================ // CoderMixer2.h #ifndef __CODER_MIXER2_H #define __CODER_MIXER2_H #include "../../../Common/MyVector.h" #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../ICoder.h" namespace NCoderMixer { struct CBindPair { UInt32 InIndex; UInt32 OutIndex; }; struct CCoderStreamsInfo { UInt32 NumInStreams; UInt32 NumOutStreams; }; struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; CRecordVector<CBindPair> BindPairs; CRecordVector<UInt32> InStreams; CRecordVector<UInt32> OutStreams; void Clear() { Coders.Clear(); BindPairs.Clear(); InStreams.Clear(); OutStreams.Clear(); } /* UInt32 GetCoderStartOutStream(UInt32 coderIndex) const { UInt32 numOutStreams = 0; for (UInt32 i = 0; i < coderIndex; i++) numOutStreams += Coders[i].NumOutStreams; return numOutStreams; } */ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const { numInStreams = 0; numOutStreams = 0; for (int i = 0; i < Coders.Size(); i++) { const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; numInStreams += coderStreamsInfo.NumInStreams; numOutStreams += coderStreamsInfo.NumOutStreams; } } int FindBinderForInStream(UInt32 inStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].InIndex == inStream) return i; return -1; } int FindBinderForOutStream(UInt32 outStream) const { for (int i = 0; i < BindPairs.Size(); i++) if (BindPairs[i].OutIndex == outStream) return i; return -1; } UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumInStreams; return streamIndex; } UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) streamIndex += Coders[i].NumOutStreams; return streamIndex; } void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumInStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const { for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) { UInt32 curSize = Coders[coderIndex].NumOutStreams; if (streamIndex < curSize) { coderStreamIndex = streamIndex; return; } streamIndex -= curSize; } throw 1; } }; class CBindReverseConverter { UInt32 _numSrcOutStreams; NCoderMixer::CBindInfo _srcBindInfo; CRecordVector<UInt32> _srcInToDestOutMap; CRecordVector<UInt32> _srcOutToDestInMap; CRecordVector<UInt32> _destInToSrcOutMap; public: UInt32 NumSrcInStreams; CRecordVector<UInt32> DestOutToSrcInMap; CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); }; struct CCoderInfo2 { CMyComPtr<ICompressCoder> Coder; CMyComPtr<ICompressCoder2> Coder2; UInt32 NumInStreams; UInt32 NumOutStreams; CRecordVector<UInt64> InSizes; CRecordVector<UInt64> OutSizes; CRecordVector<const UInt64 *> InSizePointers; CRecordVector<const UInt64 *> OutSizePointers; CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); HRESULT QueryInterface(REFGUID iid, void** pp) const { IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; return p->QueryInterface(iid, pp); } }; class CCoderMixer2 { public: virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; virtual void ReInit() = 0; virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CoderMixer2MT.cpp ================================================ // CoderMixer2MT.cpp #include "StdAfx.h" #include "CoderMixer2MT.h" namespace NCoderMixer { CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): CCoderInfo2(numInStreams, numOutStreams) { InStreams.Reserve(NumInStreams); InStreamPointers.Reserve(NumInStreams); OutStreams.Reserve(NumOutStreams); OutStreamPointers.Reserve(NumOutStreams); } void CCoder2::Execute() { Code(NULL); } void CCoder2::Code(ICompressProgressInfo *progress) { InStreamPointers.Clear(); OutStreamPointers.Clear(); UInt32 i; for (i = 0; i < NumInStreams; i++) { if (InSizePointers[i] != NULL) InSizePointers[i] = &InSizes[i]; InStreamPointers.Add((ISequentialInStream *)InStreams[i]); } for (i = 0; i < NumOutStreams; i++) { if (OutSizePointers[i] != NULL) OutSizePointers[i] = &OutSizes[i]; OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); } if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], InSizePointers[0], OutSizePointers[0], progress); else Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); { int i; for (i = 0; i < InStreams.Size(); i++) InStreams[i].Release(); for (i = 0; i < OutStreams.Size(); i++) OutStreams[i].Release(); } } static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) { sizes.Clear(); sizePointers.Clear(); for(UInt32 i = 0; i < numItems; i++) { if (srcSizes == 0 || srcSizes[i] == NULL) { sizes.Add(0); sizePointers.Add(NULL); } else { sizes.Add(*srcSizes[i]); sizePointers.Add(&sizes.Back()); } } } void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) { SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); } ////////////////////////////////////// // CCoderMixer2MT HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) { _bindInfo = bindInfo; _streamBinders.Clear(); for(int i = 0; i < _bindInfo.BindPairs.Size(); i++) { _streamBinders.Add(CStreamBinder()); RINOK(_streamBinders.Back().CreateEvents()); } return S_OK; } void CCoderMixer2MT::AddCoderCommon() { const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); _coders.Add(threadCoderInfo); } void CCoderMixer2MT::AddCoder(ICompressCoder *coder) { AddCoderCommon(); _coders.Back().Coder = coder; } void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) { AddCoderCommon(); _coders.Back().Coder2 = coder; } void CCoderMixer2MT::ReInit() { for(int i = 0; i < _streamBinders.Size(); i++) _streamBinders[i].ReInit(); } HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) { /* if (_coders.Size() != _bindInfo.Coders.Size()) throw 0; */ int i; for(i = 0; i < _coders.Size(); i++) { CCoder2 &coderInfo = _coders[i]; const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; coderInfo.InStreams.Clear(); UInt32 j; for(j = 0; j < coderStreamsInfo.NumInStreams; j++) coderInfo.InStreams.Add(NULL); coderInfo.OutStreams.Clear(); for(j = 0; j < coderStreamsInfo.NumOutStreams; j++) coderInfo.OutStreams.Add(NULL); } for(i = 0; i < _bindInfo.BindPairs.Size(); i++) { const CBindPair &bindPair = _bindInfo.BindPairs[i]; UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); } for(i = 0; i < _bindInfo.InStreams.Size(); i++) { UInt32 inCoderIndex, inCoderStreamIndex; _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; } for(i = 0; i < _bindInfo.OutStreams.Size(); i++) { UInt32 outCoderIndex, outCoderStreamIndex; _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; } return S_OK; } HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) { for (int i = 0; i < _coders.Size(); i++) if (_coders[i].Result == code) return code; return S_OK; } STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; Init(inStreams, outStreams); int i; for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].Start(); _coders[_progressCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) if (i != _progressCoderIndex) _coders[i].WaitFinish(); RINOK(ReturnIfError(E_ABORT)); RINOK(ReturnIfError(E_OUTOFMEMORY)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK && result != E_FAIL && result != S_FALSE) return result; } RINOK(ReturnIfError(S_FALSE)); for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; if (result != S_OK) return result; } return S_OK; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CoderMixer2MT.h ================================================ // CoderMixer2MT.h #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H #include "CoderMixer2.h" #include "../../../Common/MyCom.h" #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" namespace NCoderMixer { struct CCoder2: public CCoderInfo2, public CVirtThread { HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; CCoder2(UInt32 numInStreams, UInt32 numOutStreams); void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); virtual void Execute(); void Code(ICompressProgressInfo *progress); }; /* SetBindInfo() for each coder AddCoder[2]() SetProgressIndex(UInt32 coderIndex); for each file { ReInit() for each coder SetCoderInfo Code } */ class CCoderMixer2MT: public ICompressCoder2, public CCoderMixer2, public CMyUnknownImp { CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; int _progressCoderIndex; void AddCoderCommon(); HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); HRESULT ReturnIfError(HRESULT code); public: CObjectVector<CCoder2> _coders; MY_UNKNOWN_IMP STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); HRESULT SetBindInfo(const CBindInfo &bindInfo); void AddCoder(ICompressCoder *coder); void AddCoder2(ICompressCoder2 *coder); void SetProgressCoderIndex(int coderIndex) { _progressCoderIndex = coderIndex; } void ReInit(); void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } UInt64 GetWriteProcessedSize(UInt32 binderIndex) const { return _streamBinders[binderIndex].ProcessedSize; } }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CrossThreadProgress.cpp ================================================ // CrossThreadProgress.cpp #include "StdAfx.h" #include "CrossThreadProgress.h" STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { InSize = inSize; OutSize = outSize; ProgressEvent.Set(); WaitEvent.Lock(); return Result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/CrossThreadProgress.h ================================================ // CrossThreadProgress.h #ifndef __CROSSTHREADPROGRESS_H #define __CROSSTHREADPROGRESS_H #include "../../ICoder.h" #include "../../../Windows/Synchronization.h" #include "../../../Common/MyCom.h" class CCrossThreadProgress: public ICompressProgressInfo, public CMyUnknownImp { public: const UInt64 *InSize; const UInt64 *OutSize; HRESULT Result; NWindows::NSynchronization::CAutoResetEvent ProgressEvent; NWindows::NSynchronization::CAutoResetEvent WaitEvent; HRes Create() { RINOK(ProgressEvent.CreateIfNotCreated()); return WaitEvent.CreateIfNotCreated(); } void Init() { ProgressEvent.Reset(); WaitEvent.Reset(); } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/DummyOutStream.cpp ================================================ // DummyOutStream.cpp #include "StdAfx.h" #include "DummyOutStream.h" STDMETHODIMP CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/DummyOutStream.h ================================================ // DummyOutStream.h #ifndef __DUMMYOUTSTREAM_H #define __DUMMYOUTSTREAM_H #include "../../IStream.h" #include "Common/MyCom.h" class CDummyOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *outStream) { _stream = outStream; } void ReleaseStream() { _stream.Release(); } void Init() { _size = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/HandlerOut.cpp ================================================ // HandlerOut.cpp #include "StdAfx.h" #include "../../../Common/StringToInt.h" #include "../../../Windows/PropVariant.h" #ifdef COMPRESS_MT #include "../../../Windows/System.h" #endif #include "../../ICoder.h" #include "../Common/ParseProperties.h" #include "HandlerOut.h" using namespace NWindows; namespace NArchive { static const wchar_t *kCopyMethod = L"Copy"; static const wchar_t *kLZMAMethodName = L"LZMA"; static const wchar_t *kLZMA2MethodName = L"LZMA2"; static const wchar_t *kBZip2MethodName = L"BZip2"; static const wchar_t *kPpmdMethodName = L"PPMd"; static const wchar_t *kDeflateMethodName = L"Deflate"; static const wchar_t *kDeflate64MethodName = L"Deflate64"; static const wchar_t *kLzmaMatchFinderX1 = L"HC4"; static const wchar_t *kLzmaMatchFinderX5 = L"BT4"; static const UInt32 kLzmaAlgoX1 = 0; static const UInt32 kLzmaAlgoX5 = 1; static const UInt32 kLzmaDicSizeX1 = 1 << 16; static const UInt32 kLzmaDicSizeX3 = 1 << 20; static const UInt32 kLzmaDicSizeX5 = 1 << 24; static const UInt32 kLzmaDicSizeX7 = 1 << 25; static const UInt32 kLzmaDicSizeX9 = 1 << 26; static const UInt32 kLzmaFastBytesX1 = 32; static const UInt32 kLzmaFastBytesX7 = 64; static const UInt32 kPpmdMemSizeX1 = (1 << 22); static const UInt32 kPpmdMemSizeX5 = (1 << 24); static const UInt32 kPpmdMemSizeX7 = (1 << 26); static const UInt32 kPpmdMemSizeX9 = (192 << 20); static const UInt32 kPpmdOrderX1 = 4; static const UInt32 kPpmdOrderX5 = 6; static const UInt32 kPpmdOrderX7 = 16; static const UInt32 kPpmdOrderX9 = 32; static const UInt32 kDeflateAlgoX1 = 0; static const UInt32 kDeflateAlgoX5 = 1; static const UInt32 kDeflateFastBytesX1 = 32; static const UInt32 kDeflateFastBytesX7 = 64; static const UInt32 kDeflateFastBytesX9 = 128; static const UInt32 kDeflatePassesX1 = 1; static const UInt32 kDeflatePassesX7 = 3; static const UInt32 kDeflatePassesX9 = 10; static const UInt32 kBZip2NumPassesX1 = 1; static const UInt32 kBZip2NumPassesX7 = 2; static const UInt32 kBZip2NumPassesX9 = 7; static const UInt32 kBZip2DicSizeX1 = 100000; static const UInt32 kBZip2DicSizeX3 = 500000; static const UInt32 kBZip2DicSizeX5 = 900000; static const wchar_t *kDefaultMethodName = kLZMAMethodName; static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2"; static const UInt32 kDictionaryForHeaders = 1 << 20; static const UInt32 kNumFastBytesForHeaders = 273; static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5; static bool AreEqual(const UString &methodName, const wchar_t *s) { return (methodName.CompareNoCase(s) == 0); } static inline bool IsLZMAMethod(const UString &methodName) { return AreEqual(methodName, kLZMAMethodName) || AreEqual(methodName, kLZMA2MethodName); } static inline bool IsBZip2Method(const UString &methodName) { return AreEqual(methodName, kBZip2MethodName); } static inline bool IsPpmdMethod(const UString &methodName) { return AreEqual(methodName, kPpmdMethodName); } static inline bool IsDeflateMethod(const UString &methodName) { return AreEqual(methodName, kDeflateMethodName) || AreEqual(methodName, kDeflate64MethodName); } struct CNameToPropID { PROPID PropID; VARTYPE VarType; const wchar_t *Name; }; CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kEndMarker, VT_BOOL, L"eos" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" } }; static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp) { if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if (srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = (Byte)value; return true; } } else if (varType == VT_BOOL) { bool res; if (SetBoolProperty(res, srcProp) != S_OK) return false; destProp = res; return true; } return false; } static int FindPropIdFromStringName(const UString &name) { for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1; } static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value) { for (int j = 0; j < oneMethodInfo.Props.Size(); j++) if (oneMethodInfo.Props[j].Id == propID) return; CProp prop; prop.Id = propID; prop.Value = value; oneMethodInfo.Props.Add(prop); } void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ) { UInt32 level = _level; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algo = (level >= 5 ? kLzmaAlgoX5 : kLzmaAlgoX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); UInt32 algo = (level >= 5 ? kDeflateAlgoX5 : kDeflateAlgoX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } } static void SplitParams(const UString &srcString, UStringVector &subStrings) { subStrings.Clear(); UString name; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L':') { subStrings.Add(name); name.Empty(); } else name += c; } subStrings.Add(name); } static void SplitParam(const UString ¶m, UString &name, UString &value) { int eqPos = param.Find(L'='); if (eqPos >= 0) { name = param.Left(eqPos); value = param.Mid(eqPos + 1); return; } for(int i = 0; i < param.Length(); i++) { wchar_t c = param[i]; if (c >= L'0' && c <= L'9') { name = param.Left(i); value = param.Mid(i); return; } } name = param; } HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value) { CProp prop; if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(value, dicSize)); prop.Id = (name.CompareNoCase(L"D") == 0) ? NCoderPropID::kDictionarySize : NCoderPropID::kUsedMemorySize; prop.Value = dicSize; } else { int index = FindPropIdFromStringName(name); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; NCOM::CPropVariant propValue; if (nameToPropID.VarType == VT_BSTR) propValue = value; else if (nameToPropID.VarType == VT_BOOL) { bool res; if (!StringToBool(value, res)) return E_INVALIDARG; propValue = res; } else { UInt32 number; if (ParseStringToUInt32(value, number) == value.Length()) propValue = number; else propValue = value; } if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); return S_OK; } HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString) { UStringVector params; SplitParams(srcString, params); if (params.Size() > 0) oneMethodInfo.MethodName = params[0]; for (int i = 1; i < params.Size(); i++) { const UString ¶m = params[i]; UString name, value; SplitParam(param, name, value); RINOK(SetParam(oneMethodInfo, name, value)); } return S_OK; } HRESULT COutHandler::SetSolidSettings(const UString &s) { UString s2 = s; s2.MakeUpper(); for (int i = 0; i < s2.Length();) { const wchar_t *start = ((const wchar_t *)s2) + i; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (start == end) { if (s2[i++] != 'E') return E_INVALIDARG; _solidExtension = true; continue; } i += (int)(end - start); if (i == s2.Length()) return E_INVALIDARG; wchar_t c = s2[i++]; switch(c) { case 'F': if (v < 1) v = 1; _numSolidFiles = v; break; case 'B': _numSolidBytes = v; _numSolidBytesDefined = true; break; case 'K': _numSolidBytes = (v << 10); _numSolidBytesDefined = true; break; case 'M': _numSolidBytes = (v << 20); _numSolidBytesDefined = true; break; case 'G': _numSolidBytes = (v << 30); _numSolidBytesDefined = true; break; default: return E_INVALIDARG; } } return S_OK; } HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value) { bool isSolid; switch(value.vt) { case VT_EMPTY: isSolid = true; break; case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; case VT_BSTR: if (StringToBool(value.bstrVal, isSolid)) break; return SetSolidSettings(value.bstrVal); default: return E_INVALIDARG; } if (isSolid) InitSolid(); else _numSolidFiles = 1; return S_OK; } void COutHandler::Init() { _removeSfxBlock = false; _compressHeaders = true; _encryptHeadersSpecified = false; _encryptHeaders = false; WriteCTime = false; WriteATime = false; WriteMTime = true; #ifdef COMPRESS_MT _numThreads = NWindows::NSystem::GetNumberOfProcessors(); #endif _level = 5; _autoFilter = true; _volumeMode = false; _crcSize = 4; InitSolid(); } void COutHandler::BeforeSetProperty() { Init(); #ifdef COMPRESS_MT numProcessors = NSystem::GetNumberOfProcessors(); #endif mainDicSize = 0xFFFFFFFF; mainDicMethodIndex = 0xFFFFFFFF; minNumber = 0; _crcSize = 4; } HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) { UString name = nameSpec; name.MakeUpper(); if (name.IsEmpty()) return E_INVALIDARG; if (name[0] == 'X') { name.Delete(0); _level = 9; return ParsePropValue(name, value, _level); } if (name[0] == L'S') { name.Delete(0); if (name.IsEmpty()) return SetSolidSettings(value); if (value.vt != VT_EMPTY) return E_INVALIDARG; return SetSolidSettings(name); } if (name == L"CRC") { _crcSize = 4; name.Delete(0, 3); return ParsePropValue(name, value, _crcSize); } UInt32 number; int index = ParseStringToUInt32(name, number); UString realName = name.Mid(index); if (index == 0) { if(name.Left(2).CompareNoCase(L"MT") == 0) { #ifdef COMPRESS_MT RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); #endif return S_OK; } if (name.CompareNoCase(L"RSFX") == 0) return SetBoolProperty(_removeSfxBlock, value); if (name.CompareNoCase(L"F") == 0) return SetBoolProperty(_autoFilter, value); if (name.CompareNoCase(L"HC") == 0) return SetBoolProperty(_compressHeaders, value); if (name.CompareNoCase(L"HCF") == 0) { bool compressHeadersFull = true; RINOK(SetBoolProperty(compressHeadersFull, value)); if (!compressHeadersFull) return E_INVALIDARG; return S_OK; } if (name.CompareNoCase(L"HE") == 0) { RINOK(SetBoolProperty(_encryptHeaders, value)); _encryptHeadersSpecified = true; return S_OK; } if (name.CompareNoCase(L"TC") == 0) return SetBoolProperty(WriteCTime, value); if (name.CompareNoCase(L"TA") == 0) return SetBoolProperty(WriteATime, value); if (name.CompareNoCase(L"TM") == 0) return SetBoolProperty(WriteMTime, value); if (name.CompareNoCase(L"V") == 0) return SetBoolProperty(_volumeMode, value); number = 0; } if (number > 10000) return E_FAIL; if (number < minNumber) return E_INVALIDARG; number -= minNumber; for(int j = _methods.Size(); j <= (int)number; j++) { COneMethodInfo oneMethodInfo; _methods.Add(oneMethodInfo); } COneMethodInfo &oneMethodInfo = _methods[number]; if (realName.Length() == 0) { if (value.vt != VT_BSTR) return E_INVALIDARG; RINOK(SetParams(oneMethodInfo, value.bstrVal)); } else { CProp prop; if (realName.Left(1).CompareNoCase(L"D") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize)); prop.Id = NCoderPropID::kDictionarySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else if (realName.Left(1).CompareNoCase(L"C") == 0) { UInt32 blockSize; RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize)); prop.Id = NCoderPropID::kBlockSize; prop.Value = blockSize; } else if (realName.Left(3).CompareNoCase(L"MEM") == 0) { UInt32 dicSize; RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize)); prop.Id = NCoderPropID::kUsedMemorySize; prop.Value = dicSize; if (number <= mainDicMethodIndex) mainDicSize = dicSize; } else { int index = FindPropIdFromStringName(realName); if (index < 0) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[index]; prop.Id = nameToPropID.PropID; if (!ConvertProperty(value, nameToPropID.VarType, prop.Value)) return E_INVALIDARG; } oneMethodInfo.Props.Add(prop); } return S_OK; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/HandlerOut.h ================================================ // HandlerOut.h #ifndef __HANDLER_OUT_H #define __HANDLER_OUT_H #include "../../../Common/MyString.h" #include "../../Common/MethodProps.h" namespace NArchive { struct COneMethodInfo { CObjectVector<CProp> Props; UString MethodName; }; class COutHandler { public: HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); HRESULT SetSolidSettings(const UString &s); HRESULT SetSolidSettings(const PROPVARIANT &value); #ifdef COMPRESS_MT UInt32 _numThreads; #endif UInt32 _crcSize; CObjectVector<COneMethodInfo> _methods; bool _removeSfxBlock; UInt64 _numSolidFiles; UInt64 _numSolidBytes; bool _numSolidBytesDefined; bool _solidExtension; bool _compressHeaders; bool _encryptHeadersSpecified; bool _encryptHeaders; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _autoFilter; UInt32 _level; bool _volumeMode; HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value); HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString); void SetCompressionMethod2(COneMethodInfo &oneMethodInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ); void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolid() { InitSolidFiles(); InitSolidSize(); _solidExtension = false; _numSolidBytesDefined = false; } void Init(); COutHandler() { Init(); } void BeforeSetProperty(); UInt32 minNumber; UInt32 numProcessors; UInt32 mainDicSize; UInt32 mainDicMethodIndex; }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/InStreamWithCRC.cpp ================================================ // InStreamWithCRC.cpp #include "StdAfx.h" #include "InStreamWithCRC.h" STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (size > 0 && realProcessedSize == 0) _wasFinished = true; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); if (size > 0 && realProcessedSize == 0) _wasFinished = true; _size += realProcessedSize; _crc = CrcUpdate(_crc, data, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if (seekOrigin != STREAM_SEEK_SET || offset != 0) return E_FAIL; _size = 0; _crc = CRC_INIT_VAL; return _stream->Seek(offset, seekOrigin, newPosition); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/InStreamWithCRC.h ================================================ // InStreamWithCRC.h #ifndef __INSTREAMWITHCRC_H #define __INSTREAMWITHCRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class CSequentialInStreamWithCRC: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; class CInStreamWithCRC: public IInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); private: CMyComPtr<IInStream> _stream; UInt64 _size; UInt32 _crc; bool _wasFinished; public: void SetStream(IInStream *stream) { _stream = stream; } void Init() { _size = 0; _wasFinished = false; _crc = CRC_INIT_VAL; } void ReleaseStream() { _stream.Release(); } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } UInt64 GetSize() const { return _size; } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/ItemNameUtils.cpp ================================================ // Archive/Common/ItemNameUtils.cpp #include "StdAfx.h" #include "ItemNameUtils.h" namespace NArchive { namespace NItemName { static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR; static const wchar_t kDirDelimiter = L'/'; UString MakeLegalName(const UString &name) { UString zipName = name; zipName.Replace(kOSDirDelimiter, kDirDelimiter); return zipName; } UString GetOSName(const UString &name) { UString newName = name; newName.Replace(kDirDelimiter, kOSDirDelimiter); return newName; } UString GetOSName2(const UString &name) { if (name.IsEmpty()) return UString(); UString newName = GetOSName(name); if (newName[newName.Length() - 1] == kOSDirDelimiter) newName.Delete(newName.Length() - 1); return newName; } bool HasTailSlash(const AString &name, UINT codePage) { if (name.IsEmpty()) return false; LPCSTR prev = #ifdef _WIN32 CharPrevExA((WORD)codePage, name, &name[name.Length()], 0); #else (LPCSTR)(name) + (name.Length() - 1); #endif return (*prev == '/'); } #ifndef _WIN32 UString WinNameToOSName(const UString &name) { UString newName = name; newName.Replace(L'\\', kOSDirDelimiter); return newName; } #endif }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/ItemNameUtils.h ================================================ // Archive/Common/ItemNameUtils.h #ifndef __ARCHIVE_ITEMNAMEUTILS_H #define __ARCHIVE_ITEMNAMEUTILS_H #include "../../../Common/MyString.h" namespace NArchive { namespace NItemName { UString MakeLegalName(const UString &name); UString GetOSName(const UString &name); UString GetOSName2(const UString &name); bool HasTailSlash(const AString &name, UINT codePage); #ifdef _WIN32 inline UString WinNameToOSName(const UString &name) { return name; } #else UString WinNameToOSName(const UString &name); #endif }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/MultiStream.cpp ================================================ // MultiStream.cpp #include "StdAfx.h" #include "MultiStream.h" STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(_streamIndex < Streams.Size() && size > 0) { CSubStreamInfo &s = Streams[_streamIndex]; if (_pos == s.Size) { _streamIndex++; _pos = 0; continue; } RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0)); UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos)); UInt32 realProcessed; HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; if(processedSize != NULL) *processedSize += realProcessed; _pos += realProcessed; _seekPos += realProcessed; RINOK(result); break; } return S_OK; } STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 newPos; switch(seekOrigin) { case STREAM_SEEK_SET: newPos = offset; break; case STREAM_SEEK_CUR: newPos = _seekPos + offset; break; case STREAM_SEEK_END: newPos = _totalLength + offset; break; default: return STG_E_INVALIDFUNCTION; } _seekPos = 0; for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++) { UInt64 size = Streams[_streamIndex].Size; if (newPos < _seekPos + size) { _pos = newPos - _seekPos; _seekPos += _pos; if (newPosition != 0) *newPosition = newPos; return S_OK; } _seekPos += size; } if (newPos == _seekPos) { if (newPosition != 0) *newPosition = newPos; return S_OK; } return E_FAIL; } /* class COutVolumeStream: public ISequentialOutStream, public CMyUnknownImp { int _volIndex; UInt64 _volSize; UInt64 _curPos; CMyComPtr<ISequentialOutStream> _volumeStream; COutArchive _archive; CCRC _crc; public: MY_UNKNOWN_IMP CFileItem _file; CUpdateOptions _options; CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init(IArchiveUpdateCallback2 *volumeCallback, const UString &name) { _file.Name = name; _file.IsStartPosDefined = true; _file.StartPos = 0; VolumeCallback = volumeCallback; _volIndex = 0; _volSize = 0; } HRESULT Flush(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; HRESULT COutVolumeStream::Flush() { if (_volumeStream) { _file.UnPackSize = _curPos; _file.FileCRC = _crc.GetDigest(); RINOK(WriteVolumeHeader(_archive, _file, _options)); _archive.Close(); _volumeStream.Release(); _file.StartPos += _file.UnPackSize; } return S_OK; } */ /* STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); subStream.Pos = 0; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; if (_offsetPos >= subStream.Size) { _offsetPos -= subStream.Size; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { CMyComPtr<IOutStream> outStream; RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == subStream.Size) { _streamIndex++; _offsetPos = 0; } if (realProcessed != curSize && realProcessed == 0) return E_FAIL; } return S_OK; } STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; _streamIndex = 0; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/MultiStream.h ================================================ // MultiStream.h #ifndef __MULTISTREAM_H #define __MULTISTREAM_H #include "../../../Common/MyCom.h" #include "../../../Common/MyVector.h" #include "../../Archive/IArchive.h" class CMultiStream: public IInStream, public CMyUnknownImp { int _streamIndex; UInt64 _pos; UInt64 _seekPos; UInt64 _totalLength; public: struct CSubStreamInfo { CMyComPtr<IInStream> Stream; UInt64 Pos; UInt64 Size; }; CObjectVector<CSubStreamInfo> Streams; void Init() { _streamIndex = 0; _pos = 0; _seekPos = 0; _totalLength = 0; for (int i = 0; i < Streams.Size(); i++) _totalLength += Streams[i].Size; } MY_UNKNOWN_IMP1(IInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; /* class COutMultiStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<ISequentialOutStream> Stream; UInt64 Size; UInt64 Pos; }; CObjectVector<CSubStreamInfo> Streams; public: CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; */ #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp ================================================ // OutStreamWithCRC.cpp #include "StdAfx.h" #include "OutStreamWithCRC.h" STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result; if(!_stream) { realProcessedSize = size; result = S_OK; } else result = _stream->Write(data, size, &realProcessedSize); if (_calculate) _crc = CrcUpdate(_crc, data, realProcessedSize); _size += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/OutStreamWithCRC.h ================================================ // OutStreamWithCRC.h #ifndef __OUT_STREAM_WITH_CRC_H #define __OUT_STREAM_WITH_CRC_H #include "../../../Common/MyCom.h" #include "../../IStream.h" extern "C" { #include "../../../../C/7zCrc.h" } class COutStreamWithCRC: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; UInt32 _crc; bool _calculate; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(bool calculate = true) { _size = 0; _calculate = calculate; _crc = CRC_INIT_VAL; } void InitCRC() { _crc = CRC_INIT_VAL; } UInt64 GetSize() const { return _size; } UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/ParseProperties.cpp ================================================ // ParseProperties.cpp #include "StdAfx.h" #include "ParseProperties.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (prop.vt == VT_UI4) { if (!name.IsEmpty()) return E_INVALIDARG; resValue = prop.ulVal; } else if (prop.vt == VT_EMPTY) { if(!name.IsEmpty()) { const wchar_t *start = name; const wchar_t *end; UInt64 v = ConvertStringToUInt64(start, &end); if (end - start != name.Length()) return E_INVALIDARG; resValue = (UInt32)v; } } else return E_INVALIDARG; return S_OK; } static const int kLogarithmicSizeLimit = 32; static const wchar_t kByteSymbol = L'B'; static const wchar_t kKiloByteSymbol = L'K'; static const wchar_t kMegaByteSymbol = L'M'; HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize) { UString srcString = srcStringSpec; srcString.MakeUpper(); const wchar_t *start = srcString; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || srcString.Length() > numDigits + 1) return E_INVALIDARG; if (srcString.Length() == numDigits) { if (number >= kLogarithmicSizeLimit) return E_INVALIDARG; dicSize = (UInt32)1 << (int)number; return S_OK; } switch (srcString[numDigits]) { case kByteSymbol: if (number >= ((UInt64)1 << kLogarithmicSizeLimit)) return E_INVALIDARG; dicSize = (UInt32)number; break; case kKiloByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10))) return E_INVALIDARG; dicSize = (UInt32)(number << 10); break; case kMegaByteSymbol: if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20))) return E_INVALIDARG; dicSize = (UInt32)(number << 20); break; default: return E_INVALIDARG; } return S_OK; } HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue) { if (name.IsEmpty()) { if (prop.vt == VT_UI4) { UInt32 logDicSize = prop.ulVal; if (logDicSize >= 32) return E_INVALIDARG; resValue = (UInt32)1 << logDicSize; return S_OK; } if (prop.vt == VT_BSTR) return ParsePropDictionaryValue(prop.bstrVal, resValue); return E_INVALIDARG; } return ParsePropDictionaryValue(name, resValue); } bool StringToBool(const UString &s, bool &res) { if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0) { res = true; return true; } if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0) { res = false; return true; } return false; } HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value) { switch(value.vt) { case VT_EMPTY: dest = true; return S_OK; case VT_BOOL: dest = (value.boolVal != VARIANT_FALSE); return S_OK; /* case VT_UI4: dest = (value.ulVal != 0); break; */ case VT_BSTR: return StringToBool(value.bstrVal, dest) ? S_OK : E_INVALIDARG; } return E_INVALIDARG; } int ParseStringToUInt32(const UString &srcString, UInt32 &number) { const wchar_t *start = srcString; const wchar_t *end; UInt64 number64 = ConvertStringToUInt64(start, &end); if (number64 > 0xFFFFFFFF) { number = 0; return 0; } number = (UInt32)number64; return (int)(end - start); } HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads) { if (name.IsEmpty()) { switch(prop.vt) { case VT_UI4: numThreads = prop.ulVal; break; default: { bool val; RINOK(SetBoolProperty(val, prop)); numThreads = (val ? defaultNumThreads : 1); break; } } } else { UInt32 number; int index = ParseStringToUInt32(name, number); if (index != name.Length()) return E_INVALIDARG; numThreads = number; } return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/ParseProperties.h ================================================ // ParseProperties.h #ifndef __PARSEPROPERTIES_H #define __PARSEPROPERTIES_H #include "Common/MyString.h" #include "Common/Types.h" HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize); HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); bool StringToBool(const UString &s, bool &res); HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value); int ParseStringToUInt32(const UString &srcString, UInt32 &number); HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/DllExports2.cpp ================================================ // DLLExports.cpp #include "StdAfx.h" #include "../../Common/MyInitGuid.h" #include "../../Common/ComTry.h" #include "../../Common/Types.h" #include "../../Windows/PropVariant.h" #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) extern "C" { #include "../../../C/Alloc.h" } #endif #include "IArchive.h" #include "../ICoder.h" #include "../IPassword.h" HINSTANCE g_hInstance; #ifndef _UNICODE #ifdef _WIN32 bool g_IsNT = false; static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { if (dwReason == DLL_PROCESS_ATTACH) { g_hInstance = hInstance; #ifndef _UNICODE #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif #endif } return TRUE; } DEFINE_GUID(CLSID_CArchiveHandler, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00); static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject); STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject); STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) { // COM_TRY_BEGIN *outObject = 0; if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter) { return CreateCoder(clsid, iid, outObject); } else { return CreateArchiver(clsid, iid, outObject); } // COM_TRY_END } STDAPI SetLargePageMode() { #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) SetLargePageSize(); #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/IArchive.h ================================================ // IArchive.h #ifndef __IARCHIVE_H #define __IARCHIVE_H #include "../IStream.h" #include "../IProgress.h" #include "../PropID.h" #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) namespace NFileTimeType { enum EEnum { kWindows, kUnix, kDOS }; } namespace NArchive { enum { kName = 0, kClassID, kExtension, kAddExtension, kUpdate, kKeepName, kStartSignature, kFinishSignature, kAssociate }; namespace NExtract { namespace NAskMode { enum { kExtract = 0, kTest, kSkip }; } namespace NOperationResult { enum { kOK = 0, kUnSupportedMethod, kDataError, kCRCError }; } } namespace NUpdate { namespace NOperationResult { enum { kOK = 0, kError }; } } } #define INTERFACE_IArchiveOpenCallback(x) \ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) { INTERFACE_IArchiveOpenCallback(PURE); }; #define INTERFACE_IArchiveExtractCallback(x) \ INTERFACE_IProgress(x) \ /* GetStream OUT: S_OK - OK, S_FALSE - skeep this file */ \ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) { INTERFACE_IArchiveExtractCallback(PURE) }; #define INTERFACE_IArchiveOpenVolumeCallback(x) \ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) { INTERFACE_IArchiveOpenVolumeCallback(PURE); }; ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) { STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; }; ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) { STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; }; /* IInArchive::Extract: indices must be sorted numItems = 0xFFFFFFFF means "all files" testMode != 0 means "test files without writing to outStream" */ #define INTERFACE_IInArchive(x) \ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ STDMETHOD(Close)() x; \ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; ARCHIVE_INTERFACE(IInArchive, 0x60) { INTERFACE_IInArchive(PURE) }; #define INTERFACE_IArchiveUpdateCallback(x) \ INTERFACE_IProgress(x); \ STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ Int32 *newData, /*1 - new data, 0 - old data */ \ Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ ) x; \ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) { INTERFACE_IArchiveUpdateCallback(PURE); }; #define INTERFACE_IArchiveUpdateCallback2(x) \ INTERFACE_IArchiveUpdateCallback(x) \ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) { INTERFACE_IArchiveUpdateCallback2(PURE); }; #define INTERFACE_IOutArchive(x) \ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ STDMETHOD(GetFileTimeType)(UInt32 *type) x; ARCHIVE_INTERFACE(IOutArchive, 0xA0) { INTERFACE_IOutArchive(PURE) }; ARCHIVE_INTERFACE(ISetProperties, 0x03) { STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; }; #define IMP_IInArchive_GetProp(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ #define IMP_IInArchive_GetProp_WITH_NAME(k) \ (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ const STATPROPSTG &srcItem = k[index]; \ *propID = srcItem.propid; *varType = srcItem.vt; \ if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ #define IMP_IInArchive_Props \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) #define IMP_IInArchive_Props_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) #define IMP_IInArchive_ArcProps \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) #define IMP_IInArchive_ArcProps_WITH_NAME \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) #define IMP_IInArchive_ArcProps_NO \ STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ { *numProperties = 0; return S_OK; } \ STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ { return E_NOTIMPL; } \ STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ { value->vt = VT_EMPTY; return S_OK; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp ================================================ // LzmaArcRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "LzmaHandler.h" static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } static CArcInfo g_ArcInfo = { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; REGISTER_ARC(Lzma) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp ================================================ // LzmaFiltersDecode.cpp #include "StdAfx.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { static const UInt64 k_LZMA = 0x030101; static const UInt64 k_BCJ = 0x03030103; HRESULT CDecoder::Code( DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress) { *inProcessedSize = (UInt64)(Int64)-1; if (block.FilterMethod > 1) return E_NOTIMPL; if (!_lzmaDecoder) { RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); if (_lzmaDecoder == 0) return E_NOTIMPL; } { CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); if (!setDecoderProperties) return E_NOTIMPL; RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); } bool filteredMode = (block.FilterMethod == 1); CMyComPtr<ICompressSetOutStream> setOutStream; if (filteredMode) { if (!_bcjStream) { CMyComPtr<ICompressCoder> coder; RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); if (!coder) return E_NOTIMPL; coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); if (!_bcjStream) return E_NOTIMPL; } _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); if (!setOutStream) return E_NOTIMPL; RINOK(setOutStream->SetOutStream(outStream)); outStream = _bcjStream; } const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); if (filteredMode) { CMyComPtr<IOutStreamFlush> flush; _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) { RINOK(flush->Flush()); } RINOK(setOutStream->ReleaseOutStream()); } CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); if (getInStreamProcessedSize) { RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); } return S_OK; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h ================================================ // LzmaFiltersDecode.h #ifndef __LZMA_FILTERS_DECODE_H #define __LZMA_FILTERS_DECODE_H #include "../../Common/CreateCoder.h" #include "LzmaItem.h" namespace NArchive { namespace NLzma { class CDecoder { CMyComPtr<ICompressCoder> _lzmaDecoder; CMyComPtr<ISequentialOutStream> _bcjStream; public: HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS const CHeader &block, ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 *inProcessedSize, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaHandler.cpp ================================================ // LzmaHandler.cpp #include "StdAfx.h" #include "LzmaHandler.h" #include "Common/Defs.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Common/IntToString.h" #include "Windows/PropVariant.h" #include "../../Common/ProgressUtils.h" #include "../../Common/StreamUtils.h" #include "../Common/DummyOutStream.h" #include "LzmaFiltersDecode.h" namespace NArchive { namespace NLzma { STATPROPSTG kProps[] = { { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, { NULL, kpidMethod, VT_UI1} }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = 1; return S_OK; } static void ConvertUInt32ToString(UInt32 value, wchar_t *s) { ConvertUInt64ToString(value, s + MyStringLen(s)); } static void DictSizeToString(UInt32 value, wchar_t *s) { for (int i = 0; i <= 31; i++) if ((UInt32(1) << i) == value) { ConvertUInt32ToString(i, s); return; } wchar_t c = L'b'; if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = L'm'; } else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = L'k'; } ConvertUInt32ToString(value, s); int p = MyStringLen(s); s[p++] = c; s[p++] = L'\0'; } static void MyStrCat(wchar_t *d, const wchar_t *s) { MyStringCopy(d + MyStringLen(d), s); } STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { if (index != 0) return E_INVALIDARG; NWindows::NCOM::CPropVariant propVariant; switch(propID) { case kpidSize: if (m_StreamInfo.HasUnpackSize()) propVariant = (UInt64)m_StreamInfo.UnpackSize; break; case kpidPackSize: propVariant = (UInt64)m_PackSize; break; case kpidMethod: { wchar_t s[64]; s[0] = '\0'; if (m_StreamInfo.IsThereFilter) { const wchar_t *f; if (m_StreamInfo.FilterMethod == 0) f = L"Copy"; else if (m_StreamInfo.FilterMethod == 1) f = L"BCJ"; else f = L"Unknown"; MyStrCat(s, f); MyStrCat(s, L" "); } MyStrCat(s, L"LZMA:"); DictSizeToString(m_StreamInfo.GetDicSize(), s); propVariant = s; break; } } propVariant.Detach(value); return S_OK; } STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* openArchiveCallback */) { { RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); if (res != S_OK) return S_FALSE; Byte b; RINOK(ReadStream_FALSE(inStream, &b, 1)); if (b != 0) return S_FALSE; UInt64 endPos; RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); m_Stream = inStream; } return S_OK; } STDMETHODIMP CHandler::Close() { m_Stream.Release(); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN bool allFilesMode = (numItems == UInt32(-1)); if (!allFilesMode) { if (numItems == 0) return S_OK; if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); RINOK(extractCallback->SetTotal(m_PackSize)); UInt64 currentTotalPacked = 0; CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); { CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); outStreamSpec->SetStream(realOutStream); outStreamSpec->Init(); if(!testMode && !realOutStream) return S_OK; extractCallback->PrepareOperation(askMode); } CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, true); CDecoder decoder; RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); UInt64 streamPos = m_StreamStartPosition; Int32 opRes = NArchive::NExtract::NOperationResult::kOK; bool firstItem = true; for (;;) { CHeader st; HRESULT result = ReadStreamHeader(m_Stream, st); if (result != S_OK) { if (firstItem) return E_FAIL; break; } firstItem = false; lps->OutSize = outStreamSpec->GetSize(); lps->InSize = currentTotalPacked; RINOK(lps->SetCur()); streamPos += st.GetHeaderSize(); UInt64 packProcessed; { result = decoder.Code( EXTERNAL_CODECS_VARS st, m_Stream, outStream, &packProcessed, progress); if (result == E_NOTIMPL) { opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; break; } if (result == S_FALSE) { opRes = NArchive::NExtract::NOperationResult::kDataError; break; } RINOK(result); } if (packProcessed == (UInt64)(Int64)-1) break; RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); currentTotalPacked += packProcessed; streamPos += packProcessed; } outStream.Release(); return extractCallback->SetOperationResult(opRes); COM_TRY_END } IMPL_ISetCompressCodecsInfo }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaHandler.h ================================================ // Lzma/Handler.h #ifndef __GZIP_HANDLER_H #define __GZIP_HANDLER_H #include "Common/MyCom.h" #include "../IArchive.h" #include "../../Common/CreateCoder.h" #include "LzmaIn.h" namespace NArchive { namespace NLzma { // const UInt64 k_LZMA = 0x030101; class CHandler: public IInArchive, PUBLIC_ISetCompressCodecsInfo public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(IInArchive) QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Open)(IInStream *inStream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback); STDMETHOD(Close)(); STDMETHOD(GetNumberOfItems)(UInt32 *numItems); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback); STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType); UString GetMethodString(); public: CHandler() { } private: CHeader m_StreamInfo; UInt64 m_StreamStartPosition; UInt64 m_PackSize; CMyComPtr<IInStream> m_Stream; DECL_EXTERNAL_CODECS_VARS DECL_ISetCompressCodecsInfo }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaIn.cpp ================================================ // Archive/LzmaIn.cpp #include "StdAfx.h" #include "LzmaIn.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace NLzma { static bool CheckDictSize(const Byte *p) { UInt32 dicSize = GetUi32(p); int i; for (i = 1; i <= 30; i++) if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) return true; return false; } HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) { Byte sig[5 + 9]; RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); const Byte kMaxProp0Val = 5 * 5 * 9 - 1; if (sig[0] > kMaxProp0Val) return S_FALSE; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i]; block.IsThereFilter = false; block.FilterMethod = 0; if (!CheckDictSize(sig + 1)) { if (sig[0] > 1 || sig[1] > kMaxProp0Val) return S_FALSE; block.IsThereFilter = true; block.FilterMethod = sig[0]; for (int i = 0; i < 5; i++) block.LzmaProps[i] = sig[i + 1]; if (!CheckDictSize(block.LzmaProps + 1)) return S_FALSE; RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); } UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); block.UnpackSize = GetUi64(sig + unpOffset); if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) return S_FALSE; return S_OK; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaIn.h ================================================ // Archive/LzmaIn.h #ifndef __ARCHIVE_LZMA_IN_H #define __ARCHIVE_LZMA_IN_H #include "LzmaItem.h" #include "../../IStream.h" namespace NArchive { namespace NLzma { HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/LzmaItem.h ================================================ // Archive/LzmaItem.h #ifndef __ARCHIVE_LZMA_ITEM_H #define __ARCHIVE_LZMA_ITEM_H #include "Common/Types.h" #include "../../../../C/CpuArch.h" namespace NArchive { namespace NLzma { struct CHeader { UInt64 UnpackSize; bool IsThereFilter; Byte FilterMethod; Byte LzmaProps[5]; UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Lzma/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Split/SplitHandler.cpp ================================================ // SplitHandler.cpp #include "StdAfx.h" #include "Common/ComTry.h" #include "Common/Defs.h" #include "Common/NewHandler.h" #include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "Windows/Time.h" #include "../../Common/ProgressUtils.h" #include "../../Compress/CopyCoder.h" #include "../Common/ItemNameUtils.h" #include "../Common/MultiStream.h" #include "SplitHandler.h" using namespace NWindows; using namespace NTime; namespace NArchive { namespace NSplit { STATPROPSTG kProps[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidSize, VT_UI8}, { NULL, kpidPackSize, VT_UI8}, }; IMP_IInArchive_Props IMP_IInArchive_ArcProps_NO class CSeqName { public: UString _unchangedPart; UString _changedPart; bool _splitStyle; UString GetNextName() { UString newName; if (_splitStyle) { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == 'z') { c = 'a'; newName = c + newName; continue; } else if (c == 'Z') { c = 'A'; newName = c + newName; continue; } c++; if ((c == 'z' || c == 'Z') && i == 0) { _unchangedPart += c; wchar_t newChar = (c == 'z') ? L'a' : L'A'; newName.Empty(); numLetters++; for (int k = 0; k < numLetters; k++) newName += newChar; break; } newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } else { int i; int numLetters = _changedPart.Length(); for (i = numLetters - 1; i >= 0; i--) { wchar_t c = _changedPart[i]; if (c == L'9') { c = L'0'; newName = c + newName; if (i == 0) newName = UString(L'1') + newName; continue; } c++; newName = c + newName; i--; for (; i >= 0; i--) newName = _changedPart[i] + newName; break; } } _changedPart = newName; return _unchangedPart + _changedPart; } }; STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *openArchiveCallback) { COM_TRY_BEGIN Close(); if (openArchiveCallback == 0) return S_FALSE; // try { CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback) != S_OK) return S_FALSE; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); if (prop.vt != VT_BSTR) return S_FALSE; _name = prop.bstrVal; } int dotPos = _name.ReverseFind('.'); UString prefix, ext; if (dotPos >= 0) { prefix = _name.Left(dotPos + 1); ext = _name.Mid(dotPos + 1); } else ext = _name; UString extBig = ext; extBig.MakeUpper(); CSeqName seqName; int numLetters = 2; bool splitStyle = false; if (extBig.Right(2) == L"AA") { splitStyle = true; while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != 'A') break; numLetters++; } } else if (ext.Right(2) == L"01") { while (numLetters < extBig.Length()) { if (extBig[extBig.Length() - numLetters - 1] != '0') break; numLetters++; } if (numLetters != ext.Length()) return S_FALSE; } else return S_FALSE; _streams.Add(stream); seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); seqName._changedPart = ext.Right(numLetters); seqName._splitStyle = splitStyle; if (prefix.Length() < 1) _subName = L"file"; else _subName = prefix.Left(prefix.Length() - 1); _totalSize = 0; UInt64 size; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } for (;;) { UString fullName = seqName.GetNextName(); CMyComPtr<IInStream> nextStream; HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); if (result == S_FALSE) break; if (result != S_OK) return result; if (!stream) break; { NCOM::CPropVariant prop; RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; size = prop.uhVal.QuadPart; } _totalSize += size; _sizes.Add(size); _streams.Add(nextStream); if (openArchiveCallback != NULL) { UInt64 numFiles = _streams.Size(); RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); } } } /* catch(...) { return S_FALSE; } */ return S_OK; COM_TRY_END } STDMETHODIMP CHandler::Close() { _sizes.Clear(); _streams.Clear(); return S_OK; } STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) { *numItems = _streams.IsEmpty() ? 0 : 1; return S_OK; } STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; switch(propID) { case kpidPath: prop = _subName; break; case kpidSize: case kpidPackSize: prop = _totalSize; break; } prop.Detach(value); return S_OK; } STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) { COM_TRY_BEGIN if (numItems != UInt32(-1)) { if (numItems != 1) return E_INVALIDARG; if (indices[0] != 0) return E_INVALIDARG; } bool testMode = (_aTestMode != 0); CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; extractCallback->SetTotal(_totalSize); /* CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) return E_FAIL; */ UInt64 currentTotalSize = 0; UInt64 currentItemSize; RINOK(extractCallback->SetCompleted(¤tTotalSize)); CMyComPtr<ISequentialOutStream> realOutStream; Int32 askMode; askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; Int32 index = 0; RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); RINOK(extractCallback->PrepareOperation(askMode)); if (testMode) { RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); return S_OK; } if (!testMode && (!realOutStream)) return S_OK; NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) { lps->InSize = lps->OutSize = currentTotalSize; RINOK(lps->SetCur()); IInStream *inStream = _streams[i]; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); currentItemSize = copyCoderSpec->TotalSize; } realOutStream.Release(); return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); COM_TRY_END } STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) { if (index != 0) return E_INVALIDARG; *stream = 0; CMultiStream *streamSpec = new CMultiStream; CMyComPtr<ISequentialInStream> streamTemp = streamSpec; for (int i = 0; i < _streams.Size(); i++) { CMultiStream::CSubStreamInfo subStreamInfo; subStreamInfo.Stream = _streams[i]; subStreamInfo.Pos = 0; subStreamInfo.Size = _sizes[i]; streamSpec->Streams.Add(subStreamInfo); } streamSpec->Init(); *stream = streamTemp.Detach(); return S_OK; } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Split/SplitHandler.h ================================================ // Split/Handler.h #ifndef __SPLIT_HANDLER_H #define __SPLIT_HANDLER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../IArchive.h" namespace NArchive { namespace NSplit { class CHandler: public IInArchive, public IInArchiveGetStream, // public IOutArchive, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) INTERFACE_IInArchive(;) STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); private: UString _subName; UString _name; CObjectVector<CMyComPtr<IInStream> > _streams; CRecordVector<UInt64> _sizes; UInt64 _totalSize; }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Split/SplitHandlerOut.cpp ================================================ // Split/OutHandler.cpp #include "StdAfx.h" #include "SplitHandler.h" #include "../../../Windows/PropVariant.h" #include "../../../Common/ComTry.h" #include "../../../Common/StringToInt.h" using namespace NWindows; namespace NArchive { namespace NSplit { /* STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) { *type = NFileTimeType::kWindows; return S_OK; } STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) { COM_TRY_BEGIN if (numItems != 1) return E_INVALIDARG; UInt64 volumeSize = 0; CMyComPtr<IArchiveUpdateCallback2> callback2; updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&callback2); RINOK(callback2->GetVolumeSize(0, &volumeSize)); Int32 newData; Int32 newProperties; UInt32 indexInArchive; if (!updateCallback) return E_FAIL; UInt32 fileIndex = 0; RINOK(updateCallback->GetUpdateItemInfo(fileIndex, &newData, &newProperties, &indexInArchive)); if (newProperties != 0) { { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &prop)); if (prop.vt == VT_EMPTY) { } else if (prop.vt != VT_BOOL) return E_INVALIDARG; else { if (prop.boolVal != VARIANT_FALSE) return E_INVALIDARG; } } } UInt64 newSize; bool thereIsCopyData = false; if (newData != 0) { NCOM::CPropVariant prop; RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; newSize = prop.uhVal.QuadPart; } else thereIsCopyData = true; UInt64 pos = 0; while(pos < newSize) { } return S_OK; COM_TRY_END } */ }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Split/SplitRegister.cpp ================================================ // SplitRegister.cpp #include "StdAfx.h" #include "../../Common/RegisterArc.h" #include "SplitHandler.h" static IInArchive *CreateArc() { return new NArchive::NSplit::CHandler; } /* #ifndef EXTRACT_ONLY static IOutArchive *CreateArcOut() { return new NArchive::NSplit::CHandler; } #else #define CreateArcOut 0 #endif */ static CArcInfo g_ArcInfo = { L"Split", L"001", 0, 0xEA, { 0 }, 0, false, CreateArc, 0 }; REGISTER_ARC(Split) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/Split/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Archive/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/Alone.dsp ================================================ # Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Alone - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Alone.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Alone - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept !ENDIF # Begin Target # Name "Alone - Win32 Release" # Name "Alone - Win32 Debug" # Name "Alone - Win32 ReleaseU" # Name "Alone - Win32 DebugU" # Begin Group "Console" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Console\ArError.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\CompressionMode.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ConsoleClose.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\ExtractCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\List.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\Main.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\MainAr.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\OpenCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\PercentPrinter.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UpdateCallbackConsole.h # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Console\UserInputUtils.h # End Source File # End Group # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\resource.rc # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\AutoPtr.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Buffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ComTry.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\DynamicBuffer.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\ListFileUtils.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyException.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyGuidDef.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyInitGuid.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyUnknown.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Random.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdInStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StdOutStream.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\UTFConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Device.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Error.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Handle.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\MemoryLock.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Time.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\CreateCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\CreateCoder.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CrossThreadProgress.h # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilePathAutoRename.h # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FilterCoder.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InOutTempBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LimitedStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\LockedStream.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodId.h # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.cpp # End Source File # Begin Source File SOURCE=..\..\Common\MethodProps.h # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OffsetStream.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressMt.h # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\ProgressUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterArc.h # End Source File # Begin Source File SOURCE=..\..\Common\RegisterCodec.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamBinder.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamObjects.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.cpp # End Source File # Begin Source File SOURCE=..\..\Common\VirtThread.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA_Alone" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h # End Source File # End Group # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Coder.h # End Source File # Begin Source File SOURCE=..\..\Compress\Bcj2Register.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BcjCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BcjRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\BranchMisc.h # End Source File # Begin Source File SOURCE=..\..\Compress\BranchRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwap.h # End Source File # Begin Source File SOURCE=..\..\Compress\ByteSwapRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\CopyCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\CopyRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaEncoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\LzmaRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoder.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\..\Compress\RangeCoderOpt.h # End Source File # End Group # Begin Group "Archive" # PROP Default_Filter "" # Begin Group "7z" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zCompressionMode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zEncode.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zExtract.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderInStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zFolderOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zHeader.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zItem.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zProperties.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zSpecStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\7z\7zUpdate.h # End Source File # End Group # Begin Group "Archive Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\CoderMixer2MT.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\DummyOutStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\HandlerOut.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\InStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ItemNameUtils.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\MultiStream.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\OutStreamWithCRC.h # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Common\ParseProperties.h # End Source File # End Group # Begin Group "split" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Split\SplitHandler.h # End Source File # End Group # Begin Group "LZM" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaArcRegister.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaFiltersDecode.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaHandler.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.cpp # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaIn.h # End Source File # Begin Source File SOURCE=..\..\Archive\Lzma\LzmaItem.h # End Source File # End Group # End Group # Begin Group "UI Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveCommandLine.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveExtractCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ArchiveOpenCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\DefaultName.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\EnumDirItems.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Extract.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\ExtractingFilePath.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\LoadCodecs.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\OpenArchive.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Property.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\PropIDUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SetProperties.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\SortUtils.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\TempFiles.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\Update.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateAction.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateCallback.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdatePair.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\UpdateProduce.h # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.cpp # End Source File # Begin Source File SOURCE=..\..\UI\Common\WorkDir.h # End Source File # End Group # Begin Group "7-zip" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=..\..\IMyUnknown.h # End Source File # Begin Source File SOURCE=..\..\IPassword.h # End Source File # Begin Source File SOURCE=..\..\IProgress.h # End Source File # Begin Source File SOURCE=..\..\IStream.h # End Source File # Begin Source File SOURCE=..\..\PropID.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\BraIA64.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\IStream.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c !IF "$(CFG)" == "Alone - Win32 Release" # ADD CPP /O2 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 Debug" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "Alone - Win32 DebugU" # SUBTRACT CPP /YX /Yc /Yu !ENDIF # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/Alone.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Alone"=.\Alone.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/makefile ================================================ PROG = 7za.exe LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -D_NO_CRYPTO \ -DWIN_LONG_PATH \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO \ -DBREAK_HANDLER \ -DBENCH_MT \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Synchronization.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OffsetStream.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\DummyOutStream.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\MultiStream.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ LZM_OBJS = \ $O\LzmaArcRegister.obj \ $O\LzmaFiltersDecode.obj \ $O\LzmaHandler.obj \ $O\LzmaIn.obj \ SPLIT_OBJS = \ $O\SplitHandler.obj \ $O\SplitHandlerOut.obj \ $O\SplitRegister.obj \ COMPRESS_OBJS = \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\Alloc.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(LZM_OBJS) \ $(SPLIT_OBJS) \ $(COMPRESS_OBJS) \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(LZM_OBJS): ../../Archive/Lzma/$(*B).cpp $(COMPL) $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Alone7z/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za") ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zExtractR/makefile ================================================ PROG = 7zxr.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DEXTRACT_ONLY \ -DCOMPRESS_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zProperties.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzmaDec.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zExtractR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zR/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zR/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zR/makefile ================================================ PROG = 7zra.dll DEF_FILE = ../../Archive/Archive2.def LIBS = $(LIBS) user32.lib oleaut32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DCOMPRESS_MF_MT \ -D_NO_CRYPTO COMMON_OBJS = \ $O\CRC.obj \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\PropVariant.obj \ $O\Synchronization.obj \ $O\System.obj \ 7ZIP_COMMON_OBJS = \ $O\CreateCoder.obj \ $O\InBuffer.obj \ $O\InOutTempBuffer.obj \ $O\FilterCoder.obj \ $O\LimitedStreams.obj \ $O\LockedStream.obj \ $O\MethodId.obj \ $O\MethodProps.obj \ $O\OutBuffer.obj \ $O\ProgressUtils.obj \ $O\StreamBinder.obj \ $O\StreamObjects.obj \ $O\StreamUtils.obj \ $O\VirtThread.obj \ AR_OBJS = \ $O\ArchiveExports.obj \ $O\DllExports2.obj \ AR_COMMON_OBJS = \ $O\CoderMixer2.obj \ $O\CoderMixer2MT.obj \ $O\CrossThreadProgress.obj \ $O\HandlerOut.obj \ $O\InStreamWithCRC.obj \ $O\ItemNameUtils.obj \ $O\OutStreamWithCRC.obj \ $O\ParseProperties.obj \ 7Z_OBJS = \ $O\7zCompressionMode.obj \ $O\7zDecode.obj \ $O\7zEncode.obj \ $O\7zExtract.obj \ $O\7zFolderInStream.obj \ $O\7zFolderOutStream.obj \ $O\7zHandler.obj \ $O\7zHandlerOut.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zOut.obj \ $O\7zProperties.obj \ $O\7zSpecStream.obj \ $O\7zUpdate.obj \ $O\7zRegister.obj \ COMPRESS_OBJS = \ $O\CodecExports.obj \ $O\Bcj2Coder.obj \ $O\Bcj2Register.obj \ $O\BcjCoder.obj \ $O\BcjRegister.obj \ $O\BranchCoder.obj \ $O\BranchMisc.obj \ $O\BranchRegister.obj \ $O\ByteSwap.obj \ $O\ByteSwapRegister.obj \ $O\CopyCoder.obj \ $O\CopyRegister.obj \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ $O\LzmaRegister.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(AR_OBJS) \ $(AR_COMMON_OBJS) \ $(7Z_OBJS) \ $(COMPRESS_OBJS) \ $(C_OBJS) \ $O\resource.res !include "../../../Build.mak" $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(AR_OBJS): ../../Archive/$(*B).cpp $(COMPL) $(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp $(COMPL) $(7Z_OBJS): ../../Archive/7z/$(*B).cpp $(COMPL) $(COMPRESS_OBJS): ../../Compress/$(*B).cpp $(COMPL_O2) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Bundles/Format7zR/resource.rc ================================================ #include "../../MyVersionInfo.rc" MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr") 101 ICON "../../Archive/Icons/7z.ico" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/CreateCoder.cpp ================================================ // CreateCoder.cpp #include "StdAfx.h" #include "CreateCoder.h" #include "../../Windows/PropVariant.h" #include "../../Windows/Defs.h" #include "FilterCoder.h" #include "RegisterCodec.h" static const unsigned int kNumCodecsMax = 64; unsigned int g_NumCodecs = 0; const CCodecInfo *g_Codecs[kNumCodecsMax]; void RegisterCodec(const CCodecInfo *codecInfo) { if (g_NumCodecs < kNumCodecsMax) g_Codecs[g_NumCodecs++] = codecInfo; } #ifdef EXTERNAL_CODECS static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = 1; else if (prop.vt == VT_UI4) res = prop.ulVal; else return E_INVALIDARG; return S_OK; } static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) { NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(index, propID, &prop)); if (prop.vt == VT_EMPTY) res = true; else if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else return E_INVALIDARG; return S_OK; } HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) { UInt32 num; RINOK(codecsInfo->GetNumberOfMethods(&num)); for (UInt32 i = 0; i < num; i++) { CCodecInfoEx info; NWindows::NCOM::CPropVariant prop; RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); // if (prop.vt != VT_BSTR) // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); if (prop.vt != VT_UI8) { continue; // old Interface // return E_INVALIDARG; } info.Id = prop.uhVal.QuadPart; prop.Clear(); RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) info.Name = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_INVALIDARG;; RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); externalCodecs.Add(info); } return S_OK; } #endif bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (name.CompareNoCase(codec.Name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = 1; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Name.CompareNoCase(name) == 0) { methodId = codec.Id; numInStreams = codec.NumInStreams; numOutStreams = codec.NumOutStreams; return true; } } #endif return false; } bool FindMethod( #ifdef EXTERNAL_CODECS ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, #endif CMethodId methodId, UString &name) { UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #ifdef EXTERNAL_CODECS if (externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (methodId == codec.Id) { name = codec.Name; return true; } } #endif return false; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder) { bool created = false; UInt32 i; for (i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId) { if (encode) { if (codec.CreateEncoder) { void *p = codec.CreateEncoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } else if (codec.CreateDecoder) { void *p = codec.CreateDecoder(); if (codec.IsFilter) filter = (ICompressFilter *)p; else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; else coder2 = (ICompressCoder2 *)p; created = (p != 0); break; } } } #ifdef EXTERNAL_CODECS if (!created && externalCodecs) for (i = 0; i < (UInt32)externalCodecs->Size(); i++) { const CCodecInfoEx &codec = (*externalCodecs)[i]; if (codec.Id == methodId) { if (encode) { if (codec.EncoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } else if (codec.DecoderIsAssigned) { if (codec.IsSimpleCodec()) { HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) return result; if (!coder) { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); } } else { RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); } break; } } } #endif if (onlyCoder && filter) { CFilterCoder *coderSpec = new CFilterCoder; coder = coderSpec; coderSpec->Filter = filter; } return S_OK; } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode) { CMyComPtr<ICompressFilter> filter; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, true); } HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode) { CMyComPtr<ICompressFilter> filter; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, coder, coder2, encode); } HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode) { CMyComPtr<ICompressCoder> coder; CMyComPtr<ICompressCoder2> coder2; return CreateCoder( EXTERNAL_CODECS_LOC_VARS methodId, filter, coder, coder2, encode, false); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/CreateCoder.h ================================================ // CreateCoder.h #ifndef __CREATECODER_H #define __CREATECODER_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../ICoder.h" #include "MethodId.h" #ifdef EXTERNAL_CODECS struct CCodecInfoEx { UString Name; CMethodId Id; UInt32 NumInStreams; UInt32 NumOutStreams; bool EncoderIsAssigned; bool DecoderIsAssigned; bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; } CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {} }; HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs); #define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo, #define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo) #define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo); #define IMPL_ISetCompressCodecsInfo2(x) \ STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \ COM_TRY_BEGIN _codecsInfo = compressCodecsInfo; return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END } #define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler) #define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs #define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs; #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2, #define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs #define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs #define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2, #define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2, #else #define PUBLIC_ISetCompressCodecsInfo #define QUERY_ENTRY_ISetCompressCodecsInfo #define DECL_ISetCompressCodecsInfo #define IMPL_ISetCompressCodecsInfo #define EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_VARS #define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS2 #define EXTERNAL_CODECS_LOC_VARS2 #define DECL_EXTERNAL_CODECS_LOC_VARS #define EXTERNAL_CODECS_LOC_VARS #endif bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams); bool FindMethod( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, UString &name); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode, bool onlyCoder); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, CMyComPtr<ICompressCoder2> &coder2, bool encode); HRESULT CreateCoder( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressCoder> &coder, bool encode); HRESULT CreateFilter( DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId, CMyComPtr<ICompressFilter> &filter, bool encode); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FilePathAutoRename.cpp ================================================ // FilePathAutoRename.cpp #include "StdAfx.h" #include "FilePathAutoRename.h" #include "Common/Defs.h" #include "Common/IntToString.h" #include "Windows/FileName.h" #include "Windows/FileFind.h" using namespace NWindows; static bool MakeAutoName(const UString &name, const UString &extension, int value, UString &path) { wchar_t number[32]; ConvertUInt64ToString(value, number); path = name; path += number; path += extension; return NFile::NFind::DoesFileExist(path); } bool AutoRenamePath(UString &fullProcessedPath) { UString path; int dotPos = fullProcessedPath.ReverseFind(L'.'); int slashPos = fullProcessedPath.ReverseFind(L'/'); #ifdef _WIN32 int slash1Pos = fullProcessedPath.ReverseFind(L'\\'); slashPos = MyMax(slashPos, slash1Pos); #endif UString name, extension; if (dotPos > slashPos && dotPos > 0) { name = fullProcessedPath.Left(dotPos); extension = fullProcessedPath.Mid(dotPos); } else name = fullProcessedPath; name += L'_'; int indexLeft = 1, indexRight = (1 << 30); while (indexLeft != indexRight) { int indexMid = (indexLeft + indexRight) / 2; if (MakeAutoName(name, extension, indexMid, path)) indexLeft = indexMid + 1; else indexRight = indexMid; } if (MakeAutoName(name, extension, indexRight, fullProcessedPath)) return false; return true; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FilePathAutoRename.h ================================================ // Util/FilePathAutoRename.h #ifndef __FILEPATHAUTORENAME_H #define __FILEPATHAUTORENAME_H #include "Common/MyString.h" bool AutoRenamePath(UString &fullProcessedPath); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { #ifdef _WIN32 if (result) return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite) { return File.OpenShared(fileName, shareForWrite); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream HRESULT COutFileStream::Close() { return ConvertBoolToHRESULT(File.Close()); } STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; ProcessedSize += res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef USE_WIN_FILE UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef USE_WIN_FILE UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #define USE_WIN_FILE #endif #ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef USE_WIN_FILE #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif bool OpenShared(LPCTSTR fileName, bool shareForWrite); #ifdef USE_WIN_FILE #ifndef _UNICODE bool OpenShared(LPCWSTR fileName, bool shareForWrite); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { public: #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif public: virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCTSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #ifdef USE_WIN_FILE #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways) { ProcessedSize = 0; return File.Create(fileName, createAlways); } bool Open(LPCWSTR fileName, DWORD creationDisposition) { ProcessedSize = 0; return File.Open(fileName, creationDisposition); } #endif #endif HRESULT Close(); UInt64 ProcessedSize; #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FilterCoder.cpp ================================================ // FilterCoder.cpp #include "StdAfx.h" #include "FilterCoder.h" extern "C" { #include "../../../C/Alloc.h" } #include "../../Common/Defs.h" #include "StreamUtils.h" static const UInt32 kBufferSize = 1 << 17; CFilterCoder::CFilterCoder() { _buffer = (Byte *)::MidAlloc(kBufferSize); } CFilterCoder::~CFilterCoder() { ::MidFree(_buffer); } HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size) { if (_outSizeIsDefined) { UInt64 remSize = _outSize - _nowPos64; if (size > remSize) size = (UInt32)remSize; } RINOK(WriteStream(outStream, _buffer, size)); _nowPos64 += size; return S_OK; } STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { RINOK(Init()); UInt32 bufferPos = 0; _outSizeIsDefined = (outSize != 0); if (_outSizeIsDefined) _outSize = *outSize; while(NeedMore()) { size_t processedSize = kBufferSize - bufferPos; // Change it: It can be optimized using ReadPart RINOK(ReadStream(inStream, _buffer + bufferPos, &processedSize)); UInt32 endPos = bufferPos + (UInt32)processedSize; bufferPos = Filter->Filter(_buffer, endPos); if (bufferPos > endPos) { for (; endPos< bufferPos; endPos++) _buffer[endPos] = 0; bufferPos = Filter->Filter(_buffer, endPos); } if (bufferPos == 0) { if (endPos > 0) return WriteWithLimit(outStream, endPos); return S_OK; } RINOK(WriteWithLimit(outStream, bufferPos)); if (progress != NULL) { RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } return S_OK; } // #ifdef _ST_MODE STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream) { _bufferPos = 0; _outStream = outStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseOutStream() { _outStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { UInt32 sizeMax = kBufferSize - _bufferPos; UInt32 sizeTemp = size; if (sizeTemp > sizeMax) sizeTemp = sizeMax; memmove(_buffer + _bufferPos, data, sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; data = (const Byte *)data + sizeTemp; UInt32 endPos = _bufferPos + sizeTemp; _bufferPos = Filter->Filter(_buffer, endPos); if (_bufferPos == 0) { _bufferPos = endPos; break; } if (_bufferPos > endPos) { if (size != 0) return E_FAIL; break; } RINOK(WriteWithLimit(_outStream, _bufferPos)); UInt32 i = 0; while(_bufferPos < endPos) _buffer[i++] = _buffer[_bufferPos++]; _bufferPos = i; } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } STDMETHODIMP CFilterCoder::Flush() { if (_bufferPos != 0) { UInt32 endPos = Filter->Filter(_buffer, _bufferPos); if (endPos > _bufferPos) { for (; _bufferPos < endPos; _bufferPos++) _buffer[_bufferPos] = 0; if (Filter->Filter(_buffer, endPos) != endPos) return E_FAIL; } RINOK(WriteStream(_outStream, _buffer, _bufferPos)); _bufferPos = 0; } CMyComPtr<IOutStreamFlush> flush; _outStream.QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; } STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream) { _convertedPosBegin = _convertedPosEnd = _bufferPos = 0; _inStream = inStream; return Init(); } STDMETHODIMP CFilterCoder::ReleaseInStream() { _inStream.Release(); return S_OK; }; STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 processedSizeTotal = 0; while(size > 0) { if (_convertedPosBegin != _convertedPosEnd) { UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin); memmove(data, _buffer + _convertedPosBegin, sizeTemp); _convertedPosBegin += sizeTemp; data = (void *)((Byte *)data + sizeTemp); size -= sizeTemp; processedSizeTotal += sizeTemp; break; } int i; for (i = 0; _convertedPosEnd + i < _bufferPos; i++) _buffer[i] = _buffer[i + _convertedPosEnd]; _bufferPos = i; _convertedPosBegin = _convertedPosEnd = 0; size_t processedSizeTemp = kBufferSize - _bufferPos; RINOK(ReadStream(_inStream, _buffer + _bufferPos, &processedSizeTemp)); _bufferPos = _bufferPos + (UInt32)processedSizeTemp; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); if (_convertedPosEnd == 0) { if (_bufferPos == 0) break; else { _convertedPosEnd = _bufferPos; // check it continue; } } if (_convertedPosEnd > _bufferPos) { for (; _bufferPos < _convertedPosEnd; _bufferPos++) _buffer[_bufferPos] = 0; _convertedPosEnd = Filter->Filter(_buffer, _bufferPos); } } if (processedSize != NULL) *processedSize = processedSizeTotal; return S_OK; } // #endif // _ST_MODE #ifndef _NO_CRYPTO STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size) { return _setPassword->CryptoSetPassword(data, size); } #endif #ifndef EXTRACT_ONLY STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties); } STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream) { return _writeCoderProperties->WriteCoderProperties(outStream); } /* STDMETHODIMP CFilterCoder::ResetSalt() { return _CryptoResetSalt->ResetSalt(); } */ STDMETHODIMP CFilterCoder::ResetInitVector() { return _CryptoResetInitVector->ResetInitVector(); } #endif STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size) { return _setDecoderProperties->SetDecoderProperties2(data, size); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/FilterCoder.h ================================================ // FilterCoder.h #ifndef __FILTERCODER_H #define __FILTERCODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IPassword.h" #define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \ { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \ *outObject = (void *)(i *)this; AddRef(); return S_OK; } class CFilterCoder: public ICompressCoder, // #ifdef _ST_MODE public ICompressSetInStream, public ISequentialInStream, public ICompressSetOutStream, public ISequentialOutStream, public IOutStreamFlush, // #endif #ifndef _NO_CRYPTO public ICryptoSetPassword, #endif #ifndef EXTRACT_ONLY public ICompressSetCoderProperties, public ICompressWriteCoderProperties, // public ICryptoResetSalt, public ICryptoResetInitVector, #endif public ICompressSetDecoderProperties2, public CMyUnknownImp { protected: Byte *_buffer; // #ifdef _ST_MODE CMyComPtr<ISequentialInStream> _inStream; CMyComPtr<ISequentialOutStream> _outStream; UInt32 _bufferPos; UInt32 _convertedPosBegin; UInt32 _convertedPosEnd; // #endif bool _outSizeIsDefined; UInt64 _outSize; UInt64 _nowPos64; HRESULT Init() { _nowPos64 = 0; _outSizeIsDefined = false; return Filter->Init(); } CMyComPtr<ICryptoSetPassword> _setPassword; #ifndef EXTRACT_ONLY CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties; CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties; // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt; CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector; #endif CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties; public: CMyComPtr<ICompressFilter> Filter; CFilterCoder(); ~CFilterCoder(); HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size); bool NeedMore() const { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); } public: MY_QUERYINTERFACE_BEGIN MY_QUERYINTERFACE_ENTRY(ICompressCoder) // #ifdef _ST_MODE MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream) MY_QUERYINTERFACE_ENTRY(ISequentialOutStream) MY_QUERYINTERFACE_ENTRY(IOutStreamFlush) // #endif #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) #endif #ifndef EXTRACT_ONLY MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties) MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties) // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt) MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector) #endif MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // #ifdef _ST_MODE STDMETHOD(ReleaseInStream)(); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Flush)(); // #endif #ifndef _NO_CRYPTO STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size); #endif #ifndef EXTRACT_ONLY STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); // STDMETHOD(ResetSalt)(); STDMETHOD(ResetInitVector)(); #endif STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); }; // #ifdef _ST_MODE class CInStreamReleaser { public: CFilterCoder *FilterCoder; CInStreamReleaser(): FilterCoder(0) {} ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); } }; class COutStreamReleaser { public: CFilterCoder *FilterCoder; COutStreamReleaser(): FilterCoder(0) {} ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); } }; // #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" extern "C" { #include "../../../C/Alloc.h" } CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct CInBufferException: public CSystemException { CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if (_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } UInt32 ReadBytes(Byte *buf, UInt32 size) { if ((UInt32)(_bufferLimit - _buffer) >= size) { for (UInt32 i = 0; i < size; i++) buf[i] = _buffer[i]; _buffer += size; return size; } for (UInt32 i = 0; i < size; i++) { if (_buffer >= _bufferLimit) if (!ReadBlock()) return i; buf[i] = *_buffer++; } return size; } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/InOutTempBuffer.cpp ================================================ // InOutTempBuffer.cpp #include "StdAfx.h" #include "InOutTempBuffer.h" #include "../../Common/Defs.h" // #include "Windows/Defs.h" #include "StreamUtils.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static UInt32 kTmpBufferMemorySize = (1 << 20); static LPCTSTR kTempFilePrefixString = TEXT("iot"); CInOutTempBuffer::CInOutTempBuffer(): _buffer(NULL) { } void CInOutTempBuffer::Create() { _buffer = new Byte[kTmpBufferMemorySize]; } CInOutTempBuffer::~CInOutTempBuffer() { delete []_buffer; } void CInOutTempBuffer::InitWriting() { _bufferPosition = 0; _tmpFileCreated = false; _fileSize = 0; } bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) { if (size == 0) return true; if(!_tmpFileCreated) { CSysString tempDirPath; if(!MyGetTempPath(tempDirPath)) return false; if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0) return false; // _outFile.SetOpenCreationDispositionCreateAlways(); if(!_outFile.Create(_tmpFileName, true)) return false; _tmpFileCreated = true; } UInt32 processedSize; if(!_outFile.Write(data, size, processedSize)) return false; _fileSize += processedSize; return (processedSize == size); } bool CInOutTempBuffer::FlushWrite() { return _outFile.Close(); } bool CInOutTempBuffer::Write(const void *data, UInt32 size) { if(_bufferPosition < kTmpBufferMemorySize) { UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size); memmove(_buffer + _bufferPosition, (const Byte *)data, curSize); _bufferPosition += curSize; size -= curSize; data = ((const Byte *)data) + curSize; _fileSize += curSize; } return WriteToFile(data, size); } bool CInOutTempBuffer::InitReading() { _currentPositionInBuffer = 0; if(_tmpFileCreated) return _inFile.Open(_tmpFileName); return true; } HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { if (_currentPositionInBuffer < _bufferPosition) { UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer; RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite)); _currentPositionInBuffer += sizeToWrite; } if (!_tmpFileCreated) return true; for (;;) { UInt32 localProcessedSize; if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize)) return E_FAIL; if (localProcessedSize == 0) return S_OK; RINOK(WriteStream(stream, _buffer, localProcessedSize)); } } STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (!_buffer->Write(data, size)) { if (processedSize != NULL) *processedSize = 0; return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/InOutTempBuffer.h ================================================ // Util/InOutTempBuffer.h #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H #include "../../Windows/FileIO.h" #include "../../Windows/FileDir.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CInOutTempBuffer { NWindows::NFile::NDirectory::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; NWindows::NFile::NIO::CInFile _inFile; Byte *_buffer; UInt32 _bufferPosition; UInt32 _currentPositionInBuffer; CSysString _tmpFileName; bool _tmpFileCreated; UInt64 _fileSize; bool WriteToFile(const void *data, UInt32 size); public: CInOutTempBuffer(); ~CInOutTempBuffer(); void Create(); void InitWriting(); bool Write(const void *data, UInt32 size); UInt64 GetDataSize() const { return _fileSize; } bool FlushWrite(); bool InitReading(); HRESULT WriteToStream(ISequentialOutStream *stream); }; class CSequentialOutTempBufferImp: public ISequentialOutStream, public CMyUnknownImp { CInOutTempBuffer *_buffer; public: // CSequentialOutStreamImp(): _size(0) {} // UInt32 _size; void Init(CInOutTempBuffer *buffer) { _buffer = buffer; } // UInt32 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/LimitedStreams.cpp ================================================ // LimitedStreams.cpp #include "StdAfx.h" #include "LimitedStreams.h" #include "../../Common/Defs.h" STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size); HRESULT result = S_OK; if (sizeToRead > 0) { result = _stream->Read(data, sizeToRead, &realProcessedSize); _pos += realProcessedSize; if (realProcessedSize == 0) _wasFinished = true; } if(processedSize != NULL) *processedSize = realProcessedSize; return result; } STDMETHODIMP CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { HRESULT result = S_OK; if (processedSize != NULL) *processedSize = 0; if (size > _size) { size = (UInt32)_size; if (size == 0) { _overflow = true; return E_FAIL; } } if (_stream) result = _stream->Write(data, size, &size); _size -= size; if (processedSize != NULL) *processedSize = size; return result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/LimitedStreams.h ================================================ // LimitedStreams.h #ifndef __LIMITEDSTREAMS_H #define __LIMITEDSTREAMS_H #include "../../Common/MyCom.h" #include "../IStream.h" class CLimitedSequentialInStream: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; UInt64 _pos; bool _wasFinished; public: void SetStream(ISequentialInStream *stream) { _stream = stream; } void Init(UInt64 streamSize) { _size = streamSize; _pos = 0; _wasFinished = false; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); UInt64 GetSize() const { return _pos; } bool WasFinished() const { return _wasFinished; } }; class CLimitedSequentialOutStream: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; bool _overflow; public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); void SetStream(ISequentialOutStream *stream) { _stream = stream; } void ReleaseStream() { _stream.Release(); } void Init(UInt64 size) { _size = size; _overflow = false; } bool IsFinishedOK() const { return (_size == 0 && !_overflow); } UInt64 GetRem() const { return _size; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/LockedStream.cpp ================================================ // LockedStream.cpp #include "StdAfx.h" #include "LockedStream.h" HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize) { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL)); return _stream->Read(data, size, processedSize); } STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize = 0; HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize); _pos += realProcessedSize; if (processedSize != NULL) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/LockedStream.h ================================================ // LockedStream.h #ifndef __LOCKEDSTREAM_H #define __LOCKEDSTREAM_H #include "../../Windows/Synchronization.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CLockedInStream { CMyComPtr<IInStream> _stream; NWindows::NSynchronization::CCriticalSection _criticalSection; public: void Init(IInStream *stream) { _stream = stream; } HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize); }; class CLockedSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { CLockedInStream *_lockedInStream; UInt64 _pos; public: void Init(CLockedInStream *lockedInStream, UInt64 startPos) { _lockedInStream = lockedInStream; _pos = startPos; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/MethodId.cpp ================================================ // MethodId.cpp #include "StdAfx.h" #include "MethodId.h" #include "../../Common/MyString.h" static inline wchar_t GetHex(Byte value) { return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } UString ConvertMethodIdToString(UInt64 id) { wchar_t s[32]; int len = 32; s[--len] = 0; do { s[--len] = GetHex((Byte)id & 0xF); id >>= 4; s[--len] = GetHex((Byte)id & 0xF); id >>= 4; } while (id != 0); return s + len; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/MethodId.h ================================================ // MethodId.h #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "../../Common/Types.h" typedef UInt64 CMethodId; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/MethodProps.cpp ================================================ // MethodProps.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "../ICoder.h" #include "MethodProps.h" static UInt64 k_LZMA = 0x030101; // static UInt64 k_LZMA2 = 0x030102; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder) { bool tryReduce = false; UInt32 reducedDictionarySize = 1 << 10; if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */)) { for (;;) { const UInt32 step = (reducedDictionarySize >> 1); if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } reducedDictionarySize += step; if (reducedDictionarySize >= *inSizeForReduce) { tryReduce = true; break; } if (reducedDictionarySize >= ((UInt32)3 << 30)) break; reducedDictionarySize += step; } } { int numProps = method.Props.Size(); CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); if (setCoderProperties == NULL) { if (numProps != 0) return E_INVALIDARG; } else { CRecordVector<PROPID> propIDs; NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProps]; HRESULT res = S_OK; try { for (int i = 0; i < numProps; i++) { const CProp &prop = method.Props[i]; propIDs.Add(prop.Id); NWindows::NCOM::CPropVariant &value = values[i]; value = prop.Value; // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal) if (tryReduce) if (prop.Id == NCoderPropID::kDictionarySize) if (value.vt == VT_UI4) if (reducedDictionarySize < value.ulVal) value.ulVal = reducedDictionarySize; } CMyComPtr<ICompressSetCoderProperties> setCoderProperties; coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties); res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProps); } catch(...) { delete []values; throw; } delete []values; RINOK(res); } } /* CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); if (writeCoderProperties != NULL) { CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->Init(); RINOK(writeCoderProperties->WriteCoderProperties(outStream)); size_t size = outStreamSpec->GetSize(); filterProps.SetCapacity(size); memmove(filterProps, outStreamSpec->GetBuffer(), size); } */ return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/MethodProps.h ================================================ // MethodProps.h #ifndef __7Z_METHOD_PROPS_H #define __7Z_METHOD_PROPS_H #include "../../Common/MyVector.h" #include "../../Windows/PropVariant.h" #include "MethodId.h" struct CProp { PROPID Id; NWindows::NCOM::CPropVariant Value; }; struct CMethod { CMethodId Id; CObjectVector<CProp> Props; }; struct CMethodsMode { CObjectVector<CMethod> Methods; #ifdef COMPRESS_MT UInt32 NumThreads; #endif CMethodsMode() #ifdef COMPRESS_MT : NumThreads(1) #endif {} bool IsEmpty() const { return Methods.IsEmpty() ; } }; HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/OffsetStream.cpp ================================================ // OffsetStream.cpp #include "StdAfx.h" #include "Common/Defs.h" #include "OffsetStream.h" HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; return _stream->Seek(offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { return _stream->Write(data, size, processedSize); } STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 absoluteNewPosition; if (seekOrigin == STREAM_SEEK_SET) offset += _offset; HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition); if (newPosition != NULL) *newPosition = absoluteNewPosition - _offset; return result; } STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize) { return _stream->SetSize(_offset + newSize); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/OffsetStream.h ================================================ // OffsetStream.h #ifndef __OFFSETSTREAM_H #define __OFFSETSTREAM_H #include "Common/MyCom.h" #include "../IStream.h" class COffsetOutStream: public IOutStream, public CMyUnknownImp { UInt64 _offset; CMyComPtr<IOutStream> _stream; public: HRESULT Init(IOutStream *stream, UInt64 offset); MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" extern "C" { #include "../../../C/Alloc.h" } bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode == S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = Flush(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #include "../../Common/MyException.h" #ifndef _NO_EXCEPTIONS struct COutBufferException: public CSystemException { COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void FlushWithCheck(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/ProgressUtils.cpp ================================================ // ProgressUtils.h #include "StdAfx.h" #include "ProgressUtils.h" CLocalProgress::CLocalProgress() { ProgressOffset = InSize = OutSize = 0; SendRatio = SendProgress = true; } void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain) { _ratioProgress.Release(); _progress = progress; _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress); _inSizeIsMain = inSizeIsMain; } STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { UInt64 inSizeNew = InSize, outSizeNew = OutSize; if (inSize) inSizeNew += (*inSize); if (outSize) outSizeNew += (*outSize); if (SendRatio && _ratioProgress) { RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew)); } inSizeNew += ProgressOffset; outSizeNew += ProgressOffset; if (SendProgress) return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew); return S_OK; } HRESULT CLocalProgress::SetCur() { return SetRatioInfo(NULL, NULL); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/ProgressUtils.h ================================================ // ProgressUtils.h #ifndef __PROGRESSUTILS_H #define __PROGRESSUTILS_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "../IProgress.h" class CLocalProgress: public ICompressProgressInfo, public CMyUnknownImp { CMyComPtr<IProgress> _progress; CMyComPtr<ICompressProgressInfo> _ratioProgress; bool _inSizeIsMain; public: UInt64 ProgressOffset; UInt64 InSize; UInt64 OutSize; bool SendRatio; bool SendProgress; CLocalProgress(); void Init(IProgress *progress, bool inSizeIsMain); HRESULT SetCur(); MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/RegisterArc.h ================================================ // RegisterArc.h #ifndef __REGISTERARC_H #define __REGISTERARC_H #include "../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcInfo { const wchar_t *Name; const wchar_t *Ext; const wchar_t *AddExt; Byte ClassId; Byte Signature[16]; int SignatureSize; bool KeepName; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; }; void RegisterArc(const CArcInfo *arcInfo); #define REGISTER_ARC_NAME(x) CRegister ## x #define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \ REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \ static REGISTER_ARC_NAME(x) g_RegisterArc; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/RegisterCodec.h ================================================ // RegisterCodec.h #ifndef __REGISTERCODEC_H #define __REGISTERCODEC_H #include "../Common/MethodId.h" typedef void * (*CreateCodecP)(); struct CCodecInfo { CreateCodecP CreateDecoder; CreateCodecP CreateEncoder; CMethodId Id; const wchar_t *Name; UInt32 NumInStreams; bool IsFilter; }; void RegisterCodec(const CCodecInfo *codecInfo); #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ static REGISTER_CODEC_NAME(x) g_RegisterCodec; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x #define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \ REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \ RegisterCodec(&g_CodecsInfo[i]); }}; \ static REGISTER_CODECS_NAME(x) g_RegisterCodecs; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamBinder.cpp ================================================ // StreamBinder.cpp #include "StdAfx.h" #include "StreamBinder.h" #include "../../Common/Defs.h" #include "../../Common/MyCom.h" using namespace NWindows; using namespace NSynchronization; class CSequentialInStreamForBinder: public ISequentialInStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Read(data, size, processedSize); } class CSequentialOutStreamForBinder: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); private: CStreamBinder *m_StreamBinder; public: ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } }; STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { return m_StreamBinder->Write(data, size, processedSize); } ////////////////////////// // CStreamBinder // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. HRes CStreamBinder::CreateEvents() { RINOK(_allBytesAreWritenEvent.Create(true)); RINOK(_thereAreBytesToReadEvent.Create()); return _readStreamIsClosedEvent.Create(); } void CStreamBinder::ReInit() { _thereAreBytesToReadEvent.Reset(); _readStreamIsClosedEvent.Reset(); ProcessedSize = 0; } void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) { CSequentialInStreamForBinder *inStreamSpec = new CSequentialInStreamForBinder; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SetBinder(this); *inStream = inStreamLoc.Detach(); CSequentialOutStreamForBinder *outStreamSpec = new CSequentialOutStreamForBinder; CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); outStreamSpec->SetBinder(this); *outStream = outStreamLoc.Detach(); _buffer = NULL; _bufferSize= 0; ProcessedSize = 0; } HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 sizeToRead = size; if (size > 0) { RINOK(_thereAreBytesToReadEvent.Lock()); sizeToRead = MyMin(_bufferSize, size); if (_bufferSize > 0) { memcpy(data, _buffer, sizeToRead); _buffer = ((const Byte *)_buffer) + sizeToRead; _bufferSize -= sizeToRead; if (_bufferSize == 0) { _thereAreBytesToReadEvent.Reset(); _allBytesAreWritenEvent.Set(); } } } if (processedSize != NULL) *processedSize = sizeToRead; ProcessedSize += sizeToRead; return S_OK; } void CStreamBinder::CloseRead() { _readStreamIsClosedEvent.Set(); } HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (size > 0) { _buffer = data; _bufferSize = size; _allBytesAreWritenEvent.Reset(); _thereAreBytesToReadEvent.Set(); HANDLE events[2]; events[0] = _allBytesAreWritenEvent; events[1] = _readStreamIsClosedEvent; DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); if (waitResult != WAIT_OBJECT_0 + 0) { // ReadingWasClosed = true; return S_FALSE; } // if(!_allBytesAreWritenEvent.Lock()) // return E_FAIL; } if (processedSize != NULL) *processedSize = size; return S_OK; } void CStreamBinder::CloseWrite() { // _bufferSize must be = 0 _thereAreBytesToReadEvent.Set(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamBinder.h ================================================ // StreamBinder.h #ifndef __STREAMBINDER_H #define __STREAMBINDER_H #include "../IStream.h" #include "../../Windows/Synchronization.h" class CStreamBinder { NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent; NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent; NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent; UInt32 _bufferSize; const void *_buffer; public: // bool ReadingWasClosed; UInt64 ProcessedSize; CStreamBinder() {} HRes CreateEvents(); void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); void CloseRead(); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); void CloseWrite(); void ReInit(); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamObjects.cpp ================================================ // StreamObjects.cpp #include "StdAfx.h" #include "StreamObjects.h" #include "../../Common/Defs.h" STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(data, _dataPointer + _pos, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return S_OK; } void CWriteBuffer::Write(const void *data, size_t size) { size_t newCapacity = _size + size; _buffer.EnsureCapacity(newCapacity); memcpy(_buffer + _size, data, size); _size += size; } STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize) { _writeBuffer.Write(data, (size_t)size); if(processedSize != NULL) *processedSize = size; return S_OK; } STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t rem = _size - _pos; if (size < rem) rem = (size_t)size; memcpy(_buffer + _pos, data, rem); _pos += rem; if (processedSize != NULL) *processedSize = (UInt32)rem; return (rem == size ? S_OK : E_FAIL); } STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Read(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 realProcessedSize; HRESULT result = _stream->Write(data, size, &realProcessedSize); _size += realProcessedSize; if (processedSize != 0) *processedSize = realProcessedSize; return result; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamObjects.h ================================================ // StreamObjects.h #ifndef __STREAMOBJECTS_H #define __STREAMOBJECTS_H #include "../../Common/DynamicBuffer.h" #include "../../Common/MyCom.h" #include "../IStream.h" class CSequentialInStreamImp: public ISequentialInStream, public CMyUnknownImp { const Byte *_dataPointer; size_t _size; size_t _pos; public: void Init(const Byte *dataPointer, size_t size) { _dataPointer = dataPointer; _size = size; _pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CWriteBuffer { CByteDynamicBuffer _buffer; size_t _size; public: CWriteBuffer(): _size(0) {} void Init() { _size = 0; } void Write(const void *data, size_t size); size_t GetSize() const { return _size; } const CByteDynamicBuffer& GetBuffer() const { return _buffer; } }; class CSequentialOutStreamImp: public ISequentialOutStream, public CMyUnknownImp { CWriteBuffer _writeBuffer; public: void Init() { _writeBuffer.Init(); } size_t GetSize() const { return _writeBuffer.GetSize(); } const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamImp2: public ISequentialOutStream, public CMyUnknownImp { Byte *_buffer; size_t _size; size_t _pos; public: void Init(Byte *buffer, size_t size) { _buffer = buffer; _pos = 0; _size = size; } size_t GetPos() const { return _pos; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialInStreamSizeCount: public ISequentialInStream, public CMyUnknownImp { CMyComPtr<ISequentialInStream> _stream; UInt64 _size; public: void Init(ISequentialInStream *stream) { _stream = stream; _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; public: void SetStream(ISequentialOutStream *stream) { _stream = stream; } void Init() { _size = 0; } UInt64 GetSize() const { return _size; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "StreamUtils.h" static const UInt32 kBlockSize = ((UInt32)1 << 31); HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) { size_t size = *processedSize; *processedSize = 0; while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Read(data, curSize, &processedSizeLoc); *processedSize += processedSizeLoc; data = (void *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : S_FALSE; } HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) { size_t processedSize = size; RINOK(ReadStream(stream, data, &processedSize)); return (size == processedSize) ? S_OK : E_FAIL; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) { while (size != 0) { UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize; UInt32 processedSizeLoc; HRESULT res = stream->Write(data, curSize, &processedSizeLoc); data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return E_FAIL; } return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size); HRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size); HRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/VirtThread.cpp ================================================ // VirtThread.cpp #include "StdAfx.h" #include "VirtThread.h" static THREAD_FUNC_DECL CoderThread(void *p) { for (;;) { CVirtThread *t = (CVirtThread *)p; t->StartEvent.Lock(); if (t->ExitEvent) return 0; t->Execute(); t->FinishedEvent.Set(); } } WRes CVirtThread::Create() { RINOK(StartEvent.CreateIfNotCreated()); RINOK(FinishedEvent.CreateIfNotCreated()); StartEvent.Reset(); FinishedEvent.Reset(); ExitEvent = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } void CVirtThread::Start() { ExitEvent = false; StartEvent.Set(); } CVirtThread::~CVirtThread() { ExitEvent = true; if (StartEvent.IsCreated()) StartEvent.Set(); Thread.Wait(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Common/VirtThread.h ================================================ // VirtThread.h #ifndef __VIRTTHREAD_H #define __VIRTTHREAD_H #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" struct CVirtThread { NWindows::NSynchronization::CAutoResetEvent StartEvent; NWindows::NSynchronization::CAutoResetEvent FinishedEvent; NWindows::CThread Thread; bool ExitEvent; ~CVirtThread(); WRes Create(); void Start(); void WaitFinish() { FinishedEvent.Lock(); } virtual void Execute() = 0; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/Bcj2Coder.cpp ================================================ // Bcj2Coder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "Bcj2Coder.h" namespace NCompress { namespace NBcj2 { inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); } inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); } #ifndef EXTRACT_ONLY static const int kBufferSize = 1 << 17; static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CEncoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CEncoder::~CEncoder() { ::MidFree(_buffer); } HRESULT CEncoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize = 0; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256 + 2; i++) _statusEncoder[i].Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; for (;;) { UInt32 processedSize = 0; for (;;) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); UInt32 index; if (b == 0xE8) index = prevByte; else if (b == 0xE9) index = 256; else if (IsJcc(prevByte, b)) index = 257; else { prevByte = b; continue; } _statusEncoder[index].Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (!IsJ(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); unsigned index = GetIndex(prevByte, b); if (convert) { _statusEncoder[index].Encode(&_rangeEncoder, 1); bufferPos += 5; COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 24; i >= 0; i -= 8) s.WriteByte((Byte)(dest >> i)); prevByte = nextByte; } else { _statusEncoder[index].Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { /* const UInt64 compressedSize = _mainStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeEncoder.GetProcessedSize(); */ RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams, const UInt64 ** /* inSizes */, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 ** /* outSizes */, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256 + 2; i++) _statusDecoder[i].Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; for (;;) { if (processedBytes >= (1 << 20) && progress != NULL) { /* const UInt64 compressedSize = _mainInStream.GetProcessedSize() + _callStream.GetProcessedSize() + _jumpStream.GetProcessedSize() + _rangeDecoder.GetProcessedSize(); */ const UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } UInt32 i; Byte b = 0; const UInt32 kBurstSize = (1 << 18); for (i = 0; i < kBurstSize; i++) { if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (IsJ(prevByte, b)) break; prevByte = b; } processedBytes += i; if (i == kBurstSize) continue; unsigned index = GetIndex(prevByte, b); if (_statusDecoder[index].Decode(&_rangeDecoder) == 1) { UInt32 src = 0; CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream; for (int i = 0; i < 4; i++) { Byte b0; if(!s.ReadByte(b0)) return S_FALSE; src <<= 8; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (Byte)(dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/Bcj2Coder.h ================================================ // Bcj2Coder.h #ifndef __COMPRESS_BCJ2_CODER_H #define __COMPRESS_BCJ2_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" #include "RangeCoderBit.h" namespace NCompress { namespace NBcj2 { const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CEncoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CEncoder(): _buffer(0) {}; ~CEncoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2]; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CDecoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2]; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CDecoder *_coder; public: CCoderReleaser(CDecoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/Bcj2Register.cpp ================================================ // Bcj2Register.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "Bcj2Coder.h" static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false }; REGISTER_CODEC(BCJ2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BcjCoder.cpp ================================================ // BcjCoder.cpp #include "StdAfx.h" #include "BcjCoder.h" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BcjCoder.h ================================================ // BcjCoder.h #ifndef __COMPRESS_BCJ_CODER_H #define __COMPRESS_BCJ_CODER_H extern "C" { #include "../../../C/Bra.h" } #include "BranchCoder.h" struct CBranch86 { UInt32 _prevMask; void x86Init() { x86_Convert_Init(_prevMask); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BcjRegister.cpp ================================================ // BcjRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BcjCoder.h" static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); } #ifndef EXTRACT_ONLY static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder()); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true }; REGISTER_CODEC(BCJ) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BranchCoder.h ================================================ // BranchCoder.h #ifndef __COMPRESS_BRANCH_CODER_H #define __COMPRESS_BRANCH_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassA(Name, id, subId) \ MyClassEncoderA(Name ## _Encoder) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BranchMisc.cpp ================================================ // BranchMisc.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Bra.h" } #include "BranchMisc.h" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARM_Convert(data, size, _bufferPos, 0); } UInt32 CBC_ARMT_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMT_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::ARMT_Convert(data, size, _bufferPos, 0); } UInt32 CBC_PPC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::PPC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::SPARC_Convert(data, size, _bufferPos, 0); } UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return (UInt32)::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BranchMisc.h ================================================ // BranchMisc.h #ifndef __COMPRESS_BRANCH_MISC_H #define __COMPRESS_BRANCH_MISC_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) MyClassA(BC_ARMT, 0x07, 1) MyClassA(BC_PPC, 0x02, 5) MyClassA(BC_SPARC, 0x08, 5) MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/BranchRegister.cpp ================================================ // BranchRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "BranchMisc.h" #define CREATE_CODEC(x) \ static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \ static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); } CREATE_CODEC(BC_PPC) CREATE_CODEC(BC_IA64) CREATE_CODEC(BC_ARM) CREATE_CODEC(BC_ARMT) CREATE_CODEC(BC_SPARC) #define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true } static CCodecInfo g_CodecsInfo[] = { METHOD_ITEM(BC_PPC, 0x02, 0x05, L"PPC"), METHOD_ITEM(BC_IA64, 0x04, 1, L"IA64"), METHOD_ITEM(BC_ARM, 0x05, 1, L"ARM"), METHOD_ITEM(BC_ARMT, 0x07, 1, L"ARMT"), METHOD_ITEM(BC_SPARC, 0x08, 0x05, L"SPARC") }; REGISTER_CODECS(Branch) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/ByteSwap.cpp ================================================ // ByteSwap.cpp #include "StdAfx.h" #include "ByteSwap.h" STDMETHODIMP CByteSwap2::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 2; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b = data[i]; data[i] = data[i + 1]; data[i + 1] = b; } return i; } STDMETHODIMP CByteSwap4::Init() { return S_OK; } STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size) { const UInt32 kStep = 4; UInt32 i; for (i = 0; i + kStep <= size; i += kStep) { Byte b0 = data[i]; Byte b1 = data[i + 1]; data[i] = data[i + 3]; data[i + 1] = data[i + 2]; data[i + 2] = b1; data[i + 3] = b0; } return i; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/ByteSwap.h ================================================ // ByteSwap.h #ifndef __COMPRESS_BYTE_SWAP_H #define __COMPRESS_BYTE_SWAP_H #include "../../Common/MyCom.h" #include "../ICoder.h" class CByteSwap2: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; class CByteSwap4: public ICompressFilter, public CMyUnknownImp { public: MY_UNKNOWN_IMP STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/ByteSwapRegister.cpp ================================================ // ByteSwapRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "ByteSwap.h" static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); } static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); } static CCodecInfo g_CodecsInfo[] = { { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true }, { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true } }; REGISTER_CODECS(ByteSwap) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/CodecExports.cpp ================================================ // CodecExports.cpp #include "StdAfx.h" #include "../../Common/ComTry.h" #include "../../Windows/PropVariant.h" #include "../Common/RegisterCodec.h" #include "../ICoder.h" extern unsigned int g_NumCodecs; extern const CCodecInfo *g_Codecs[]; static const UInt16 kDecodeId = 0x2790; DEFINE_GUID(CLSID_CCodec, 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value) { if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0) value->vt = VT_BSTR; return S_OK; } static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) { return SetPropString((const char *)&guid, sizeof(GUID), value); } static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value) { GUID clsId = CLSID_CCodec; for (int i = 0; i < sizeof(id); i++, id >>= 8) clsId.Data4[i] = (Byte)(id & 0xFF); if (encode) clsId.Data3++; return SetPropGUID(clsId, value); } static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index) { index = -1; if (clsID->Data1 != CLSID_CCodec.Data1 || clsID->Data2 != CLSID_CCodec.Data2 || (clsID->Data3 & ~1) != kDecodeId) return S_OK; encode = (clsID->Data3 != kDecodeId); UInt64 id = 0; for (int j = 0; j < 8; j++) id |= ((UInt64)clsID->Data4[j]) << (8 * j); for (unsigned i = 0; i < g_NumCodecs; i++) { const CCodecInfo &codec = *g_Codecs[i]; if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder) continue; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; index = i; return S_OK; } return S_OK; } STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject) { COM_TRY_BEGIN *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; const CCodecInfo &codec = *g_Codecs[index]; if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter || codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2) return E_NOINTERFACE; if (encode) { if (!codec.CreateEncoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateEncoder(); } else { if (!codec.CreateDecoder) return CLASS_E_CLASSNOTAVAILABLE; *outObject = codec.CreateDecoder(); } if (isCoder) ((ICompressCoder *)*outObject)->AddRef(); else if (isCoder2) ((ICompressCoder2 *)*outObject)->AddRef(); else ((ICompressFilter *)*outObject)->AddRef(); return S_OK; COM_TRY_END } STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject) { *outObject = 0; bool isCoder = (*iid == IID_ICompressCoder) != 0; bool isCoder2 = (*iid == IID_ICompressCoder2) != 0; bool isFilter = (*iid == IID_ICompressFilter) != 0; if (!isCoder && !isCoder2 && !isFilter) return E_NOINTERFACE; bool encode; int codecIndex; HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex); if (res != S_OK) return res; if (codecIndex < 0) return CLASS_E_CLASSNOTAVAILABLE; return CreateCoder2(encode, codecIndex, iid, outObject); } STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value) { ::VariantClear((VARIANTARG *)value); const CCodecInfo &codec = *g_Codecs[codecIndex]; switch(propID) { case NMethodPropID::kID: { value->uhVal.QuadPart = (UInt64)codec.Id; value->vt = VT_UI8; break; } case NMethodPropID::kName: if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0) value->vt = VT_BSTR; break; case NMethodPropID::kDecoder: if (codec.CreateDecoder) return SetClassID(codec.Id, false, value); break; case NMethodPropID::kEncoder: if (codec.CreateEncoder) return SetClassID(codec.Id, true, value); break; case NMethodPropID::kInStreams: { if (codec.NumInStreams != 1) { value->vt = VT_UI4; value->ulVal = (ULONG)codec.NumInStreams; } break; } } return S_OK; } STDAPI GetNumberOfMethods(UINT32 *numCodecs) { *numCodecs = g_NumCodecs; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/CopyCoder.cpp ================================================ // Compress/CopyCoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_buffer == 0) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (_buffer == 0) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 realProcessedSize; UInt32 size = kBufferSize; if (outSize != 0) if (size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &realProcessedSize)); if (realProcessedSize == 0) break; RINOK(WriteStream(outStream, _buffer, realProcessedSize)); TotalSize += realProcessedSize; if (progress != NULL) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/CopyCoder.h ================================================ // Compress/CopyCoder.h #ifndef __COMPRESS_COPY_CODER_H #define __COMPRESS_COPY_CODER_H #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { class CCopyCoder: public ICompressCoder, public ICompressGetInStreamProcessedSize, public CMyUnknownImp { Byte *_buffer; public: UInt64 TotalSize; CCopyCoder(): TotalSize(0) , _buffer(0) {}; ~CCopyCoder(); MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/CopyRegister.cpp ================================================ // CopyRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "CopyCoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); } static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodec, 0x00, L"Copy", 1, false }; REGISTER_CODEC(Copy) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LzmaDecoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaDecoder.h # End Source File # Begin Source File SOURCE=..\LzmaEncoder.cpp # End Source File # Begin Source File SOURCE=..\LzmaEncoder.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\Synchronization.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\System.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Thread.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Group "C" # PROP Default_Filter "" # Begin Group "LzmaUtil" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Dec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaUtil\Lzma86Enc.h # End Source File # End Group # Begin Source File SOURCE=..\..\..\..\C\7zCrc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\7zCrc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Bra86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFind.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzFindMt.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzHash.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaDec.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\LzmaEnc.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\..\..\..\C\Threads.h # End Source File # Begin Source File SOURCE=..\..\..\..\C\Types.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.cpp # End Source File # Begin Source File SOURCE=.\LzmaBenchCon.h # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/Exception.h ================================================ /* A couple of exceptions for lzmp. * * Copyright (C) 2005 Ville Koskinen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _EXCEPTION_H_ #define _EXCEPTION_H_ #include <string> using std::string; class Exception { private: string message; public: Exception(char *what): message(what) { } Exception(string what): message(what) { } ~Exception() { } string what(void) { return message; } }; class ArgumentException: public Exception { public: ArgumentException(char *what): Exception(what) { } ArgumentException(string what): Exception(what) { } ~ArgumentException() { } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #include "LzmaBenchCon.h" #ifdef COMPRESS_MF_MT #include "../../../Windows/System.h" #endif extern "C" { #include "../../../../C/7zVersion.h" #include "../../../../C/Alloc.h" #include "../../../../C/LzmaUtil/Lzma86Dec.h" #include "../../../../C/LzmaUtil/Lzma86Enc.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kAlgo, kDict, kFb, kMc, kLc, kLp, kPb, kMatchFinder, kMultiThread, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MT", NSwitchType::kUnLimitedPostString, false, 0 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kPostChar, false, 0, 0, L"+" } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" " -d{N}: set dictionary size - [12, 30], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -mc{N}: set number of cycles for match finder\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" " -mt{N}: set number of CPU threads\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } static void ParseUInt32(const CParser &parser, int index, UInt32 &res) { if (parser[index].ThereIs) if (!GetNumber(parser[index].PostStrings[0], res)) IncorrectCommand(); } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n"); if (n == 1) { PrintHelp(); return 0; } bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4); if (unsupportedTypes) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictDefined = false; UInt32 dict = (UInt32)-1; if(parser[NKey::kDict].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDict].PostStrings[0], dicLog)) IncorrectCommand(); dict = 1 << dicLog; dictDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; UInt32 numThreads = (UInt32)-1; #ifdef COMPRESS_MF_MT if (parser[NKey::kMultiThread].ThereIs) { UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); const UString &s = parser[NKey::kMultiThread].PostStrings[0]; if (s.IsEmpty()) numThreads = numCPUs; else if (!GetNumber(s, numThreads)) IncorrectCommand(); } #endif if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 1; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchCon(stderr, numIterations, numThreads, dict); } if (numThreads == (UInt32)-1) numThreads = 1; bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; COutFileStream *outStreamSpec = NULL; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; size_t inSize = (size_t)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } if (ReadStream_FAIL(inStream, inBuffer, inSize) != S_OK) throw "Can not read"; Byte *outBuffer = 0; size_t outSize; if (encodeMode) { // we allocate 105% of original size for output buffer outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictDefined) dict = 1 << 23; int res = Lzma86_Encode(outBuffer, &outSize, inBuffer, inSize, 5, dict, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { UInt64 outSize64; if (Lzma86_GetUnpackSize(inBuffer, inSize, &outSize64) != 0) throw "data error"; outSize = (size_t)outSize64; if (outSize != outSize64) throw "too big"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = Lzma86_Decode(outBuffer, &outSize, inBuffer, &inSize); if (inSize != (size_t)fileSize) throw "incorrect processed size"; if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, outSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictDefined) dict = 1 << 23; UInt32 pb = 2; UInt32 lc = 3; // = 0; for 32-bit data UInt32 lp = 0; // = 2; for 32-bit data UInt32 algo = 1; UInt32 fb = 128; UInt32 mc = 16 + fb / 2; bool mcDefined = false; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; ParseUInt32(parser, NKey::kAlgo, algo); ParseUInt32(parser, NKey::kFb, fb); ParseUInt32(parser, NKey::kLc, lc); ParseUInt32(parser, NKey::kLp, lp); ParseUInt32(parser, NKey::kPb, pb); mcDefined = parser[NKey::kMc].ThereIs; if (mcDefined) if (!GetNumber(parser[NKey::kMc].PostStrings[0], mc)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker, NCoderPropID::kNumThreads, NCoderPropID::kMatchFinderCycles, }; const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT props[kNumPropsMax]; for (int p = 0; p < 6; p++) props[p].vt = VT_UI4; props[0].ulVal = (UInt32)dict; props[1].ulVal = (UInt32)pb; props[2].ulVal = (UInt32)lc; props[3].ulVal = (UInt32)lp; props[4].ulVal = (UInt32)algo; props[5].ulVal = (UInt32)fb; props[6].vt = VT_BSTR; props[6].bstrVal = (BSTR)(const wchar_t *)mf; props[7].vt = VT_BOOL; props[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; props[8].vt = VT_UI4; props[8].ulVal = (UInt32)numThreads; // it must be last in property list props[9].vt = VT_UI4; props[9].ulVal = (UInt32)mc; int numProps = kNumPropsMax; if (!mcDefined) numProps--; if (encoderSpec->SetCoderProperties(propIDs, props, numProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; decoderSpec->FinishStream = true; const UInt32 kPropertiesSize = 5; Byte header[kPropertiesSize + 8]; if (ReadStream_FALSE(inStream, header, kPropertiesSize + 8) != S_OK) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(header, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) fileSize |= ((UInt64)header[kPropertiesSize + i]) << (8 * i); if (decoder->Code(inStream, outStream, 0, (fileSize == (UInt64)(Int64)-1) ? 0 : &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } if (outStreamSpec != NULL) { if (outStreamSpec->Close() != S_OK) { fprintf(stderr, "File closing error"); return 1; } } return 0; } int MY_CDECL main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif #ifdef _WIN32 #define USE_ALLOCA #endif #ifdef USE_ALLOCA #ifdef _WIN32 #include <malloc.h> #else #include <stdlib.h> #endif #endif extern "C" { #include "../../../../C/7zCrc.h" #include "../../../../C/Alloc.h" } #include "../../../Common/MyCom.h" #ifdef BENCH_MT #include "../../../Windows/Synchronization.h" #include "../../../Windows/Thread.h" #endif #ifdef EXTERNAL_LZMA #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #else #include "../LzmaDecoder.h" #include "../LzmaEncoder.h" #endif static const UInt32 kUncompressMinBlockSize = 1 << 26; static const UInt32 kAdditionalSize = (1 << 16); static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 5; class CBaseRandomGenerator { UInt32 A1; UInt32 A2; public: CBaseRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBenchBuffer { public: size_t BufferSize; Byte *Buffer; CBenchBuffer(): Buffer(0) {} virtual ~CBenchBuffer() { Free(); } void Free() { ::MidFree(Buffer); Buffer = 0; } bool Alloc(size_t bufferSize) { if (Buffer != 0 && BufferSize == bufferSize) return true; Free(); Buffer = (Byte *)::MidAlloc(bufferSize); BufferSize = bufferSize; return (Buffer != 0); } }; class CBenchRandomGenerator: public CBenchBuffer { CBaseRandomGenerator *RG; public: void Set(CBaseRandomGenerator *rg) { RG = rg; } UInt32 GetVal(UInt32 &res, int numBits) { UInt32 val = res & (((UInt32)1 << numBits) - 1); res >>= numBits; return val; } UInt32 GetLen(UInt32 &res) { UInt32 len = GetVal(res, 2); return GetVal(res, 1 + len); } void Generate() { UInt32 pos = 0; UInt32 rep0 = 1; while (pos < BufferSize) { UInt32 res = RG->GetRnd(); res >>= 1; if (GetVal(res, 1) == 0 || pos < 1024) Buffer[pos++] = (Byte)(res & 0xFF); else { UInt32 len; len = 1 + GetLen(res); if (GetVal(res, 3) != 0) { len += GetLen(res); do { UInt32 ppp = GetVal(res, 5) + 6; res = RG->GetRnd(); if (ppp > 30) continue; rep0 = /* (1 << ppp) +*/ GetVal(res, ppp); res = RG->GetRnd(); } while (rep0 >= pos); rep0++; } for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++) Buffer[pos] = Buffer[pos - rep0]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Pos; size_t Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { size_t remain = Size - Pos; UInt32 kMaxBlockSize = (1 << 20); if (size > kMaxBlockSize) size = kMaxBlockSize; if (size > remain) size = (UInt32)remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CBenchBuffer, public CMyUnknownImp { // bool _overflow; public: UInt32 Pos; // CBenchmarkOutStream(): _overflow(false) {} void Init() { // _overflow = false; Pos = 0; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { size_t curSize = BufferSize - Pos; if (curSize > size) curSize = size; memcpy(Buffer + Pos, data, curSize); Pos += (UInt32)curSize; if(processedSize != NULL) *processedSize = (UInt32)curSize; if (curSize != size) { // _overflow = true; return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: UInt32 Crc; MY_UNKNOWN_IMP void Init() { Crc = CRC_INIT_VAL; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { Crc = CrcUpdate(Crc, data, size); if (processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec; return (UInt64)time(NULL) * 1000000; #else return time(NULL); #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; */ return GetTickCount(); #endif } static UInt64 GetFreq() { #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 return 1000000; #else return 1; #endif #else /* LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; */ return 1000; #endif } #ifndef USE_POSIX_TIME static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } #endif static UInt64 GetUserTime() { #ifdef USE_POSIX_TIME return clock(); #else FILETIME creationTime, exitTime, kernelTime, userTime; if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0) return GetTime64(userTime) + GetTime64(kernelTime); return (UInt64)GetTickCount() * 10000; #endif } static UInt64 GetUserFreq() { #ifdef USE_POSIX_TIME return CLOCKS_PER_SEC; #else return 10000000; #endif } class CBenchProgressStatus { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSection CS; #endif public: HRESULT Res; bool EncodeMode; void SetResult(HRESULT res) { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif Res = res; } HRESULT GetResult() { #ifdef BENCH_MT NWindows::NSynchronization::CCriticalSectionLock lock(CS); #endif return Res; } }; class CBenchProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { public: CBenchProgressStatus *Status; CBenchInfo BenchInfo; HRESULT Res; IBenchCallback *callback; CBenchProgressInfo(): callback(0) {} MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; void SetStartTime(CBenchInfo &bi) { bi.GlobalFreq = GetFreq(); bi.UserFreq = GetUserFreq(); bi.GlobalTime = ::GetTimeCount(); bi.UserTime = ::GetUserTime(); } void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest) { dest.GlobalFreq = GetFreq(); dest.UserFreq = GetUserFreq(); dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime; dest.UserTime = ::GetUserTime() - biStart.UserTime; } STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { HRESULT res = Status->GetResult(); if (res != S_OK) return res; if (!callback) return res; CBenchInfo info = BenchInfo; SetFinishTime(BenchInfo, info); if (Status->EncodeMode) { info.UnpackSize = *inSize; info.PackSize = *outSize; res = callback->SetEncodeResult(info, false); } else { info.PackSize = BenchInfo.PackSize + *inSize; info.UnpackSize = BenchInfo.UnpackSize + *outSize; res = callback->SetDecodeResult(info, false); } if (res != S_OK) Status->SetResult(res); return res; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } UInt64 GetUsage(const CBenchInfo &info) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userTime, userFreq); NormalizeVals(globalFreq, globalTime); if (userFreq == 0) userFreq = 1; if (globalTime == 0) globalTime = 1; return userTime * globalFreq * 1000000 / userFreq / globalTime; } UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating) { UInt64 userTime = info.UserTime; UInt64 userFreq = info.UserFreq; UInt64 globalTime = info.GlobalTime; UInt64 globalFreq = info.GlobalFreq; NormalizeVals(userFreq, userTime); NormalizeVals(globalTime, globalFreq); if (globalFreq == 0) globalFreq = 1; if (userTime == 0) userTime = 1; return userFreq * globalTime / globalFreq * rating / userTime; } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits); UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime, freq); } UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations) { UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations; return MyMultDiv64(numCommands, elapsedTime, freq); } #ifdef EXTERNAL_LZMA typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, const GUID *interfaceID, void **outObject); #endif struct CEncoderInfo; struct CEncoderInfo { #ifdef BENCH_MT NWindows::CThread thread[2]; #endif CMyComPtr<ICompressCoder> encoder; CBenchProgressInfo *progressInfoSpec[2]; CMyComPtr<ICompressProgressInfo> progressInfo[2]; UInt32 NumIterations; #ifdef USE_ALLOCA size_t AllocaSize; #endif struct CDecoderInfo { CEncoderInfo *Encoder; UInt32 DecoderIndex; #ifdef USE_ALLOCA size_t AllocaSize; #endif bool CallbackMode; }; CDecoderInfo decodersInfo[2]; CMyComPtr<ICompressCoder> decoders[2]; HRESULT Results[2]; CBenchmarkOutStream *outStreamSpec; CMyComPtr<ISequentialOutStream> outStream; IBenchCallback *callback; UInt32 crc; UInt32 kBufferSize; UInt32 compressedSize; CBenchRandomGenerator rg; CBenchmarkOutStream *propStreamSpec; CMyComPtr<ISequentialOutStream> propStream; HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg); HRESULT Encode(); HRESULT Decode(UInt32 decoderIndex); CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {} #ifdef BENCH_MT static THREAD_FUNC_DECL EncodeThreadFunction(void *param) { CEncoderInfo *encoder = (CEncoderInfo *)param; #ifdef USE_ALLOCA alloca(encoder->AllocaSize); #endif HRESULT res = encoder->Encode(); encoder->Results[0] = res; if (res != S_OK) encoder->progressInfoSpec[0]->Status->SetResult(res); return 0; } static THREAD_FUNC_DECL DecodeThreadFunction(void *param) { CDecoderInfo *decoder = (CDecoderInfo *)param; #ifdef USE_ALLOCA alloca(decoder->AllocaSize); #endif CEncoderInfo *encoder = decoder->Encoder; encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex); return 0; } HRESULT CreateEncoderThread() { return thread[0].Create(EncodeThreadFunction, this); } HRESULT CreateDecoderThread(int index, bool callbackMode #ifdef USE_ALLOCA , size_t allocaSize #endif ) { CDecoderInfo &decoder = decodersInfo[index]; decoder.DecoderIndex = index; decoder.Encoder = this; #ifdef USE_ALLOCA decoder.AllocaSize = allocaSize; #endif decoder.CallbackMode = callbackMode; return thread[index].Create(DecodeThreadFunction, &decoder); } #endif }; HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc) { rg.Set(rgLoc); kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (!rg.Alloc(kBufferSize)) return E_OUTOFMEMORY; rg.Generate(); crc = CrcCalc(rg.Buffer, rg.BufferSize); outStreamSpec = new CBenchmarkOutStream; if (!outStreamSpec->Alloc(kCompressedBufferSize)) return E_OUTOFMEMORY; outStream = outStreamSpec; propStreamSpec = 0; if (!propStream) { propStreamSpec = new CBenchmarkOutStream; propStream = propStreamSpec; } if (!propStreamSpec->Alloc(kMaxLzmaPropSize)) return E_OUTOFMEMORY; propStreamSpec->Init(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMultiThread }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = (UInt32)dictionarySize; properties[1].vt = VT_BOOL; properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE; { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties)); if (!setCoderProperties) return E_FAIL; RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps)); CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties); if (writeCoderProperties) { RINOK(writeCoderProperties->WriteCoderProperties(propStream)); } } return S_OK; } HRESULT CEncoderInfo::Encode() { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; inStreamSpec->Init(rg.Buffer, rg.BufferSize); outStreamSpec->Init(); RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0])); compressedSize = outStreamSpec->Pos; encoder.Release(); return S_OK; } HRESULT CEncoderInfo::Decode(UInt32 decoderIndex) { CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex]; CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties; decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties); if (!compressSetDecoderProperties) return E_FAIL; CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; CBenchProgressInfo *pi = progressInfoSpec[decoderIndex]; pi->BenchInfo.UnpackSize = 0; pi->BenchInfo.PackSize = 0; for (UInt32 j = 0; j < NumIterations; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos)); UInt64 outSize = kBufferSize; RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex])); if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc) return S_FALSE; pi->BenchInfo.UnpackSize += kBufferSize; pi->BenchInfo.PackSize += compressedSize; } decoder.Release(); return S_OK; } static const UInt32 kNumThreadsMax = (1 << 16); struct CBenchEncoders { CEncoderInfo *encoders; CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; } ~CBenchEncoders() { delete []encoders; } }; HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback) { UInt32 numEncoderThreads = #ifdef BENCH_MT (numThreads > 1 ? numThreads / 2 : 1); #else 1; #endif UInt32 numSubDecoderThreads = #ifdef BENCH_MT (numThreads > 1 ? 2 : 1); #else 1; #endif if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax) { return E_INVALIDARG; } CBenchEncoders encodersSpec(numEncoderThreads); CEncoderInfo *encoders = encodersSpec.encoders; #ifdef EXTERNAL_LZMA UString name = L"LZMA"; #endif UInt32 i; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.callback = (i == 0) ? callback : 0; #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, true, encoder.encoder)); #else encoder.encoder = new NCompress::NLzma::CEncoder; #endif for (UInt32 j = 0; j < numSubDecoderThreads; j++) { #ifdef EXTERNAL_LZMA RINOK(codecs->CreateCoder(name, false, encoder.decoders[j])); #else encoder.decoders[j] = new NCompress::NLzma::CDecoder; #endif } } CBaseRandomGenerator rg; rg.Init(); for (i = 0; i < numEncoderThreads; i++) { RINOK(encoders[i].Init(dictionarySize, numThreads, &rg)); } CBenchProgressStatus status; status.Res = S_OK; status.EncodeMode = true; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; for (int j = 0; j < 2; j++) { encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo; encoder.progressInfoSpec[j]->Status = &status; } if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numEncoderThreads > 1) { #ifdef USE_ALLOCA encoder.AllocaSize = (i * 16 * 21) & 0x7FF; #endif RINOK(encoder.CreateEncoderThread()) } else #endif { RINOK(encoder.Encode()); } } #ifdef BENCH_MT if (numEncoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) encoders[i].thread[0].Wait(); #endif RINOK(status.Res); CBenchInfo info; SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = 1; // progressInfoSpec->NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetEncodeResult(info, true)); status.Res = S_OK; status.EncodeMode = false; UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize; if (i == 0) { encoder.progressInfoSpec[0]->callback = callback; encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads; SetStartTime(encoder.progressInfoSpec[0]->BenchInfo); } #ifdef BENCH_MT if (numDecoderThreads > 1) { for (UInt32 j = 0; j < numSubDecoderThreads; j++) { HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0) #ifdef USE_ALLOCA , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF #endif ); RINOK(res); } } else #endif { RINOK(encoder.Decode(0)); } } #ifdef BENCH_MT HRESULT res = S_OK; if (numDecoderThreads > 1) for (i = 0; i < numEncoderThreads; i++) for (UInt32 j = 0; j < numSubDecoderThreads; j++) { CEncoderInfo &encoder = encoders[i]; encoder.thread[j].Wait(); if (encoder.Results[j] != S_OK) res = encoder.Results[j]; } RINOK(res); #endif RINOK(status.Res); SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info); info.UnpackSize = 0; info.PackSize = 0; info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations; for (i = 0; i < numEncoderThreads; i++) { CEncoderInfo &encoder = encoders[i]; info.UnpackSize += encoder.kBufferSize; info.PackSize += encoder.compressedSize; } RINOK(callback->SetDecodeResult(info, false)); RINOK(callback->SetDecodeResult(info, true)); return S_OK; } inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary) { UInt32 hs = dictionary - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; hs++; return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + (1 << 20) + (multiThread ? (6 << 20) : 0); } UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary) { const UInt32 kBufferSize = dictionary; const UInt32 kCompressedBufferSize = (kBufferSize / 2); UInt32 numSubThreads = (numThreads > 1) ? 2 : 1; UInt32 numBigThreads = numThreads / numSubThreads; return (kBufferSize + kCompressedBufferSize + GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads; } static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase) { for (UInt32 i = 0; i < numCycles; i++) if (CrcCalc(data, size) != crcBase) return false; return true; } #ifdef BENCH_MT struct CCrcInfo { NWindows::CThread Thread; const Byte *Data; UInt32 Size; UInt32 NumCycles; UInt32 Crc; bool Res; void Wait() { Thread.Wait(); Thread.Close(); } }; static THREAD_FUNC_DECL CrcThreadFunction(void *param) { CCrcInfo *p = (CCrcInfo *)param; p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc); return 0; } struct CCrcThreads { UInt32 NumThreads; CCrcInfo *Items; CCrcThreads(): Items(0), NumThreads(0) {} void WaitAll() { for (UInt32 i = 0; i < NumThreads; i++) Items[i].Wait(); NumThreads = 0; } ~CCrcThreads() { WaitAll(); delete []Items; } }; #endif static UInt32 CrcCalc1(const Byte *buf, UInt32 size) { UInt32 crc = CRC_INIT_VAL;; for (UInt32 i = 0; i < size; i++) crc = CRC_UPDATE_BYTE(crc, buf[i]); return CRC_GET_DIGEST(crc); } static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { for (UInt32 i = 0; i < size; i++) buf[i] = (Byte)RG.GetRnd(); } static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG) { RandGen(buf, size, RG); return CrcCalc1(buf, size); } bool CrcInternalTest() { CBenchBuffer buffer; const UInt32 kBufferSize0 = (1 << 8); const UInt32 kBufferSize1 = (1 << 10); const UInt32 kCheckSize = (1 << 5); if (!buffer.Alloc(kBufferSize0 + kBufferSize1)) return false; Byte *buf = buffer.Buffer; UInt32 i; for (i = 0; i < kBufferSize0; i++) buf[i] = (Byte)i; UInt32 crc1 = CrcCalc1(buf, kBufferSize0); if (crc1 != 0x29058C73) return false; CBaseRandomGenerator RG; RandGen(buf + kBufferSize0, kBufferSize1, RG); for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++) for (UInt32 j = 0; j < kCheckSize; j++) if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j)) return false; return true; } HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed) { if (numThreads == 0) numThreads = 1; CBenchBuffer buffer; size_t totalSize = (size_t)bufferSize * numThreads; if (totalSize / numThreads != bufferSize) return E_OUTOFMEMORY; if (!buffer.Alloc(totalSize)) return E_OUTOFMEMORY; Byte *buf = buffer.Buffer; CBaseRandomGenerator RG; UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1; UInt64 timeVal; #ifdef BENCH_MT CCrcThreads threads; if (numThreads > 1) { threads.Items = new CCrcInfo[numThreads]; UInt32 i; for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; Byte *data = buf + (size_t)bufferSize * i; info.Data = data; info.NumCycles = numCycles; info.Size = bufferSize; info.Crc = RandGenCrc(data, bufferSize, RG); } timeVal = GetTimeCount(); for (i = 0; i < numThreads; i++) { CCrcInfo &info = threads.Items[i]; RINOK(info.Thread.Create(CrcThreadFunction, &info)); threads.NumThreads++; } threads.WaitAll(); for (i = 0; i < numThreads; i++) if (!threads.Items[i].Res) return S_FALSE; } else #endif { UInt32 crc = RandGenCrc(buf, bufferSize, RG); timeVal = GetTimeCount(); if (!CrcBig(buf, bufferSize, numCycles, crc)) return S_FALSE; } timeVal = GetTimeCount() - timeVal; if (timeVal == 0) timeVal = 1; UInt64 size = (UInt64)numCycles * totalSize; speed = MyMultDiv64(size, timeVal, GetFreq()); return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LZMABENCH_H #define __LZMABENCH_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif struct CBenchInfo { UInt64 GlobalTime; UInt64 GlobalFreq; UInt64 UserTime; UInt64 UserFreq; UInt64 UnpackSize; UInt64 PackSize; UInt32 NumIterations; CBenchInfo(): NumIterations(0) {} }; struct IBenchCallback { virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0; virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0; }; UInt64 GetUsage(const CBenchInfo &benchOnfo); UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating); UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size); UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations); HRESULT LzmaBench( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback); const int kBenchMinDicLogSize = 18; UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary); bool CrcInternalTest(); HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp ================================================ // LzmaBenchCon.cpp #include "StdAfx.h" #include <stdio.h> #include "LzmaBench.h" #include "LzmaBenchCon.h" #include "../../../Common/IntToString.h" #if defined(BENCH_MT) || defined(_WIN32) #include "../../../Windows/System.h" #endif #ifdef BREAK_HANDLER #include "../../UI/Console/ConsoleClose.h" #endif #include "../../../Common/MyCom.h" struct CTotalBenchRes { UInt64 NumIterations; UInt64 Rating; UInt64 Usage; UInt64 RPU; void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; } void Normalize() { if (NumIterations == 0) return; Rating /= NumIterations; Usage /= NumIterations; RPU /= NumIterations; NumIterations = 1; } void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) { Rating = (r1.Rating + r2.Rating) / 2; Usage = (r1.Usage + r2.Usage) / 2; RPU = (r1.RPU + r2.RPU) / 2; NumIterations = (r1.NumIterations + r2.NumIterations) / 2; } }; struct CBenchCallback: public IBenchCallback { CTotalBenchRes EncodeRes; CTotalBenchRes DecodeRes; FILE *f; void Init() { EncodeRes.Init(); DecodeRes.Init(); } void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); } UInt32 dictionarySize; HRESULT SetEncodeResult(const CBenchInfo &info, bool final); HRESULT SetDecodeResult(const CBenchInfo &info, bool final); }; static void NormalizeVals(UInt64 &v1, UInt64 &v2) { while (v1 > 1000000) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq) { UInt64 elTime = elapsedTime; NormalizeVals(freq, elTime); if (elTime == 0) elTime = 1; return value * freq / elTime; } static void PrintNumber(FILE *f, UInt64 value, int size) { char s[32]; ConvertUInt64ToString(value, s); fprintf(f, " "); for (int len = (int)strlen(s); len < size; len++) fprintf(f, " "); fprintf(f, "%s", s); } static void PrintRating(FILE *f, UInt64 rating) { PrintNumber(f, rating / 1000000, 6); } static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating) { PrintNumber(f, (usage + 5000) / 10000, 5); PrintRating(f, rpu); PrintRating(f, rating); } static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res) { UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq); PrintNumber(f, speed / 1024, 7); UInt64 usage = GetUsage(info); UInt64 rpu = GetRatingPerUsage(info, rating); PrintResults(f, usage, rpu, rating); res.NumIterations++; res.RPU += rpu; res.Rating += rating; res.Usage += usage; } static void PrintTotals(FILE *f, const CTotalBenchRes &res) { fprintf(f, " "); PrintResults(f, res.Usage, res.RPU, res.Rating); } HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize); PrintResults(f, info, rating, EncodeRes); } return S_OK; } static const char *kSep = " | "; HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif if (final) { UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations); fprintf(f, kSep); CBenchInfo info2 = info; info2.UnpackSize *= info2.NumIterations; info2.PackSize *= info2.NumIterations; info2.NumIterations = 1; PrintResults(f, info2, rating, DecodeRes); } return S_OK; } static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads) { fprintf(f, "\nRAM %s ", sizeString); PrintNumber(f, (size >> 20), 5); fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads); } HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); // UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; if (numThreads > 1) numThreads &= ~1; if (dictionary == (UInt32)-1) { int dicSizeLog; for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--) if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize) break; dictionary = (1 << dicSizeLog); } #else if (dictionary == (UInt32)-1) dictionary = (1 << 22); numThreads = 1; #endif PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads); CBenchCallback callback; callback.Init(); callback.f = f; fprintf(f, "\n\nDict Compressing | Decompressing\n "); int j; for (j = 0; j < 2; j++) { fprintf(f, " Speed Usage R/U Rating"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n "); for (j = 0; j < 2; j++) { fprintf(f, " KB/s %% MIPS MIPS"); if (j == 0) fprintf(f, kSep); } fprintf(f, "\n\n"); for (UInt32 i = 0; i < numIterations; i++) { const int kStartDicLog = 22; int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog; while (((UInt32)1 << pow) > dictionary) pow--; for (; ((UInt32)1 << pow) <= dictionary; pow++) { fprintf(f, "%2d:", pow); callback.dictionarySize = (UInt32)1 << pow; HRESULT res = LzmaBench( #ifdef EXTERNAL_LZMA codecs, #endif numThreads, callback.dictionarySize, &callback); fprintf(f, "\n"); RINOK(res); } } callback.Normalize(); fprintf(f, "----------------------------------------------------------------\nAvr:"); PrintTotals(f, callback.EncodeRes); fprintf(f, " "); PrintTotals(f, callback.DecodeRes); fprintf(f, "\nTot:"); CTotalBenchRes midRes; midRes.SetMid(callback.EncodeRes, callback.DecodeRes); PrintTotals(f, midRes); fprintf(f, "\n"); return S_OK; } struct CTempValues { UInt64 *Values; CTempValues(UInt32 num) { Values = new UInt64[num]; } ~CTempValues() { delete []Values; } }; HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary) { if (!CrcInternalTest()) return S_FALSE; #ifdef BENCH_MT UInt64 ramSize = NWindows::NSystem::GetRamSize(); UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors(); PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs); if (numThreads == (UInt32)-1) numThreads = numCPUs; #else numThreads = 1; #endif if (dictionary == (UInt32)-1) dictionary = (1 << 24); CTempValues speedTotals(numThreads); fprintf(f, "\n\nSize"); for (UInt32 ti = 0; ti < numThreads; ti++) { fprintf(f, " %5d", ti + 1); speedTotals.Values[ti] = 0; } fprintf(f, "\n\n"); UInt64 numSteps = 0; for (UInt32 i = 0; i < numIterations; i++) { for (int pow = 10; pow < 32; pow++) { UInt32 bufSize = (UInt32)1 << pow; if (bufSize > dictionary) break; fprintf(f, "%2d: ", pow); UInt64 speed; for (UInt32 ti = 0; ti < numThreads; ti++) { #ifdef BREAK_HANDLER if (NConsoleClose::TestBreakSignal()) return E_ABORT; #endif RINOK(CrcBench(ti + 1, bufSize, speed)); PrintNumber(f, (speed >> 20), 5); speedTotals.Values[ti] += speed; } fprintf(f, "\n"); numSteps++; } } if (numSteps != 0) { fprintf(f, "\nAvg:"); for (UInt32 ti = 0; ti < numThreads; ti++) PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5); fprintf(f, "\n"); } return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h ================================================ // LzmaBenchCon.h #ifndef __LZMABENCHCON_H #define __LZMABENCHCON_H #include <stdio.h> #include "../../../Common/Types.h" #ifdef EXTERNAL_LZMA #include "../../UI/Common/LoadCodecs.h" #endif HRESULT LzmaBenchCon( #ifdef EXTERNAL_LZMA CCodecs *codecs, #endif FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzma_version.h ================================================ #ifndef LZMA_VERSION_H #define LZMA_VERSION_H /* Version and copyright information used by LZMA utils. */ static const char *LZMA_SDK_VERSION_STRING = "4.43"; static const char *LZMA_SDK_COPYRIGHT_STRING = "Copyright (C) 1999-2006 Igor Pavlov"; static const char *LZMA_SDK_COPYRIGHT_INFO = " See http://7-zip.org/sdk.html or the documentation of LZMA SDK for\n" " the license. For reference, the version 4.43 is free software\n" " licensed under the GNU LGPL."; static const char *LZMA_UTILS_VERSION_STRING = PACKAGE_VERSION; static const char *LZMA_UTILS_COPYRIGHT_STRING = "Copyright (C) 2006 Lasse Collin"; static const char *LZMA_UTILS_COPYRIGHT_INFO = "This program comes with ABSOLUTELY NO WARRANTY.\n" "You may redistribute copies of this program\n" "under the terms of the GNU General Public License.\n" "For more information about these matters, see the file " "named COPYING.\n"; #endif /* ifndef LZMA_VERSION_H */ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/lzmp.cpp ================================================ /* * LZMA command line tool similar to gzip to encode and decode LZMA files. * * Copyright (C) 2005 Ville Koskinen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include "../../../Common/MyInitGuid.h" #include <iostream> using std::cout; using std::cerr; using std::endl; #include <cstdio> #include <cstdlib> #include <cstring> #include <string> using std::string; #include <vector> using std::vector; typedef vector<string> stringVector; #include <unistd.h> #include <getopt.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <utime.h> #include <sys/time.h> // futimes() // For Solaris #ifndef HAVE_FUTIMES //#define futimes(fd, tv) futimesat(fd, NULL, tv) #endif #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../7zip/Common/FileStreams.h" #include "../../../Common/Types.h" #include "../../../7zip/Compress/LzmaDecoder.h" #include "../../../7zip/Compress/LzmaEncoder.h" #include "Exception.h" #include "lzma_version.h" namespace lzma { const char *PROGRAM_VERSION = PACKAGE_VERSION; const char *PROGRAM_COPYRIGHT = "Copyright (C) 2006 Ville Koskinen"; /* LZMA_Alone switches: -a{N}: set compression mode - [0, 2], default: 2 (max) -d{N}: set dictionary - [0,28], default: 23 (8MB) -fb{N}: set number of fast bytes - [5, 255], default: 128 -lc{N}: set number of literal context bits - [0, 8], default: 3 -lp{N}: set number of literal pos bits - [0, 4], default: 0 -pb{N}: set number of pos bits - [0, 4], default: 2 -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2, pat2h, pat3h, pat4h, hc3, hc4], default: bt4 */ struct lzma_option { short compression_mode; // -a short dictionary; // -d short fast_bytes; // -fb wchar_t *match_finder; // -mf short literal_context_bits; // -lc short literal_pos_bits; // -lp short pos_bits; // -pb }; /* The following is a mapping from gzip/bzip2 style -1 .. -9 compression modes * to the corresponding LZMA compression modes. Thanks, Larhzu, for coining * these. */ const lzma_option option_mapping[] = { { 0, 0, 0, NULL, 0, 0, 0}, // -0 (needed for indexing) { 0, 16, 64, L"hc4", 3, 0, 2}, // -1 { 0, 20, 64, L"hc4", 3, 0, 2}, // -2 { 1, 19, 64, L"bt4", 3, 0, 2}, // -3 { 2, 20, 64, L"bt4", 3, 0, 2}, // -4 { 2, 21, 128, L"bt4", 3, 0, 2}, // -5 { 2, 22, 128, L"bt4", 3, 0, 2}, // -6 { 2, 23, 128, L"bt4", 3, 0, 2}, // -7 { 2, 24, 255, L"bt4", 3, 0, 2}, // -8 { 2, 25, 255, L"bt4", 3, 0, 2}, // -9 }; struct extension_pair { char *from; char *to; }; const extension_pair known_extensions[] = { { ".lzma", "" }, { ".tlz", ".tar" }, { NULL, NULL } }; /* Sorry, I just happen to like enumerations. */ enum PROGRAM_MODE { PM_COMPRESS = 0, PM_DECOMPRESS, PM_TEST, PM_HELP, PM_LICENSE, PM_VERSION }; enum { STATUS_OK = 0, STATUS_ERROR = 1, STATUS_WARNING = 2 }; /* getopt options. */ /* struct option { name, has_arg, flag, val } */ const struct option long_options[] = { { "stdout", 0, 0, 'c' }, { "decompress", 0, 0, 'd' }, { "compress", 0, 0, 'z' }, { "keep", 0, 0, 'k' }, { "force", 0, 0, 'f' }, { "test", 0, 0, 't' }, { "suffix", 1, 0, 'S' }, { "quiet", 0, 0, 'q' }, { "verbose", 0, 0, 'v' }, { "help", 0, 0, 'h' }, { "license", 0, 0, 'L' }, { "version", 0, 0, 'V' }, { "fast", 0, 0, '1' }, { "best", 0, 0, '9' }, { 0, 0, 0, 0 } }; /* getopt option string (for the above options). */ const char option_string[] = "cdzkftS:qvhLV123456789A:D:F:"; /* Defaults. */ PROGRAM_MODE program_mode = PM_COMPRESS; int verbosity = 0; bool stdinput = false; bool stdoutput = false; bool keep = false; bool force = false; int compression_mode = 7; //char *suffix = strdup(".lzma"); char *suffix = strdup(known_extensions[0].from); lzma_option advanced_options = { -1, -1, -1, NULL, -1, -1, -1 }; void print_help(const char *const argv0) { // Help goes to stdout while other messages go to stderr. cout << "\nlzma " << PROGRAM_VERSION << " " << PROGRAM_COPYRIGHT << "\n" "Based on LZMA SDK " << LZMA_SDK_VERSION_STRING << " " << LZMA_SDK_COPYRIGHT_STRING << "\n\nUsage: " << argv0 << " [flags and input files in any order]\n" " -c --stdout output to standard output\n" " -d --decompress force decompression\n" " -z --compress force compression\n" " -k --keep keep (don't delete) input files\n" " -f --force force overwrite of output file and compress links\n" " -t --test test compressed file integrity\n" " -S .suf --suffix .suf use suffix .suf on compressed files\n" " -q --quiet suppress error messages\n" " -v --verbose be verbose\n" " -h --help print this message\n" " -L --license display the license information\n" " -V --version display version numbers of LZMA SDK and lzma\n" " -1 .. -2 fast compression\n" " -3 .. -9 good to excellent compression. -7 is the default.\n" " --fast alias for -1\n" " --best alias for -9 (usually *not* what you want)\n\n" " Memory usage depends a lot on the chosen compression mode -1 .. -9.\n" " See the man page lzma(1) for details.\n\n"; } void print_license(void) { cout << "\n LZMA command line tool " << PROGRAM_VERSION << " - " << PROGRAM_COPYRIGHT << "\n LZMA SDK " << LZMA_SDK_VERSION_STRING << " - " << LZMA_SDK_COPYRIGHT_STRING << "\n This program is a part of the LZMA utils package.\n" " http://tukaani.org/lzma/\n\n" " This program is free software; you can redistribute it and/or\n" " modify it under the terms of the GNU General Public License\n" " as published by the Free Software Foundation; either version 2\n" " of the License, or (at your option) any later version.\n" "\n" " This program is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n" "\n"; } void print_version(void) { cout << "LZMA command line tool " << PROGRAM_VERSION << "\n" << "LZMA SDK " << LZMA_SDK_VERSION_STRING << "\n"; } short str2int (const char *str, const int &min, const int &max) { int value = -1; char *endptr = NULL; if (str == NULL || str[0] == '\0') throw ArgumentException("Invalid integer option"); value = strtol (str, &endptr, 10); if (*endptr != '\0' || value < min || value > max) throw ArgumentException("Invalid integer option"); return value; } void parse_options(int argc, char **argv, stringVector &filenames) { /* Snatched from getopt(3). */ int c; /* Check how we were called */ { char *p = strrchr (argv[0], '/'); // Remove path prefix, if any if (p++ == NULL) p = argv[0]; if (strstr (p, "un") != NULL) { program_mode = PM_DECOMPRESS; } else if (strstr (p, "cat") != NULL) { program_mode = PM_DECOMPRESS; stdoutput = true; } } while (-1 != (c = getopt_long(argc, argv, option_string, long_options, NULL))) { switch (c) { // stdout case 'c': stdoutput = true; break; // decompress case 'd': program_mode = PM_DECOMPRESS; break; // compress case 'z': program_mode = PM_COMPRESS; break; // keep case 'k': keep = true; break; // force case 'f': force = true; break; // test case 't': program_mode = PM_TEST; break; // suffix case 'S': if (optarg) { free(suffix); suffix = strdup(optarg); } break; // quiet case 'q': verbosity = 0; break; // verbose case 'v': verbosity++; break; // help case 'h': program_mode = PM_HELP; break; // license case 'L': program_mode = PM_LICENSE; break; // version case 'V': program_mode = PM_VERSION; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': compression_mode = c - '0'; break; // Advanced options // // Compression mode case 'A': advanced_options.compression_mode = str2int (optarg, 0, 2); break; // Dictionary size case 'D': advanced_options.dictionary = str2int (optarg, 0, 28); break; // Fast bytes case 'F': advanced_options.fast_bytes = str2int (optarg, 0, 273); break; default: throw ArgumentException(""); break; } // switch(c) } // while(1) for (int i = optind; i < argc; i++) { if (strcmp("-", argv[i]) == 0) continue; filenames.push_back(argv[i]); } } // parse_options void set_encoder_properties(NCompress::NLzma::CEncoder *encoder, lzma_option &opt) { /* Almost verbatim from LzmaAlone.cpp. */ PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); #define VALUE(x) (advanced_options.x >= 0 ? advanced_options.x : opt.x) PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(1 << VALUE (dictionary)); properties[1].ulVal = UInt32(VALUE (pos_bits)); properties[2].ulVal = UInt32(VALUE (literal_context_bits)); properties[3].ulVal = UInt32(VALUE (literal_pos_bits)); properties[4].ulVal = UInt32(VALUE (compression_mode)); properties[5].ulVal = UInt32(VALUE (fast_bytes)); #undef VALUE properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)opt.match_finder; properties[7].vt = VT_BOOL; properties[7].boolVal = stdinput ? VARIANT_TRUE : VARIANT_FALSE; if (encoder->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) throw Exception("SetCoderProperties() error"); } void encode(NCompress::NLzma::CEncoder *encoderSpec, CMyComPtr<ISequentialInStream> inStream, CMyComPtr<ISequentialOutStream> outStream, lzma_option encoder_options, UInt64 fileSize) { set_encoder_properties(encoderSpec, encoder_options); encoderSpec->WriteCoderProperties(outStream); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, sizeof(b), 0) != S_OK) throw Exception("Write error while encoding"); } HRESULT result = encoderSpec->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) throw Exception("Cannot allocate memory"); else if (result != S_OK) { char buffer[33]; snprintf(buffer, 33, "%d", (unsigned int)result); throw Exception(string("Encoder error: ") + buffer); } } void decode(NCompress::NLzma::CDecoder *decoderSpec, CMyComPtr<ISequentialInStream> inStream, CMyComPtr<ISequentialOutStream> outStream) { const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; UInt64 fileSize = 0; if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK) throw Exception("Read error"); if (processedSize != kPropertiesSize) throw Exception("Read error"); if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) throw Exception("SetDecoderProperties() error"); for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK) throw Exception("Read error"); if (processedSize != 1) throw Exception("Read error"); fileSize |= ((UInt64)b) << (8 * i); } if (decoderSpec->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) throw Exception("Decoder error"); } int open_instream(const string infile, CMyComPtr<ISequentialInStream> &inStream, UInt64 &fileSize) { CInFileStream *inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(infile.c_str())) throw Exception("Cannot open input file " + infile); inStreamSpec->File.GetLength(fileSize); return inStreamSpec->File.GetHandle(); } int open_outstream(const string outfile, CMyComPtr<ISequentialOutStream> &outStream) { COutFileStream *outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool open_by_force = (program_mode == PM_TEST) | force; if (!outStreamSpec->Create(outfile.c_str(), open_by_force)) throw Exception("Cannot open output file " + outfile); return outStreamSpec->File.GetHandle(); } double get_ratio(int inhandle, int outhandle) { struct stat in_stats, out_stats; fstat(inhandle, &in_stats); fstat(outhandle, &out_stats); return (double)out_stats.st_size / (double)in_stats.st_size; } mode_t get_file_mode(string filename) { struct stat in_stat; lstat(filename.c_str(), &in_stat); return in_stat.st_mode; } bool string_ends_with(string str, string ending) { return equal(ending.rbegin(), ending.rend(), str.rbegin()); } bool extension_is_known(string filename) { bool known_format = false; extension_pair extension; int i = 1; extension = known_extensions[0]; while (extension.from != NULL) { if (string_ends_with(filename, extension.from)) { known_format = true; break; } extension = known_extensions[i]; i++; } if (!known_format) { if (!string_ends_with(filename, suffix)) { return false; } } return true; } string replace_extension(string filename) { int suffix_starts_at = filename.length() - strlen (suffix); string from_suffix = filename.substr(suffix_starts_at, strlen (suffix)); string ret = filename.substr(0, suffix_starts_at); extension_pair extension; int i = 1; bool found_replacement = false; extension = known_extensions[0]; while (extension.from != NULL) { if (from_suffix.compare(extension.from) == 0) { ret += extension.to; found_replacement = true; break; } extension = known_extensions[i]; i++; } return ret; } string pretty_print_status(string filename, string output_filename, string ratio) { string ret = ""; ret += filename; ret += ":\t "; if (program_mode == PM_TEST) { ret += "decoded succesfully"; return ret; } if (!stdinput && !stdoutput) { ret += ratio; ret += " -- "; } if (program_mode == PM_COMPRESS) { if (keep) { ret += "encoded succesfully"; return ret; } ret += "replaced with "; ret += output_filename; return ret; } if (program_mode == PM_DECOMPRESS) { if (keep) { ret += "decoded succesfully"; return ret; } ret += "replaced with "; ret += output_filename; return ret; } return ret; } static string archive_name; // I know, it is crude, but I haven't found any other // way then making a global variable to transfer filename to handler void signal_handler (int signum) { unlink (archive_name.c_str()); // deleting signal (signum, SIG_DFL); // we return the default function to used signal kill (getpid(), signum); // and then send this signal to the process again } } // namespace lzma int main(int argc, char **argv) { using namespace lzma; using std::cerr; stringVector filenames; signal (SIGTERM,signal_handler); signal (SIGHUP,signal_handler); signal (SIGINT,signal_handler); try { parse_options(argc, argv, filenames); } catch (...) { return STATUS_ERROR; } if (program_mode == PM_HELP) { print_help(argv[0]); return STATUS_OK; } else if (program_mode == PM_LICENSE) { print_license(); return STATUS_OK; } else if (program_mode == PM_VERSION) { print_version(); return STATUS_OK; } if (filenames.empty()) { stdinput = true; stdoutput = true; /* FIXME: get rid of this */ filenames.push_back("-"); } /* Protection: always create new files with 0600 in order to prevent * outsiders from reading incomplete data. */ umask(0077); bool warning = false; for (int i = 0; i < filenames.size(); i++) { CMyComPtr<ISequentialInStream> inStream; CMyComPtr<ISequentialOutStream> outStream; UInt64 fileSize = 0; int inhandle = 0, outhandle = 0; string output_filename; if (stdinput) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); fileSize = (UInt64)(Int64)-1; inhandle = STDIN_FILENO; outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); outhandle = STDOUT_FILENO; } else { mode_t infile_mode = get_file_mode(filenames[i]); if (!S_ISREG(infile_mode)) { if (S_ISDIR(infile_mode)) { warning = true; cerr << argv[0] << ": " << filenames[i] << ": " << "cowardly refusing to work on directory" << endl; continue; } else if (S_ISLNK(infile_mode)) { if (!stdoutput && !force) { warning = true; cerr << argv[0] << ": " << filenames[i] << ": " << "cowardly refusing to work on symbolic link " << "(use --force to force encoding or decoding)" << endl; continue; } } else { warning = true; cerr << argv[0] << ": " << filenames[i] << ": " << "doesn't exist or is not a regular file" << endl; continue; } } // Test if the file already ends with *suffix. if (program_mode == PM_COMPRESS && !force && string_ends_with(filenames[i], suffix)) { warning = true; cerr << filenames[i] << " already has " << suffix << " suffix -- unchanged\n"; continue; } // Test if the file extension is known. if (program_mode == PM_DECOMPRESS && !extension_is_known(filenames[i])) { warning = true; cerr << filenames[i] << ": " << " unknown suffix -- unchanged" << endl; continue; } try { inhandle = open_instream(filenames[i], inStream, fileSize); } catch (Exception e) { cerr << argv[0] << ": " << e.what() << endl; return STATUS_ERROR; } if (stdoutput) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); outhandle = STDOUT_FILENO; } else { /* Testing mode is nothing else but decoding * and throwing away the result. */ if (program_mode == PM_TEST) output_filename = "/dev/null"; else if (program_mode == PM_DECOMPRESS) output_filename = replace_extension(filenames[i]); else output_filename = filenames[i] + suffix; archive_name = output_filename; try { outhandle = open_outstream(output_filename, outStream); } catch (Exception e) { cerr << argv[0] << ": " << e.what() << endl; return STATUS_ERROR; } } } // Unless --force is specified, do not read/write compressed // data from/to a terminal. if (!force) { if (program_mode == PM_COMPRESS && isatty(outhandle)) { cerr << argv[0] << ": compressed data not " "written to a terminal. Use " "-f to force compression.\n" << argv[0] << ": For help, type: " << argv[0] << " -h\n"; return STATUS_ERROR; } else if (program_mode == PM_DECOMPRESS && isatty(inhandle)) { cerr << argv[0] << ": compressed data not " "read from a terminal. Use " "-f to force decompression.\n" << argv[0] << ": For help, type: " << argv[0] << " -h\n"; return STATUS_ERROR; } } if (program_mode == PM_COMPRESS) { NCompress::NLzma::CEncoder *encoderSpec = new NCompress::NLzma::CEncoder; lzma_option options = option_mapping[compression_mode]; try { encode(encoderSpec, inStream, outStream, options, fileSize); } catch (Exception e) { cerr << argv[0] << ": " << e.what() << endl; unlink(output_filename.c_str()); delete(encoderSpec); return STATUS_ERROR; } delete(encoderSpec); } else { // PM_DECOMPRESS | PM_TEST NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; try { decode(decoderSpec, inStream, outStream); } catch (Exception e) { cerr << argv[0] << ": " << e.what() << endl; unlink(output_filename.c_str()); delete(decoderSpec); return STATUS_ERROR; } delete(decoderSpec); } /* Set permissions and owners. */ if ( (program_mode == PM_COMPRESS || program_mode == PM_DECOMPRESS ) && (!stdinput && !stdoutput) ) { int ret = 0; struct stat file_stats; ret = fstat(inhandle, &file_stats); ret = fchmod(outhandle, file_stats.st_mode); ret = fchown(outhandle, file_stats.st_uid, file_stats.st_gid); // We need to call fchmod() again, since otherwise the SUID bits // are lost. ret = fchmod(outhandle, file_stats.st_mode); struct timeval file_times[2]; // Access time file_times[0].tv_sec = file_stats.st_atime; file_times[0].tv_usec = 0; // Modification time file_times[1].tv_sec = file_stats.st_mtime; file_times[1].tv_usec = 0; ret = futimes(outhandle, file_times); if (!keep) unlink(filenames[i].c_str()); } if (verbosity > 0) { if (stdoutput) { cerr << filenames[i] << ":\t "; cerr << "decoded succesfully" << endl; } else { char buf[10] = { 0 }; if (program_mode == PM_DECOMPRESS) snprintf(buf, 10, "%.2f%%", (1 - get_ratio(outhandle, inhandle)) * 100); if (program_mode == PM_COMPRESS) snprintf(buf, 10, "%.2f%%", (1 - get_ratio(inhandle, outhandle)) * 100); string ratio = buf; cerr << pretty_print_status(filenames[i], output_filename, ratio) << endl; } } } if (warning) return STATUS_WARNING; return STATUS_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe LIBS = $(LIBS) user32.lib CFLAGS = $(CFLAGS) \ -DCOMPRESS_MF_MT \ -DBENCH_MT \ LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ LZMA_OPT_OBJS = \ $O\LzmaDecoder.obj \ $O\LzmaEncoder.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj WIN_OBJS = \ $O\System.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ C_OBJS = \ $O\7zCrc.obj \ $O\Alloc.obj \ $O\Bra86.obj \ $O\LzFind.obj \ $O\LzFindMt.obj \ $O\LzmaDec.obj \ $O\LzmaEnc.obj \ $O\Threads.obj \ C_LZMAUTIL_OBJS = \ $O\Lzma86Dec.obj \ $O\Lzma86Enc.obj \ OBJS = \ $O\StdAfx.obj \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(C_OBJS) \ $(C_LZMAUTIL_OBJS) \ $O\FileStreams.obj \ $O\FileIO.obj \ !include "../../../Build.mak" $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) $(C_LZMAUTIL_OBJS): ../../../../C/LzmaUtil/$(*B).c $(COMPL_O2) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma_alone PROG2 = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c -I ../../../ -D_FILE_OFFSET_BITS=64 -DPACKAGE_VERSION="\"4.32.0beta3\"" ifdef SystemDrive IS_MINGW = 1 endif ifdef IS_MINGW FILE_IO =FileIO FILE_IO_2 =Windows/$(FILE_IO) LIB2 = -luuid else FILE_IO =C_FileIO FILE_IO_2 =Common/$(FILE_IO) endif OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaBenchCon.o \ LzmaDecoder.o \ LzmaEncoder.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ $(FILE_IO).o \ CommandLineParser.o \ CRC.o \ IntToString.o \ MyString.o \ StringConvert.o \ StringToInt.o \ MyVector.o \ 7zCrc.o \ Alloc.o \ Bra86.o \ LzFind.o \ LzmaDec.o \ LzmaEnc.o \ Lzma86Dec.o \ Lzma86Enc.o \ OBJS2 = \ C_FileIO.o \ CRC.o \ Alloc.o \ FileStreams.o \ StreamUtils.o \ InBuffer.o \ OutBuffer.o \ LzmaDecoder.o \ StringConvert.o \ StringToInt.o \ LzmaEncoder.o \ LzmaDec.o \ LzmaEnc.o \ LzFind.o \ 7zCrc.o \ lzmp.o all: $(PROG) $(PROG2) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) $(PROG2): $(OBJS2) $(CXX) -o $(PROG2) $(LDFLAGS) $(OBJS2) $(LIB) lzmp.o: lzmp.cpp $(CXX) $(CFLAGS) lzmp.cpp LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaBenchCon.o: LzmaBenchCon.cpp $(CXX) $(CFLAGS) LzmaBenchCon.cpp LzmaDecoder.o: ../LzmaDecoder.cpp $(CXX) $(CFLAGS) ../LzmaDecoder.cpp LzmaEncoder.o: ../LzmaEncoder.cpp $(CXX) $(CFLAGS) ../LzmaEncoder.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp $(FILE_IO).o: ../../../$(FILE_IO_2).cpp $(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp IntToString.o: ../../../Common/IntToString.cpp $(CXX) $(CFLAGS) ../../../Common/IntToString.cpp MyString.o: ../../../Common/MyString.cpp $(CXX) $(CFLAGS) ../../../Common/MyString.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp MyVector.o: ../../../Common/MyVector.cpp $(CXX) $(CFLAGS) ../../../Common/MyVector.cpp 7zCrc.o: ../../../../C/7zCrc.c $(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c Alloc.o: ../../../../C/Alloc.c $(CXX_C) $(CFLAGS) ../../../../C/Alloc.c Bra86.o: ../../../../C/Bra86.c $(CXX_C) $(CFLAGS) ../../../../C/Bra86.c LzFind.o: ../../../../C/LzFind.c $(CXX_C) $(CFLAGS) ../../../../C/LzFind.c LzmaDec.o: ../../../../C/LzmaDec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaDec.c LzmaEnc.o: ../../../../C/LzmaEnc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaEnc.c Lzma86Dec.o: ../../../../C/LzmaUtil/Lzma86Dec.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Dec.c Lzma86Enc.o: ../../../../C/LzmaUtil/Lzma86Enc.c $(CXX_C) $(CFLAGS) ../../../../C/LzmaUtil/Lzma86Enc.c clean: -$(RM) $(PROG) $(PROG2) $(OBJS) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LzmaDecoder.cpp ================================================ // LzmaDecoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaDecoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; // case SZ_ERROR_PROGRESS: return E_ABORT; case SZ_ERROR_DATA: return S_FALSE; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kInBufSize = 1 << 20; CDecoder::CDecoder(): _inBuf(0), _outSizeDefined(false), FinishStream(false) { LzmaDec_Construct(&_state); } static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CDecoder::~CDecoder() { LzmaDec_Free(&_state, &g_Alloc); MyFree(_inBuf); } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) { RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); if (_inBuf == 0) { _inBuf = (Byte *)MyAlloc(kInBufSize); if (_inBuf == 0) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); if (_outSizeDefined) _outSize = *outSize; LzmaDec_Init(&_state); _inPos = _inSize = 0; _inSizeProcessed = _outSizeProcessed = 0; return S_OK; } STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.dicPos; SizeT curSize = _state.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.dicPos == _state.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.dic, _state.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.dicPos == _state.dicBufSize) _state.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } } #ifndef NO_READ_FROM_CODER STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; } #endif }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LzmaDecoder.h ================================================ // LzmaDecoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H extern "C" { #include "../../../C/LzmaDec.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, public ICompressGetInStreamProcessedSize, #ifndef NO_READ_FROM_CODER public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CMyComPtr<ISequentialInStream> _inStream; Byte *_inBuf; UInt32 _inPos; UInt32 _inSize; CLzmaDec _state; bool _outSizeDefined; UInt64 _outSize; UInt64 _inSizeProcessed; UInt64 _outSizeProcessed; public: #ifndef NO_READ_FROM_CODER MY_UNKNOWN_IMP5( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP2( ICompressSetDecoderProperties2, ICompressGetInStreamProcessedSize) #endif STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifndef NO_READ_FROM_CODER STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif bool FinishStream; CDecoder(); virtual ~CDecoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LzmaEncoder.cpp ================================================ // LzmaEncoder.cpp #include "StdAfx.h" extern "C" { #include "../../../C/Alloc.h" } #include "../Common/StreamUtils.h" #include "LzmaEncoder.h" static HRESULT SResToHRESULT(SRes res) { switch(res) { case SZ_OK: return S_OK; case SZ_ERROR_MEM: return E_OUTOFMEMORY; case SZ_ERROR_PARAM: return E_INVALIDARG; // case SZ_ERROR_THREAD: return E_FAIL; } return E_FAIL; } namespace NCompress { namespace NLzma { static const UInt32 kStreamStepSize = (UInt32)1 << 31; static SRes MyRead(void *object, void *data, size_t *size) { UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize); HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize); *size = curSize; return (SRes)res; } static size_t MyWrite(void *object, const void *data, size_t size) { CSeqOutStream *p = (CSeqOutStream *)object; p->Res = WriteStream(p->RealStream, data, size); if (p->Res != 0) return 0; return size; } static void *SzBigAlloc(void *, size_t size) { return BigAlloc(size); } static void SzBigFree(void *, void *address) { BigFree(address); } static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; static void *SzAlloc(void *, size_t size) { return MyAlloc(size); } static void SzFree(void *, void *address) { MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CEncoder::CEncoder() { _seqInStream.SeqInStream.Read = MyRead; _seqOutStream.SeqOutStream.Write = MyWrite; _encoder = 0; _encoder = LzmaEnc_Create(&g_Alloc); if (_encoder == 0) throw 1; } CEncoder::~CEncoder() { if (_encoder != 0) LzmaEnc_Destroy(_encoder, &g_Alloc, &g_BigAlloc); } inline wchar_t GetUpperChar(wchar_t c) { if (c >= 'a' && c <= 'z') c -= 0x20; return c; } static int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) { wchar_t c = GetUpperChar(*s++); if (c == L'H') { if (GetUpperChar(*s++) != L'C') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 4 || numHashBytesLoc > 4) return 0; if (*s++ != 0) return 0; *btMode = 0; *numHashBytes = numHashBytesLoc; return 1; } if (c != L'B') return 0; if (GetUpperChar(*s++) != L'T') return 0; int numHashBytesLoc = (int)(*s++ - L'0'); if (numHashBytesLoc < 2 || numHashBytesLoc > 4) return 0; c = GetUpperChar(*s++); if (c != L'\0') return 0; *btMode = 1; *numHashBytes = numHashBytesLoc; return 1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { CLzmaEncProps props; LzmaEncProps_Init(&props); for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; switch (propIDs[i]) { case NCoderPropID::kNumFastBytes: if (prop.vt != VT_UI4) return E_INVALIDARG; props.fb = prop.ulVal; break; case NCoderPropID::kMatchFinderCycles: if (prop.vt != VT_UI4) return E_INVALIDARG; props.mc = prop.ulVal; break; case NCoderPropID::kAlgorithm: if (prop.vt != VT_UI4) return E_INVALIDARG; props.algo = prop.ulVal; break; case NCoderPropID::kDictionarySize: if (prop.vt != VT_UI4) return E_INVALIDARG; props.dictSize = prop.ulVal; break; case NCoderPropID::kPosStateBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.pb = prop.ulVal; break; case NCoderPropID::kLitPosBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lp = prop.ulVal; break; case NCoderPropID::kLitContextBits: if (prop.vt != VT_UI4) return E_INVALIDARG; props.lc = prop.ulVal; break; case NCoderPropID::kNumThreads: if (prop.vt != VT_UI4) return E_INVALIDARG; props.numThreads = prop.ulVal; break; case NCoderPropID::kMultiThread: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.numThreads = ((prop.boolVal == VARIANT_TRUE) ? 2 : 1); break; case NCoderPropID::kEndMarker: if (prop.vt != VT_BOOL) return E_INVALIDARG; props.writeEndMark = (prop.boolVal == VARIANT_TRUE); break; case NCoderPropID::kMatchFinder: if (prop.vt != VT_BSTR) return E_INVALIDARG; if (!ParseMatchFinder(prop.bstrVal, &props.btMode, &props.numHashBytes /* , &_matchFinderBase.skipModeBits */)) return E_INVALIDARG; break; default: return E_INVALIDARG; } } return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { Byte props[LZMA_PROPS_SIZE]; size_t size = LZMA_PROPS_SIZE; RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)); return WriteStream(outStream, props, size); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _seqOutStream.RealStream = outStream; _seqOutStream.Res = S_OK; return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _seqOutStream.RealStream.Release(); return S_OK; } typedef struct _CCompressProgressImp { ICompressProgress p; ICompressProgressInfo *Progress; HRESULT Res; } CCompressProgressImp; #define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1) #define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x) SRes CompressProgress(void *pp, UInt64 inSize, UInt64 outSize) { CCompressProgressImp *p = (CCompressProgressImp *)pp; p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize)); return (SRes)p->Res; } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { CCompressProgressImp progressImp; progressImp.p.Progress = CompressProgress; progressImp.Progress = progress; progressImp.Res = SZ_OK; _seqInStream.RealStream = inStream; SetOutStream(outStream); SRes res = LzmaEnc_Encode(_encoder, &_seqOutStream.SeqOutStream, &_seqInStream.SeqInStream, progress ? &progressImp.p : NULL, &g_Alloc, &g_BigAlloc); ReleaseOutStream(); if (res == SZ_ERROR_WRITE && _seqOutStream.Res != S_OK) return _seqOutStream.Res; if (res == SZ_ERROR_PROGRESS && progressImp.Res != S_OK) return progressImp.Res; return SResToHRESULT(res); } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LzmaEncoder.h ================================================ // LzmaEncoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H extern "C" { #include "../../../C/LzmaEnc.h" } #include "../../Common/MyCom.h" #include "../ICoder.h" namespace NCompress { namespace NLzma { struct CSeqInStream { ISeqInStream SeqInStream; ISequentialInStream *RealStream; }; struct CSeqOutStream { ISeqOutStream SeqOutStream; CMyComPtr<ISequentialOutStream> RealStream; HRESULT Res; }; class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CMyUnknownImp { CLzmaEncHandle _encoder; CSeqInStream _seqInStream; CSeqOutStream _seqOutStream; public: CEncoder(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder(); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/LzmaRegister.cpp ================================================ // LzmaRegister.cpp #include "StdAfx.h" #include "../Common/RegisterCodec.h" #include "LzmaDecoder.h" static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CDecoder); } #ifndef EXTRACT_ONLY #include "LzmaEncoder.h" static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLzma::CEncoder); } #else #define CreateCodecOut 0 #endif static CCodecInfo g_CodecInfo = { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false }; REGISTER_CODEC(LZMA) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/RangeCoder.h ================================================ // Compress/RangeCoder.h #ifndef __COMPRESS_RANGE_CODER_H #define __COMPRESS_RANGE_CODER_H #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numBits) { for (numBits--; numBits >= 0; numBits--) { Range >>= 1; Low += Range & (0 - ((value >> numBits) & 1)); if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/RangeCoderBit.h ================================================ // Compress/RangeCoderBit.h #ifndef __COMPRESS_RANGE_CODER_BIT_H #define __COMPRESS_RANGE_CODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 4; const int kNumBitPriceShiftBits = 4; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; extern UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return ProbPrices[(this->Prob ^ ((-(int)symbol)) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return ProbPrices[(this->Prob ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/Compress/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kBlockSize, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kMatchFinderCycles, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kNumThreads, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetCoderMt, 0x25) { STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICompressCodecsInfo, 0x60) { STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; }; CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) { STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; /* CODER_INTERFACE(ICryptoResetSalt, 0x88) { STDMETHOD(ResetSalt)() PURE; }; */ CODER_INTERFACE(ICryptoResetInitVector, 0x8C) { STDMETHOD(ResetInitVector)() PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription, kDecoderIsAssigned, kEncoderIsAssigned }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/IDecl.h ================================================ // IDecl.h #ifndef __IDECL_H #define __IDECL_H #include "../Common/MyUnknown.h" #define DECL_INTERFACE_SUB(i, base, groupId, subId) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ struct i: public base #define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/IPassword.h ================================================ // IPassword.h #ifndef __IPASSWORD_H #define __IPASSWORD_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) { STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; }; PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) { STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/IProgress.h ================================================ // Interface/IProgress.h #ifndef __IPROGRESS_H #define __IPROGRESS_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define INTERFACE_IProgress(x) \ STDMETHOD(SetTotal)(UInt64 total) x; \ STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ DECL_INTERFACE(IProgress, 0, 5) { INTERFACE_IProgress(PURE) }; /* // {23170F69-40C1-278A-0000-000000050002} DEFINE_GUID(IID_IProgress2, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") IProgress2: public IUnknown { public: STDMETHOD(SetTotal)(const UInt64 *total) PURE; STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; }; */ #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" #include "IDecl.h" #define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/MyVersion.h ================================================ #define MY_VER_MAJOR 4 #define MY_VER_MINOR 65 #define MY_VER_BUILD 0 #define MY_VERSION "4.65" #define MY_7ZIP_VERSION "7-Zip 4.65" #define MY_DATE "2009-02-03" #define MY_COPYRIGHT "Copyright (c) 1999-2009 Igor Pavlov" #define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/MyVersionInfo.rc ================================================ #include <WinVer.h> #include "MyVersion.h" #define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 #ifdef DEBUG #define DBG_FL VS_FF_DEBUG #else #define DBG_FL 0 #endif #define MY_VERSION_INFO(fileType, descr, intName, origName) \ LANGUAGE 9, 1 \ 1 VERSIONINFO \ FILEVERSION MY_VER \ PRODUCTVERSION MY_VER \ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \ FILEFLAGS DBG_FL \ FILEOS VOS_NT_WINDOWS32 \ FILETYPE fileType \ FILESUBTYPE 0x0L \ BEGIN \ BLOCK "StringFileInfo" \ BEGIN \ BLOCK "040904b0" \ BEGIN \ VALUE "CompanyName", "Igor Pavlov" \ VALUE "FileDescription", descr \ VALUE "FileVersion", MY_VERSION \ VALUE "InternalName", intName \ VALUE "LegalCopyright", MY_COPYRIGHT \ VALUE "OriginalFilename", origName \ VALUE "ProductName", "7-Zip" \ VALUE "ProductVersion", MY_VERSION \ END \ END \ BLOCK "VarFileInfo" \ BEGIN \ VALUE "Translation", 0x409, 1200 \ END \ END #define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe") #define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll") ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/PropID.h ================================================ // PropID.h #ifndef __7ZIP_PROPID_H #define __7ZIP_PROPID_H enum { kpidNoProperty = 0, kpidHandlerItemIndex = 2, kpidPath, kpidName, kpidExtension, kpidIsDir, kpidSize, kpidPackSize, kpidAttrib, kpidCTime, kpidATime, kpidMTime, kpidSolid, kpidCommented, kpidEncrypted, kpidSplitBefore, kpidSplitAfter, kpidDictionarySize, kpidCRC, kpidType, kpidIsAnti, kpidMethod, kpidHostOS, kpidFileSystem, kpidUser, kpidGroup, kpidBlock, kpidComment, kpidPosition, kpidPrefix, kpidNumSubDirs, kpidNumSubFiles, kpidUnpackVer, kpidVolume, kpidIsVolume, kpidOffset, kpidLinks, kpidNumBlocks, kpidNumVolumes, kpidTimeType, kpidBit64, kpidBigEndian, kpidCpu, kpidPhySize, kpidHeadersSize, kpidChecksum, kpidCharacts, kpidVa, kpidTotalSize = 0x1100, kpidFreeSpace, kpidClusterSize, kpidVolumeName, kpidLocalName = 0x1200, kpidProvider, kpidUserDefined = 0x10000 }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/Client7z.cpp ================================================ // Client7z.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyInitGuid.h" #include "Common/StringConvert.h" #include "Windows/DLL.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FileStreams.h" #include "../../Archive/IArchive.h" #include "../../IPassword.h" #include "../../MyVersion.h" // use another CLSIDs, if you want to support other formats (zip, rar, ...). // {23170F69-40C1-278A-1000-000110070000} DEFINE_GUID(CLSID_CFormat7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); using namespace NWindows; #define kDllName "7z.dll" static const char *kCopyrightString = MY_7ZIP_VERSION " (" kDllName " client) " MY_COPYRIGHT " " MY_DATE; static const char *kHelpString = "Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n" "Examples:\n" " Client7z.exe a archive.7z f1.txt f2.txt : compress two files to archive.7z\n" " Client7z.exe l archive.7z : List contents of archive.7z\n" " Client7z.exe x archive.7z : eXtract files from archive.7z\n"; typedef UINT32 (WINAPI * CreateObjectFunc)( const GUID *clsID, const GUID *interfaceID, void **outObject); #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif void PrintString(const UString &s) { printf("%s", (LPCSTR)GetOemString(s)); } void PrintString(const AString &s) { printf("%s", (LPCSTR)s); } void PrintNewLine() { PrintString("\n"); } void PrintStringLn(const AString &s) { PrintString(s); PrintNewLine(); } void PrintError(const AString &s) { PrintNewLine(); PrintString(s); PrintNewLine(); } static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } static const wchar_t *kEmptyFileAlias = L"[Content]"; ////////////////////////////////////////////////////////////// // Archive Open callback class class CArchiveOpenCallback: public IArchiveOpenCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; CArchiveOpenCallback() : PasswordIsDefined(false) {} }; STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */) { return S_OK; } STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Extracting callback class static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; static const char *kTestingString = "Testing "; static const char *kExtractingString = "Extracting "; static const char *kSkippingString = "Skipping "; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCRCFailed = "CRC Failed"; static const char *kDataError = "Data Error"; static const char *kUnknownError = "Unknown Error"; class CArchiveExtractCallback: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { public: MY_UNKNOWN_IMP1(ICryptoGetTextPassword) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IArchiveExtractCallback STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); STDMETHOD(PrepareOperation)(Int32 askExtractMode); STDMETHOD(SetOperationResult)(Int32 resultEOperationResult); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; UString _directoryPath; // Output directory UString _filePath; // name inside arcvhive UString _diskFilePath; // full path to file on disk bool _extractMode; struct CProcessedFileInfo { FILETIME MTime; UInt32 Attrib; bool isDir; bool AttribDefined; bool MTimeDefined; } _processedFileInfo; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; UString Password; CArchiveExtractCallback() : PasswordIsDefined(false) {} }; void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath) { NumErrors = 0; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (NFile::NFind::FindFile(fullProcessedPath, fi)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; break; }; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: PrintString(kExtractingString); break; case NArchive::NExtract::NAskMode::kTest: PrintString(kTestingString); break; case NArchive::NExtract::NAskMode::kSkip: PrintString(kSkippingString); break; }; PrintString(_filePath); return S_OK; } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumErrors++; PrintString(" "); switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: PrintString(kUnsupportedMethod); break; case NArchive::NExtract::NOperationResult::kCRCError: PrintString(kCRCFailed); break; case NArchive::NExtract::NOperationResult::kDataError: PrintString(kDataError); break; default: PrintString(kUnknownError); } } } if (_outFileStream != NULL) { if (_processedFileInfo.MTimeDefined) _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime); RINOK(_outFileStreamSpec->Close()); } _outFileStream.Release(); if (_extractMode && _processedFileInfo.AttribDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib); PrintNewLine(); return S_OK; } STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////// // Archive Creating callback class struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UString FullPath; UInt32 Attrib; bool isDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) // IProgress STDMETHOD(SetTotal)(UInt64 size); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IUpdateCallback2 STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator); STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); STDMETHOD(SetOperationResult)(Int32 operationResult); STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size); STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream); STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; UString DirPrefix; const CObjectVector<CDirItem> *DirItems; bool PasswordIsDefined; UString Password; bool AskPassword; bool m_NeedBeClosed; UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {}; ~CArchiveUpdateCallback() { Finilize(); } HRESULT Finilize(); void Init(const CObjectVector<CDirItem> *dirItems) { DirItems = dirItems; m_NeedBeClosed = false; FailedFiles.Clear(); FailedCodes.Clear(); } }; STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */) { return S_OK; } STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */) { return E_NOTIMPL; } STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) { if (newData != NULL) *newData = BoolToInt(true); if (newProperties != NULL) *newProperties = BoolToInt(true); if (indexInArchive != NULL) *indexInArchive = (UInt32)-1; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = false; prop.Detach(value); return S_OK; } { const CDirItem &dirItem = (*DirItems)[index]; switch(propID) { case kpidPath: prop = dirItem.Name; break; case kpidIsDir: prop = dirItem.isDir(); break; case kpidSize: prop = dirItem.Size; break; case kpidAttrib: prop = dirItem.Attrib; break; case kpidCTime: prop = dirItem.CTime; break; case kpidATime: prop = dirItem.ATime; break; case kpidMTime: prop = dirItem.MTime; break; } } prop.Detach(value); return S_OK; } HRESULT CArchiveUpdateCallback::Finilize() { if (m_NeedBeClosed) { PrintNewLine(); m_NeedBeClosed = false; } return S_OK; } static void GetStream2(const wchar_t *name) { PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; PrintString(name); } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { RINOK(Finilize()); const CDirItem &dirItem = (*DirItems)[index]; GetStream2(dirItem.Name); if (dirItem.isDir()) return S_OK; { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); UString path = DirPrefix + dirItem.FullPath; if (!inStreamSpec->Open(path)) { DWORD sysError = ::GetLastError(); FailedCodes.Add(sysError); FailedFiles.Add(path); // if (systemError == ERROR_SHARING_VIOLATION) { PrintNewLine(); PrintError("WARNING: can't open file"); // PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return sysError; } *inStream = inStreamLoc.Detach(); } return S_OK; } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */) { m_NeedBeClosed = true; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { if (!PasswordIsDefined) { if (AskPassword) { // You can ask real password here from user // Password = GetPassword(OutStream); // PasswordIsDefined = true; PrintError("Password is not defined"); return E_ABORT; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); } ////////////////////////////////////////////////////////////////////////// // Main function int MY_CDECL main(int argc, char* argv[]) { #ifdef _WIN32 #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #endif PrintStringLn(kCopyrightString); if (argc < 3) { PrintStringLn(kHelpString); return 1; } NWindows::NDLL::CLibrary library; if (!library.Load(TEXT(kDllName))) { PrintError("Can not load library"); return 1; } CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject"); if (createObjectFunc == 0) { PrintError("Can not get CreateObject"); return 1; } AString command = argv[1]; command.MakeLower(); UString archiveName = GetUnicodeString(argv[2], CP_OEMCP); if (command.Compare("a") == 0) { // create archive command if (argc < 4) { PrintStringLn(kHelpString); return 1; } CObjectVector<CDirItem> dirItems; int i; for (i = 3; i < argc; i++) { CDirItem di; UString name = GetUnicodeString(argv[i], CP_OEMCP); NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(name, fi)) { PrintString(UString(L"Can't find file") + name); return 1; } di.Attrib = fi.Attrib; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Name = name; di.FullPath = name; dirItems.Add(di); } COutFileStream *outFileStreamSpec = new COutFileStream; CMyComPtr<IOutStream> outFileStream = outFileStreamSpec; if (!outFileStreamSpec->Create(archiveName, false)) { PrintError("can't create archive file"); return 1; } CMyComPtr<IOutArchive> outArchive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK) { PrintError("Can not get class object"); return 1; } CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec); updateCallbackSpec->Init(&dirItems); // updateCallbackSpec->PasswordIsDefined = true; // updateCallbackSpec->Password = L"1"; HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback); updateCallbackSpec->Finilize(); if (result != S_OK) { PrintError("Update Error"); return 1; } for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++) { PrintNewLine(); PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]); } if (updateCallbackSpec->FailedFiles.Size() != 0) return 1; } else { if (argc != 3) { PrintStringLn(kHelpString); return 1; } bool listCommand; if (command.Compare("l") == 0) listCommand = true; else if (command.Compare("x") == 0) listCommand = false; else { PrintError("incorrect command"); return 1; } CMyComPtr<IInArchive> archive; if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK) { PrintError("Can not get class object"); return 1; } CInFileStream *fileSpec = new CInFileStream; CMyComPtr<IInStream> file = fileSpec; if (!fileSpec->Open(archiveName)) { PrintError("Can not open archive file"); return 1; } { CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback; CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec); openCallbackSpec->PasswordIsDefined = false; // openCallbackSpec->PasswordIsDefined = true; // openCallbackSpec->Password = L"1"; if (archive->Open(file, 0, openCallback) != S_OK) { PrintError("Can not open archive"); return 1; } } if (listCommand) { // List command UInt32 numItems = 0; archive->GetNumberOfItems(&numItems); for (UInt32 i = 0; i < numItems; i++) { { // Get uncompressed size of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidSize, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); PrintString(" "); } { // Get name of file NWindows::NCOM::CPropVariant prop; archive->GetProperty(i, kpidPath, &prop); UString s = ConvertPropVariantToString(prop); PrintString(s); } PrintString("\n"); } } else { // Extract command CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec); extractCallbackSpec->Init(archive, L""); // second parameter is output folder path extractCallbackSpec->PasswordIsDefined = false; // extractCallbackSpec->PasswordIsDefined = true; // extractCallbackSpec->Password = L"1"; HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); if (result != S_OK) { PrintError("Extract Error"); return 1; } } } return 0; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/Client7z.dsp ================================================ # Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=Client7z - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "Client7z.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "Client7z - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "Client7z - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "Client7z - Win32 Release" # Name "Client7z - Win32 Debug" # Begin Group "Spec" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\DLL.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\DLL.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileDir.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileFind.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileName.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariant.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\PropVariantConversions.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\IntToString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\IntToString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyString.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\MyVector.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Wildcard.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # End Group # Begin Source File SOURCE=.\Client7z.cpp # End Source File # End Target # End Project ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/Client7z.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "Client7z"=.\Client7z.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include <windows.h> #include <stdio.h> #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Client7z/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ CONSOLE_OBJS = \ $O\Client7z.obj \ COMMON_OBJS = \ $O\IntToString.obj \ $O\NewHandler.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ 7ZIP_COMMON_OBJS = \ $O\FileStreams.obj \ OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveCommandLine.cpp ================================================ // ArchiveCommandLine.cpp #include "StdAfx.h" #ifdef _WIN32 #include <io.h> #endif #include <stdio.h> #include "Common/ListFileUtils.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" #include "UpdateAction.h" #include "Update.h" #include "SortUtils.h" #include "EnumDirItems.h" extern bool g_CaseSensitive; #if _MSC_VER >= 1400 #define MY_isatty_fileno(x) _isatty(_fileno(x)) #else #define MY_isatty_fileno(x) isatty(fileno(x)) #endif #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, #ifndef _NO_CRYPTO kPassword, #endif kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kLargePages, kCharSet, kTechMode, kShareForWrite, kCaseSensitive }; } static const wchar_t kRecursedIDChar = 'R'; static const wchar_t *kRecursedPostCharSet = L"0-"; namespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 }; } static const char kImmediateNameID = '!'; static const char kMapNameID = '#'; static const char kFileListID = '@'; static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be static const wchar_t *kOverwritePostCharSet = L"asut"; NExtract::NOverwriteMode::EEnum k_OverwriteModes[] = { NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting }; static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"-HELP", NSwitchType::kSimple, false }, { L"BA", NSwitchType::kSimple, false }, { L"BD", NSwitchType::kSimple, false }, { L"T", NSwitchType::kUnLimitedPostString, false, 1 }, { L"Y", NSwitchType::kSimple, false }, #ifndef _NO_CRYPTO { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, #endif { L"M", NSwitchType::kUnLimitedPostString, true, 1 }, { L"O", NSwitchType::kUnLimitedPostString, false, 1 }, { L"W", NSwitchType::kUnLimitedPostString, false, 0 }, { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize}, { L"AN", NSwitchType::kSimple, false }, { L"U", NSwitchType::kUnLimitedPostString, true, 1}, { L"V", NSwitchType::kUnLimitedPostString, true, 1}, { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet }, { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SI", NSwitchType::kUnLimitedPostString, false, 0 }, { L"SO", NSwitchType::kSimple, false, 0 }, { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet}, { L"SEML", NSwitchType::kUnLimitedPostString, false, 0}, { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } }; static const CCommandForm g_CommandForms[] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }, { L"B", false }, { L"I", false } }; static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]); static const wchar_t *kUniversalWildcard = L"*"; static const int kMinNonSwitchWords = 1; static const int kCommandIndex = 0; // --------------------------- // exception messages static const char *kUserErrorMessage = "Incorrect command line"; static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch."; static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile"; static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line"; static const char *kTerminalOutError = "I won't write compressed data to a terminal"; static const char *kSameTerminalError = "I won't write data and program's messages to same terminal"; static void ThrowException(const char *errorMessage) { throw CArchiveCommandLineException(errorMessage); }; static void ThrowUserErrorException() { ThrowException(kUserErrorMessage); }; // --------------------------- bool CArchiveCommand::IsFromExtractGroup() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; } } NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const { switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; } } bool CArchiveCommand::IsFromUpdateGroup() const { return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete); } static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) { switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; } } static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command) { UString commandStringUpper = commandString; commandStringUpper.MakeUpper(); UString postString; int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, postString) ; if (commandIndex < 0) return false; command.CommandType = (NCommandType::EEnum)commandIndex; return true; } // ------------------------------------------------------------------ // filenames functions static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type) { bool isWildCard = DoesNameContainWildCard(name); bool recursed = false; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage) { UStringVector names; if (!ReadNamesFromListFile(fileName, names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile; } static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType) { if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine; } static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage) { if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for (int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); } } #ifdef _WIN32 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType) { int splitPos = switchParam.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) ThrowUserErrorException(); UString mappingSize = switchParam2.Left(splitPos); UString eventName = switchParam2.Mid(splitPos + 1); UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL); UInt32 dataSize = (UInt32)dataSize64; { CFileMapping fileMapping; if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName))) ThrowException("Can not open mapping"); LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) ThrowException("MapViewOfFile error"); try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) ThrowException("Incorrect mapping data"); UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) ThrowException("data error"); } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CManualResetEvent event; if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK) event.Set(); } } #endif static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage) { for (int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) ThrowUserErrorException(); if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) ThrowUserErrorException(); UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else ThrowUserErrorException(); } } #ifdef _WIN32 // This code converts all short file names to long file names. static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) { for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); } } static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node) { ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].Name); // mix folders with same name for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode1 = node.SubNodes[i]; for (int j = i + 1; j < node.SubNodes.Size();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); } } static void ConvertToLongNames(NWildcard::CCensor &censor) { for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); } } #endif static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i) { switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603; } const UString kUpdatePairStateIDSet = L"PQRXYZW"; const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1}; const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString) { for (int i = 0; i < command.Length();) { wchar_t c = MyCharUpper(command[i]); int statePos = kUpdatePairStateIDSet.Find(c); if (statePos < 0) { postString = command.Mid(i); return true; } i++; if (i >= command.Length()) return false; int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i])); if (actionPos < 0) return false; actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos); if (kUpdatePairStateNotSupportedActions[statePos] == actionPos) return false; i++; } postString.Empty(); return true; } static void ParseUpdateCommandString(CUpdateOptions &options, const UStringVector &updatePostStrings, const NUpdateArchive::CActionSet &defaultActionSet) { for (int i = 0; i < updatePostStrings.Size(); i++) { const UString &updateString = updatePostStrings[i]; if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0) { if (options.UpdateArchiveItself) { options.UpdateArchiveItself = false; options.Commands.Delete(0); } } else { NUpdateArchive::CActionSet actionSet = defaultActionSet; UString postString; if (!ParseUpdateCommandString2(updateString, actionSet, postString)) ThrowUserErrorException(); if (postString.IsEmpty()) { if (options.UpdateArchiveItself) options.Commands[0].ActionSet = actionSet; } else { if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID) ThrowUserErrorException(); CUpdateArchiveCommand uc; UString archivePath = postString.Mid(1); if (archivePath.IsEmpty()) ThrowUserErrorException(); uc.UserArchivePath = archivePath; uc.ActionSet = actionSet; options.Commands.Add(uc); } } } } static const char kByteSymbol = 'B'; static const char kKiloSymbol = 'K'; static const char kMegaSymbol = 'M'; static const char kGigaSymbol = 'G'; static bool ParseComplexSize(const UString &src, UInt64 &result) { UString s = src; s.MakeUpper(); const wchar_t *start = s; const wchar_t *end; UInt64 number = ConvertStringToUInt64(start, &end); int numDigits = (int)(end - start); if (numDigits == 0 || s.Length() > numDigits + 1) return false; if (s.Length() == numDigits) { result = number; return true; } int numBits; switch (s[numDigits]) { case kByteSymbol: result = number; return true; case kKiloSymbol: numBits = 10; break; case kMegaSymbol: numBits = 20; break; case kGigaSymbol: numBits = 30; break; default: return false; } if (number >= ((UInt64)1 << (64 - numBits))) return false; result = number << numBits; return true; } static void SetAddCommandOptions( NCommandType::EEnum commandType, const CParser &parser, CUpdateOptions &options) { NUpdateArchive::CActionSet defaultActionSet; switch(commandType) { case NCommandType::kAdd: defaultActionSet = NUpdateArchive::kAddActionSet; break; case NCommandType::kDelete: defaultActionSet = NUpdateArchive::kDeleteActionSet; break; default: defaultActionSet = NUpdateArchive::kUpdateActionSet; } options.UpdateArchiveItself = true; options.Commands.Clear(); CUpdateArchiveCommand updateMainCommand; updateMainCommand.ActionSet = defaultActionSet; options.Commands.Add(updateMainCommand); if (parser[NKey::kUpdate].ThereIs) ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, defaultActionSet); if (parser[NKey::kWorkingDir].ThereIs) { const UString &postString = parser[NKey::kWorkingDir].PostStrings[0]; if (postString.IsEmpty()) NDirectory::MyGetTempPath(options.WorkingDir); else options.WorkingDir = postString; } options.SfxMode = parser[NKey::kSfx].ThereIs; if (options.SfxMode) options.SfxModule = parser[NKey::kSfx].PostStrings[0]; if (parser[NKey::kVolume].ThereIs) { const UStringVector &sv = parser[NKey::kVolume].PostStrings; for (int i = 0; i < sv.Size(); i++) { UInt64 size; if (!ParseComplexSize(sv[i], size)) ThrowException("Incorrect volume size"); options.VolumesSizes.Add(size); } } } static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties) { if (parser[NKey::kProperty].ThereIs) { // options.MethodMode.Properties.Clear(); for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { CProperty property; const UString &postString = parser[NKey::kProperty].PostStrings[i]; int index = postString.Find(L'='); if (index < 0) property.Name = postString; else { property.Name = postString.Left(index); property.Value = postString.Mid(index + 1); } properties.Add(property); } } } CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {} void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options) { try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { ThrowUserErrorException(); } options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; #ifdef _WIN32 options.LargePages = false; if (parser[NKey::kLargePages].ThereIs) { const UString &postString = parser[NKey::kLargePages].PostStrings.Front(); if (postString.IsEmpty()) options.LargePages = true; } #endif } struct CCodePagePair { const wchar_t *Name; UINT CodePage; }; static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, { L"WIN", CP_ACP }, { L"DOS", CP_OEMCP } }; static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { const wchar_t *end; UInt64 number = ConvertStringToUInt64(s, &end); if (*end != 0) return false; if (number > (UInt32)0xFFFFFFFF) return false; v = (UInt32)number; return true; } void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) { const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); if (numNonSwitchStrings < kMinNonSwitchWords) ThrowUserErrorException(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command)) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); NRecursedType::EEnum recursedType; if (parser[NKey::kRecursed].ThereIs) recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex); else recursedType = NRecursedType::kNonRecursed; UINT codePage = CP_UTF8; if (parser[NKey::kCharSet].ThereIs) { UString name = parser[NKey::kCharSet].PostStrings.Front(); name.MakeUpper(); int i; for (i = 0; i < kNumCodePages; i++) { const CCodePagePair &pair = g_CodePagePairs[i]; if (name.Compare(pair.Name) == 0) { codePage = pair.CodePage; break; } } if (i >= kNumCodePages) ThrowUserErrorException(); } bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) { thereAreSwitchIncludes = true; AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kInclude].PostStrings, true, recursedType, codePage); } if (parser[NKey::kExclude].ThereIs) AddSwitchWildCardsToCensor(options.WildcardCensor, parser[NKey::kExclude].PostStrings, false, recursedType, codePage); int curCommandIndex = kCommandIndex + 1; bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) ThrowUserErrorException(); options.ArchiveName = nonSwitchStrings[curCommandIndex++]; } AddToCensorFromNonSwitchesStrings( curCommandIndex, options.WildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage); options.YesToAll = parser[NKey::kYes].ThereIs; bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; if (options.PasswordEnabled) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if (options.StdInMode) ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); NWildcard::CCensor archiveWildcardCensor; if (parser[NKey::kArInclude].ThereIs) { AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage); } if (parser[NKey::kArExclude].ThereIs) AddSwitchWildCardsToCensor(archiveWildcardCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage); if (thereIsArchiveName) AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed); #ifdef _WIN32 ConvertToLongNames(archiveWildcardCensor); #endif archiveWildcardCensor.ExtendExclude(); UStringVector archivePaths; { CDirItems dirItems; { UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes); if (res != S_OK || errorPaths.Size() > 0) throw "cannot find archive"; } for (int i = 0; i < dirItems.Items.Size(); i++) { const CDirItem &dirItem = dirItems.Items[i]; if (!dirItem.IsDir()) archivePaths.Add(dirItems.GetPhyPath(i)); } } if (archivePaths.Size() == 0) throw "there is no such archive"; UStringVector archivePathsFull; int i; for (i = 0; i < archivePaths.Size(); i++) { UString fullPath; NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath); archivePathsFull.Add(fullPath); } CIntVector indices; SortFileNames(archivePathsFull, indices); options.ArchivePathsSorted.Reserve(indices.Size()); options.ArchivePathsFullSorted.Reserve(indices.Size()); for (i = 0; i < indices.Size(); i++) { options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } if (isExtractGroupCommand) { SetMethodOptions(parser, options.ExtractProperties); if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal) throw kSameTerminalError; if (parser[NKey::kOutputDir].ThereIs) { options.OutputDir = parser[NKey::kOutputDir].PostStrings[0]; NFile::NName::NormalizeDirPathPrefix(options.OutputDir); } options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore; if (parser[NKey::kOverwrite].ThereIs) options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex]; else if (options.YesToAll) options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; } } else if (options.Command.IsFromUpdateGroup()) { CUpdateOptions &updateOptions = options.UpdateOptions; SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); SetMethodOptions(parser, updateOptions.MethodMode.Properties); if (parser[NKey::kShareForWrite].ThereIs) updateOptions.OpenShareForWrite = true; options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs; if (options.EnablePercents) { if ((options.StdOutMode && !options.IsStdErrTerminal) || (!options.StdOutMode && !options.IsStdOutTerminal)) options.EnablePercents = false; } updateOptions.EMailMode = parser[NKey::kEmail].ThereIs; if (updateOptions.EMailMode) { updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front(); if (updateOptions.EMailAddress.Length() > 0) if (updateOptions.EMailAddress[0] == L'.') { updateOptions.EMailRemoveAfter = true; updateOptions.EMailAddress.Delete(0); } } updateOptions.StdOutMode = options.StdOutMode; updateOptions.StdInMode = options.StdInMode; if (updateOptions.StdOutMode && updateOptions.EMailMode) throw "stdout mode and email mode cannot be combined"; if (updateOptions.StdOutMode && options.IsStdOutTerminal) throw kTerminalOutError; if (updateOptions.StdInMode) updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front(); #ifdef _WIN32 ConvertToLongNames(options.WildcardCensor); #endif } else if (options.Command.CommandType == NCommandType::kBenchmark) { options.NumThreads = (UInt32)-1; options.DictionarySize = (UInt32)-1; options.NumIterations = 1; if (curCommandIndex < numNonSwitchStrings) { if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations)) ThrowUserErrorException(); } for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++) { UString postString = parser[NKey::kProperty].PostStrings[i]; postString.MakeUpper(); if (postString.Length() < 2) ThrowUserErrorException(); if (postString[0] == 'D') { int pos = 1; if (postString[pos] == '=') pos++; UInt32 logSize; if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize)) ThrowUserErrorException(); if (logSize > 31) ThrowUserErrorException(); options.DictionarySize = 1 << logSize; } else if (postString[0] == 'M' && postString[1] == 'T' ) { int pos = 2; if (postString[pos] == '=') pos++; if (postString[pos] != 0) if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads)) ThrowUserErrorException(); } else if (postString[0] == 'M' && postString[1] == '=' ) { int pos = 2; if (postString[pos] != 0) options.Method = postString.Mid(2); } else ThrowUserErrorException(); } } else if (options.Command.CommandType == NCommandType::kInfo) { } else ThrowUserErrorException(); options.WildcardCensor.ExtendExclude(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveCommandLine.h ================================================ // ArchiveCommandLine.h #ifndef __ARCHIVECOMMANDLINE_H #define __ARCHIVECOMMANDLINE_H #include "Common/Wildcard.h" #include "Common/CommandLineParser.h" #include "Extract.h" #include "Update.h" struct CArchiveCommandLineException: public AString { CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {} }; namespace NCommandType { enum EEnum { kAdd = 0, kUpdate, kDelete, kTest, kExtract, kFullExtract, kList, kBenchmark, kInfo };} namespace NRecursedType { enum EEnum { kRecursed, kWildCardOnlyRecursed, kNonRecursed };} struct CArchiveCommand { NCommandType::EEnum CommandType; bool IsFromExtractGroup() const; bool IsFromUpdateGroup() const; bool IsTestMode() const { return CommandType == NCommandType::kTest; } NExtract::NPathMode::EEnum GetPathMode() const; }; struct CArchiveCommandLineOptions { bool HelpMode; #ifdef _WIN32 bool LargePages; #endif bool IsInTerminal; bool IsStdOutTerminal; bool IsStdErrTerminal; bool StdInMode; bool StdOutMode; bool EnableHeaders; bool YesToAll; bool ShowDialog; // NWildcard::CCensor ArchiveWildcardCensor; NWildcard::CCensor WildcardCensor; CArchiveCommand Command; UString ArchiveName; #ifndef _NO_CRYPTO bool PasswordEnabled; UString Password; #endif bool TechMode; // Extract bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; UStringVector ArchivePathsSorted; UStringVector ArchivePathsFullSorted; CObjectVector<CProperty> ExtractProperties; CUpdateOptions UpdateOptions; UString ArcType; bool EnablePercents; // Benchmark UInt32 NumIterations; UInt32 NumThreads; UInt32 DictionarySize; UString Method; CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {}; }; class CArchiveCommandLineParser { NCommandLineParser::CParser parser; public: CArchiveCommandLineParser(); void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options); void Parse2(CArchiveCommandLineOptions &options); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp ================================================ // ArchiveExtractCallback.cpp #include "StdAfx.h" #include "ArchiveExtractCallback.h" #include "Common/Wildcard.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" #include "OpenArchive.h" using namespace NWindows; static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name"; static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; void CArchiveExtractCallback::Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize) { _stdOutMode = stdOutMode; _numErrors = 0; _unpTotal = 1; _packTotal = packSize; _extractCallback2 = extractCallback2; _compressProgress.Release(); _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; _itemDefaultName = itemDefaultName; _utcMTimeDefault = utcMTimeDefault; _attributesDefault = attributesDefault; _removePathParts = removePathParts; _archiveHandler = archiveHandler; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN _unpTotal = size; if (!_multiArchives && _extractCallback2) return _extractCallback2->SetTotal(size); return S_OK; COM_TRY_END } static void NormalizeVals(UInt64 &v1, UInt64 &v2) { const UInt64 kMax = (UInt64)1 << 31; while (v1 > kMax) { v1 >>= 1; v2 >>= 1; } } static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal) { NormalizeVals(packTotal, unpTotal); NormalizeVals(unpCur, unpTotal); if (unpTotal == 0) unpTotal = 1; return unpCur * packTotal / unpTotal; } STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN if (!_extractCallback2) return S_OK; if (_multiArchives) { if (completeValue != NULL) { UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal); return _extractCallback2->SetCompleted(&packCur); } } return _extractCallback2->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return _localProgress->SetRatioInfo(inSize, outSize); COM_TRY_END } void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; for(int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); fullPath += dirPathParts[i]; NFile::NDirectory::MyCreateDirectory(fullPath); } } static UString MakePathNameFromParts(const UStringVector &parts) { UString result; for(int i = 0; i < parts.Size(); i++) { if(i != 0) result += wchar_t(NFile::NName::kDirDelimiter); result += parts[i]; } return result; } HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0); } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; UString fullPath; RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) return E_FAIL; _position = prop.uhVal.QuadPart; _isSplit = true; } } RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); bool newFileSizeDefined; UInt64 newFileSize; { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); newFileSizeDefined = (prop.vt != VT_EMPTY); if (newFileSizeDefined) { newFileSize = ConvertPropVariantToUInt64(prop); _curSize = newFileSize; } } if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) { if (_stdOutMode) { CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream; *outStream = outStreamLoc.Detach(); return S_OK; } { NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attributes = _attributesDefault; _processedFileInfo.AttributesAreDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attributes = prop.ulVal; _processedFileInfo.AttributesAreDefined = true; } } RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); bool isAnti = false; RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); if(pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) { case NExtract::NPathMode::kFullPathnames: break; case NExtract::NPathMode::kCurrentPathnames: { numRemovePathParts = _removePathParts.Size(); if (pathParts.Size() <= numRemovePathParts) return E_FAIL; for (int i = 0; i < numRemovePathParts; i++) if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0) return E_FAIL; break; } case NExtract::NPathMode::kNoPathnames: { numRemovePathParts = pathParts.Size() - 1; break; } } pathParts.Delete(0, numRemovePathParts); MakeCorrectPath(pathParts); UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { if (!_processedFileInfo.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); } if (!pathParts.IsEmpty()) { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); if (_processedFileInfo.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); } } UString fullProcessedPath = _directoryPath + processedPath; if(_processedFileInfo.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) NFile::NDirectory::MyRemoveDirectory(_diskFilePath); return S_OK; } if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) { switch(_overwriteMode) { case NExtract::NOverwriteMode::kSkipExisting: return S_OK; case NExtract::NOverwriteMode::kAskBefore: { Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, newFileSizeDefined ? &newFileSize : NULL, &overwiteResult)) switch(overwiteResult) { case NOverwriteAnswer::kCancel: return E_ABORT; case NOverwriteAnswer::kNo: return S_OK; case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkipExisting; return S_OK; case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt; break; case NOverwriteAnswer::kYes: break; case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kAutoRename; break; default: return E_FAIL; } } } if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename) { if (!AutoRenamePath(fullProcessedPath)) { UString message = UString(kCantAutoRename) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting) { UString existPath = fullProcessedPath; if (!AutoRenamePath(existPath)) { UString message = kCantAutoRename + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } } else if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { UString message = UString(kCantDeleteOutputFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; // return E_FAIL; } } } if (!isAnti) { _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS)) { // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit) { UString message = L"can not open output file " + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); return S_OK; } } if (_isSplit) { RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL)); } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } _diskFilePath = fullProcessedPath; } else { *outStream = NULL; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) { COM_TRY_BEGIN _extractMode = false; switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: _extractMode = true; }; return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: case NArchive::NExtract::NOperationResult::kUnSupportedMethod: case NArchive::NExtract::NOperationResult::kCRCError: case NArchive::NExtract::NOperationResult::kDataError: break; default: _outFileStream.Release(); return E_FAIL; } if (_outFileStream != NULL) { _outFileStreamSpec->SetTime( (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); _curSize = _outFileStreamSpec->ProcessedSize; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } UnpackSize += _curSize; if (_processedFileInfo.IsDir) NumFolders++; else NumFiles++; if (_extractMode && _processedFileInfo.AttributesAreDefined) NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END } /* STDMETHODIMP CArchiveExtractCallback::GetInStream( const wchar_t *name, ISequentialInStream **inStream) { COM_TRY_BEGIN CInFileStream *inFile = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamTemp = inFile; if (!inFile->Open(_srcDirectoryPrefix + name)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; COM_TRY_END } */ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (!_cryptoGetTextPassword) { RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, &_cryptoGetTextPassword)); } return _cryptoGetTextPassword->CryptoGetTextPassword(password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveExtractCallback.h ================================================ // ArchiveExtractCallback.h #ifndef __ARCHIVEEXTRACTCALLBACK_H #define __ARCHIVEEXTRACTCALLBACK_H #include "../../Archive/IArchive.h" #include "IFileExtractCallback.h" #include "Common/MyString.h" #include "Common/MyCom.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" #include "../../IPassword.h" #include "ExtractMode.h" class CArchiveExtractCallback: public IArchiveExtractCallback, // public IArchiveVolumeExtractCallback, public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) INTERFACE_IArchiveExtractCallback(;) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); // IArchiveVolumeExtractCallback // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); // ICryptoGetTextPassword STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); private: CMyComPtr<IInArchive> _archiveHandler; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; UString _directoryPath; NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; UString _filePath; UInt64 _position; bool _isSplit; UString _diskFilePath; bool _extractMode; bool WriteCTime; bool WriteATime; bool WriteMTime; bool _encrypted; struct CProcessedFileInfo { FILETIME CTime; FILETIME ATime; FILETIME MTime; UInt32 Attributes; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool IsDir; bool AttributesAreDefined; } _processedFileInfo; UInt64 _curSize; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; UStringVector _removePathParts; UString _itemDefaultName; FILETIME _utcMTimeDefault; UInt32 _attributesDefault; bool _stdOutMode; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); public: CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), WriteMTime(true), _multiArchives(false) { LocalProgressSpec = new CLocalProgress(); _localProgress = LocalProgressSpec; } CLocalProgress *LocalProgressSpec; CMyComPtr<ICompressProgressInfo> _localProgress; UInt64 _packTotal; UInt64 _unpTotal; bool _multiArchives; UInt64 NumFolders; UInt64 NumFiles; UInt64 UnpackSize; void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; _pathMode = pathMode; _overwriteMode = overwriteMode; } void Init( IInArchive *archiveHandler, IFolderArchiveExtractCallback *extractCallback2, bool stdOutMode, const UString &directoryPath, const UStringVector &removePathParts, const UString &itemDefaultName, const FILETIME &utcMTimeDefault, UInt32 attributesDefault, UInt64 packSize); UInt64 _numErrors; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveName.cpp ================================================ // ArchiveName.cpp #include "StdAfx.h" #include "Windows/FileFind.h" #include "Windows/FileDir.h" using namespace NWindows; UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveName.h ================================================ // ArchiveName.h #ifndef __ARCHIVENAME_H #define __ARCHIVENAME_H #include "Common/MyString.h" UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp ================================================ // ArchiveOpenCallback.cpp #include "StdAfx.h" #include "ArchiveOpenCallback.h" #include "Common/StringConvert.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetTotal(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetTotal(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes) { COM_TRY_BEGIN if (ReOpenCallback) return ReOpenCallback->SetCompleted(files, bytes); if (!Callback) return S_OK; return Callback->Open_SetCompleted(files, bytes); COM_TRY_END } STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN NCOM::CPropVariant prop; if (_subArchiveMode) switch(propID) { case kpidName: prop = _subArchiveName; break; } else switch(propID) { case kpidName: prop = _fileInfo.Name; break; case kpidIsDir: prop = _fileInfo.IsDir(); break; case kpidSize: prop = _fileInfo.Size; break; case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break; case kpidCTime: prop = _fileInfo.CTime; break; case kpidATime: prop = _fileInfo.ATime; break; case kpidMTime: prop = _fileInfo.MTime; break; } prop.Detach(value); return S_OK; COM_TRY_END } int COpenCallbackImp::FindName(const UString &name) { for (int i = 0; i < FileNames.Size(); i++) if (name.CompareNoCase(FileNames[i]) == 0) return i; return -1; } struct CInFileStreamVol: public CInFileStream { UString Name; COpenCallbackImp *OpenCallbackImp; CMyComPtr<IArchiveOpenCallback> OpenCallbackRef; ~CInFileStreamVol() { int index = OpenCallbackImp->FindName(Name); if (index >= 0) OpenCallbackImp->FileNames.Delete(index); } }; STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream) { COM_TRY_BEGIN if (_subArchiveMode) return S_FALSE; if (Callback) { RINOK(Callback->Open_CheckBreak()); } *inStream = NULL; UString fullPath = _folderPrefix + name; if (!NFile::NFind::FindFile(fullPath, _fileInfo)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; CInFileStreamVol *inFile = new CInFileStreamVol; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); inFile->Name = name; inFile->OpenCallbackImp = this; inFile->OpenCallbackRef = this; FileNames.Add(name); TotalSize += _fileInfo.Size; return S_OK; COM_TRY_END } #ifndef _NO_CRYPTO STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password) { COM_TRY_BEGIN if (ReOpenCallback) { CMyComPtr<ICryptoGetTextPassword> getTextPassword; ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); if (getTextPassword) return getTextPassword->CryptoGetTextPassword(password); } if (!Callback) return E_NOTIMPL; return Callback->Open_CryptoGetTextPassword(password); COM_TRY_END } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ArchiveOpenCallback.h ================================================ // ArchiveOpenCallback.h #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H #include "Common/MyString.h" #include "Common/MyCom.h" #include "Windows/FileFind.h" #ifndef _NO_CRYPTO #include "../../IPassword.h" #endif #include "../../Archive/IArchive.h" #ifdef _NO_CRYPTO #define INTERFACE_IOpenCallbackUI_Crypto(x) #else #define INTERFACE_IOpenCallbackUI_Crypto(x) \ virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \ virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \ virtual bool Open_WasPasswordAsked() x; \ virtual void Open_ClearPasswordWasAskedFlag() x; \ #endif #define INTERFACE_IOpenCallbackUI(x) \ virtual HRESULT Open_CheckBreak() x; \ virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \ virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \ INTERFACE_IOpenCallbackUI_Crypto(x) struct IOpenCallbackUI { INTERFACE_IOpenCallbackUI(=0) }; class COpenCallbackImp: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public IArchiveOpenSetSubArchiveName, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: #ifndef _NO_CRYPTO MY_UNKNOWN_IMP3( IArchiveOpenVolumeCallback, ICryptoGetTextPassword, IArchiveOpenSetSubArchiveName ) #else MY_UNKNOWN_IMP2( IArchiveOpenVolumeCallback, IArchiveOpenSetSubArchiveName ) #endif INTERFACE_IArchiveOpenCallback(;) INTERFACE_IArchiveOpenVolumeCallback(;) #ifndef _NO_CRYPTO STDMETHOD(CryptoGetTextPassword)(BSTR *password); #endif STDMETHOD(SetSubArchiveName(const wchar_t *name)) { _subArchiveMode = true; _subArchiveName = name; return S_OK; } private: UString _folderPrefix; NWindows::NFile::NFind::CFileInfoW _fileInfo; bool _subArchiveMode; UString _subArchiveName; public: UStringVector FileNames; IOpenCallbackUI *Callback; CMyComPtr<IArchiveOpenCallback> ReOpenCallback; UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) throw 1; FileNames.Clear(); _subArchiveMode = false; TotalSize = 0; } int FindName(const UString &name); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/DefaultName.cpp ================================================ // DefaultName.cpp #include "StdAfx.h" #include "DefaultName.h" static UString GetDefaultName3(const UString &fileName, const UString &extension, const UString &addSubExtension) { int extLength = extension.Length(); int fileNameLength = fileName.Length(); if (fileNameLength > extLength + 1) { int dotPos = fileNameLength - (extLength + 1); if (fileName[dotPos] == '.') if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0) return fileName.Left(dotPos) + addSubExtension; } int dotPos = fileName.ReverseFind(L'.'); if (dotPos > 0) return fileName.Left(dotPos) + addSubExtension; if (addSubExtension.IsEmpty()) return fileName + L"~"; else return fileName + addSubExtension; } UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension) { UString name = GetDefaultName3(fileName, extension, addSubExtension); name.TrimRight(); return name; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/DefaultName.h ================================================ // DefaultName.h #ifndef __DEFAULTNAME_H #define __DEFAULTNAME_H #include "Common/MyString.h" UString GetDefaultName2(const UString &fileName, const UString &extension, const UString &addSubExtension); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/DirItem.h ================================================ // DirItem.h #ifndef __DIR_ITEM_H #define __DIR_ITEM_H #include "Common/MyString.h" #include "Common/Types.h" #include "../../Archive/IArchive.h" struct CDirItem { UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; UString Name; UInt32 Attrib; int PhyParent; int LogParent; CDirItem(): PhyParent(-1), LogParent(-1) {} bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } }; class CDirItems { UStringVector Prefixes; CIntVector PhyParents; CIntVector LogParents; UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; public: CObjectVector<CDirItem> Items; int GetNumFolders() const { return Prefixes.Size(); } UString GetPhyPath(int index) const; UString GetLogPath(int index) const; int AddPrefix(int phyParent, int logParent, const UString &prefix); void DeleteLastPrefix(); void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void EnumerateDirItems2( const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); void ReserveDown(); }; struct CArcItem { UInt64 Size; FILETIME MTime; UString Name; bool IsDir; bool SizeDefined; bool Censored; UInt32 IndexInServer; int TimeType; CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/EnumDirItems.cpp ================================================ // EnumDirItems.cpp #include "StdAfx.h" #include <stdio.h> #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Common/MyCom.h" #include "EnumDirItems.h" using namespace NWindows; using namespace NFile; using namespace NName; void AddDirFileInfo(int phyParent, int logParent, const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems) { CDirItem di; di.Size = fi.Size; di.CTime = fi.CTime; di.ATime = fi.ATime; di.MTime = fi.MTime; di.Attrib = fi.Attrib; di.PhyParent = phyParent; di.LogParent = logParent; di.Name = fi.Name; dirItems.Add(di); } UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const { UString path; int len = name.Length(); int i; for (i = index; i >= 0; i = parents[i]) len += Prefixes[i].Length(); int totalLen = len; wchar_t *p = path.GetBuffer(len); p[len] = 0; len -= name.Length(); memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); for (i = index; i >= 0; i = parents[i]) { const UString &s = Prefixes[i]; len -= s.Length(); memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); } path.ReleaseBuffer(totalLen); return path; } UString CDirItems::GetPhyPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); } UString CDirItems::GetLogPath(int index) const { const CDirItem &di = Items[index]; return GetPrefixesPath(LogParents, di.LogParent, di.Name); } void CDirItems::ReserveDown() { Prefixes.ReserveDown(); PhyParents.ReserveDown(); LogParents.ReserveDown(); Items.ReserveDown(); } int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) { PhyParents.Add(phyParent); LogParents.Add(logParent); return Prefixes.Add(prefix); } void CDirItems::DeleteLastPrefix() { PhyParents.DeleteBack(); LogParents.DeleteBack(); Prefixes.DeleteBack(); } void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); for (;;) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParent, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } } void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; if (!NFind::FindFile(phyPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); UString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const UString name2 = fi.Name + (wchar_t)kDirDelimiter; int parent = AddPrefix(phyParentCur, logParent, name2); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &curFolderName, const UString &phyPrefix, const UStringVector &addArchivePrefix, CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { const UString name2 = curFolderName + (wchar_t)kDirDelimiter; int parent = dirItems.AddPrefix(phyParent, logParent, name2); int numItems = dirItems.Items.Size(); HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); if (numItems == dirItems.Items.Size()) dirItems.DeleteLastPrefix(); return res; } static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const UString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fi.Name); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; if (!NFind::FindFile(fullPath, fi)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); for (int ttt = 0; ; ttt++) { NFind::CFileInfoW fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); const UString &name = fi.Name; bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; } HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for (int i = 0; i < censor.Pairs.Size(); i++) { const NWildcard::CPair &pair = censor.Pairs[i]; int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } dirItems.ReserveDown(); return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/EnumDirItems.h ================================================ // EnumDirItems.h #ifndef __ENUM_DIR_ITEMS_H #define __ENUM_DIR_ITEMS_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "DirItem.h" void AddDirFileInfo(int phyParent, int logParent, const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems); struct IEnumDirItemCallback { virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0; }; HRESULT EnumerateItems( const NWildcard::CCensor &censor, CDirItems &dirItems, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ExitCode.h ================================================ // ExitCode.h #ifndef __EXIT_CODE_H #define __EXIT_CODE_H namespace NExitCode { enum EEnum { kSuccess = 0, // Successful operation kWarning = 1, // Non fatal error(s) occurred kFatalError = 2, // A fatal error occurred // kCRCError = 3, // A CRC error occurred when unpacking // kLockedArchive = 4, // Attempt to modify an archive previously locked // kWriteError = 5, // Write to disk error // kOpenError = 6, // Open file error kUserError = 7, // Command line option error kMemoryError = 8, // Not enough memory for operation // kCreateFileError = 9, // Create file error kUserBreak = 255 // User stopped the process }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/Extract.cpp ================================================ // Extract.cpp #include "StdAfx.h" #include "Extract.h" #include "Windows/Defs.h" #include "Windows/FileDir.h" #include "OpenArchive.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( IInArchive *archive, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, UString &errorMessage) { CRecordVector<UInt32> realIndices; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { UString filePath; RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; realIndices.Add(i); } if (realIndices.Size() == 0) { callback->ThereAreNoFiles(); return S_OK; } UStringVector removePathParts; UString outDir = options.OutputDir; outDir.Replace(L"*", options.DefaultItemName); #ifdef _WIN32 outDir.TrimRight(); #endif if(!outDir.IsEmpty()) if(!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) res = E_FAIL; errorMessage = ((UString)L"Can not create output directory ") + outDir; return res; } extractCallbackSpec->Init( archive, callback, options.StdOutMode, outDir, removePathParts, options.DefaultItemName, options.ArchiveFileInfo.MTime, options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif HRESULT result = archive->Extract(&realIndices.Front(), realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/Extract.h ================================================ // Extract.h #ifndef __EXTRACT_H #define __EXTRACT_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "ArchiveExtractCallback.h" #include "ArchiveOpenCallback.h" #include "ExtractMode.h" #include "Property.h" #include "../Common/LoadCodecs.h" class CExtractOptions { public: bool StdOutMode; bool TestMode; NExtract::NPathMode::EEnum PathMode; UString OutputDir; bool YesToAll; UString DefaultItemName; NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; // UString Password; #ifdef COMPRESS_MT CObjectVector<CProperty> Properties; #endif NExtract::NOverwriteMode::EEnum OverwriteMode; #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): StdOutMode(false), YesToAll(false), TestMode(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} /* bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || (ExtractMode == NExtractMode::kFullPath); } */ }; struct CDecompressStat { UInt64 NumArchives; UInt64 UnpackSize; UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } }; HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ExtractMode.h ================================================ // ExtractMode.h #ifndef __EXTRACT_MODE_H #define __EXTRACT_MODE_H namespace NExtract { namespace NPathMode { enum EEnum { kFullPathnames, kCurrentPathnames, kNoPathnames }; } namespace NOverwriteMode { enum EEnum { kAskBefore, kWithoutPrompt, kSkipExisting, kAutoRename, kAutoRenameExisting }; } } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ExtractingFilePath.cpp ================================================ // ExtractingFilePath.cpp #include "StdAfx.h" #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) { #ifdef _WIN32 UString res; for (int i = 0; i < s.Length(); i++) { wchar_t c = s[i]; if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') c = '_'; res += c; } res.TrimRight(); return res; #else return s; #endif } #ifdef _WIN32 static const wchar_t *g_ReservedNames[] = { L"CON", L"PRN", L"AUX", L"NUL" }; static bool CheckTail(const UString &name, int len) { int dotPos = name.Find(L'.'); if (dotPos < 0) dotPos = name.Length(); UString s = name.Left(dotPos); s.TrimRight(); return (s.Length() != len); } static bool CheckNameNum(const UString &name, const wchar_t *reservedName) { int len = MyStringLen(reservedName); if (name.Length() <= len) return true; if (name.Left(len).CompareNoCase(reservedName) != 0) return true; wchar_t c = name[len]; if (c < L'0' || c > L'9') return true; return CheckTail(name, len + 1); } static bool IsSupportedName(const UString &name) { for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) { const wchar_t *reservedName = g_ReservedNames[i]; int len = MyStringLen(reservedName); if (name.Length() < len) continue; if (name.Left(len).CompareNoCase(reservedName) != 0) continue; if (!CheckTail(name, len)) return false; } if (!CheckNameNum(name, L"COM")) return false; return CheckNameNum(name, L"LPT"); } #endif static UString GetCorrectFileName(const UString &path) { if (path == L".." || path == L".") return UString(); return ReplaceIncorrectChars(path); } void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ExtractingFilePath.h ================================================ // ExtractingFilePath.h #ifndef __EXTRACTINGFILEPATH_H #define __EXTRACTINGFILEPATH_H #include "Common/MyString.h" void MakeCorrectPath(UStringVector &pathParts); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/IFileExtractCallback.h ================================================ // IFileExtractCallback.h #ifndef __IFILEEXTRACTCALLBACK_H #define __IFILEEXTRACTCALLBACK_H #include "Common/MyString.h" #include "../../IDecl.h" namespace NOverwriteAnswer { enum EEnum { kYes, kYesToAll, kNo, kNoToAll, kAutoRename, kCancel }; } DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07) { public: STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer) PURE; STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE; STDMETHOD(MessageError)(const wchar_t *message) PURE; STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE; }; struct IExtractCallbackUI: IFolderArchiveExtractCallback { virtual HRESULT BeforeOpen(const wchar_t *name) = 0; virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0; virtual HRESULT ThereAreNoFiles() = 0; virtual HRESULT ExtractResult(HRESULT result) = 0; #ifndef _NO_CRYPTO virtual HRESULT SetPassword(const UString &password) = 0; #endif }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/LoadCodecs.cpp ================================================ // LoadCodecs.cpp #include "StdAfx.h" #include "LoadCodecs.h" #include "../../../Common/MyCom.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Common/StringToInt.h" #endif #include "../../../Windows/PropVariant.h" #include "../../ICoder.h" #include "../../Common/RegisterArc.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/FileFind.h" #include "../../../Windows/DLL.h" #ifdef NEW_FOLDER_INTERFACE #include "../../../Windows/ResourceString.h" static const UINT kIconTypesResId = 100; #endif #ifdef _WIN32 #include "Windows/Registry.h" #endif using namespace NWindows; using namespace NFile; #ifdef _WIN32 extern HINSTANCE g_hInstance; #endif static CSysString GetLibraryFolderPrefix() { #ifdef _WIN32 TCHAR fullPath[MAX_PATH + 1]; ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH); CSysString path = fullPath; int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); return path.Left(pos + 1); #else return CSysString(); // FIX IT #endif } #define kCodecsFolderName TEXT("Codecs") #define kFormatsFolderName TEXT("Formats") static const TCHAR *kMainDll = TEXT("7z.dll"); #ifdef _WIN32 static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip"); static LPCTSTR kProgramPathValue = TEXT("Path"); static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) { NRegistry::CKey key; if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS) if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS) { NName::NormalizeDirPathPrefix(path); return true; } return false; } #endif CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); NFind::CFileInfo fi; if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) if (!fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) if (fi.IsDir()) return moduleFolderPrefix; #ifdef _WIN32 CSysString path; if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; } typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject); typedef UInt32 (WINAPI *SetLargePageModeFunc)(); static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) { NWindows::NCOM::CPropVariant prop; isAssigned = false; RINOK(getMethodProperty(index, propId, &prop)); if (prop.vt == VT_BSTR) { isAssigned = true; clsId = *(const GUID *)prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } HRESULT CCodecs::LoadCodecs() { CCodecLib &lib = Libs.Back(); lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty"); if (lib.GetMethodProperty == NULL) return S_OK; UInt32 numMethods = 1; GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods"); if (getNumberOfMethodsFunc != NULL) { RINOK(getNumberOfMethodsFunc(&numMethods)); } for(UInt32 i = 0; i < numMethods; i++) { CDllCodecInfo info; info.LibIndex = Libs.Size() - 1; info.CodecIndex = i; RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned)); RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned)); Codecs.Add(info); } return S_OK; } static HRESULT ReadProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NCOM::CPropVariant &prop) { if (getProp2) return getProp2(index, propID, &prop);; return getProp(propID, &prop); } static HRESULT ReadBoolProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BOOL) res = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } static HRESULT ReadStringProp( GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, UString &res) { NCOM::CPropVariant prop; RINOK(ReadProp(getProp, getProp2, index, propID, prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } #endif static const unsigned int kNumArcsMax = 32; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) { if (g_NumArcs < kNumArcsMax) g_Arcs[g_NumArcs++] = arcInfo; } static void SplitString(const UString &srcString, UStringVector &destStrings) { destStrings.Clear(); UString s; int len = srcString.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = srcString[i]; if (c == L' ') { if (!s.IsEmpty()) { destStrings.Add(s); s.Empty(); } } else s += c; } if (!s.IsEmpty()) destStrings.Add(s); } void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt) { UStringVector exts, addExts; SplitString(ext, exts); if (addExt != 0) SplitString(addExt, addExts); for (int i = 0; i < exts.Size(); i++) { CArcExtInfo extInfo; extInfo.Ext = exts[i]; if (i < addExts.Size()) { extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); } Exts.Add(extInfo); } } #ifdef EXTERNAL_CODECS HRESULT CCodecs::LoadFormats() { const NDLL::CLibrary &lib = Libs.Back().Lib; GetHandlerPropertyFunc getProp = 0; GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2) lib.GetProcAddress("GetHandlerProperty2"); if (getProp2 == NULL) { getProp = (GetHandlerPropertyFunc) lib.GetProcAddress("GetHandlerProperty"); if (getProp == NULL) return S_OK; } UInt32 numFormats = 1; GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc) lib.GetProcAddress("GetNumberOfFormats"); if (getNumberOfFormats != NULL) { RINOK(getNumberOfFormats(&numFormats)); } if (getProp2 == NULL) numFormats = 1; for(UInt32 i = 0; i < numFormats; i++) { CArcInfoEx item; item.LibIndex = Libs.Size() - 1; item.FormatIndex = i; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name)); NCOM::CPropVariant prop; if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); UString ext, addExt; RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext)); RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt)); item.AddExts(ext, addExt); ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled); if (item.UpdateEnabled) ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName); if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } Formats.Add(item); } return S_OK; } #ifdef NEW_FOLDER_INTERFACE void CCodecLib::LoadIcons() { UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId); UStringVector pairs; SplitString(iconTypes, pairs); for (int i = 0; i < pairs.Size(); i++) { const UString &s = pairs[i]; int pos = s.Find(L':'); if (pos < 0) continue; CIconPair iconPair; const wchar_t *end; UString num = s.Mid(pos + 1); iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end); if (*end != L'\0') continue; iconPair.Ext = s.Left(pos); IconPairs.Add(iconPair); } } int CCodecLib::FindIconIndex(const UString &ext) const { for (int i = 0; i < IconPairs.Size(); i++) { const CIconPair &pair = IconPairs[i]; if (ext.CompareNoCase(pair.Ext) == 0) return pair.IconIndex; } return -1; } #endif #ifdef _7ZIP_LARGE_PAGES extern "C" { extern SIZE_T g_LargePageSize; } #endif HRESULT CCodecs::LoadDll(const CSysString &dllPath) { { NDLL::CLibrary library; if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE)) return S_OK; } Libs.Add(CCodecLib()); CCodecLib &lib = Libs.Back(); #ifdef NEW_FOLDER_INTERFACE lib.Path = dllPath; #endif bool used = false; HRESULT res = S_OK; if (lib.Lib.Load(dllPath)) { #ifdef NEW_FOLDER_INTERFACE lib.LoadIcons(); #endif #ifdef _7ZIP_LARGE_PAGES if (g_LargePageSize != 0) { SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode"); if (setLargePageMode != 0) setLargePageMode(); } #endif lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject"); if (lib.CreateObject != 0) { int startSize = Codecs.Size(); res = LoadCodecs(); used = (Codecs.Size() != startSize); if (res == S_OK) { startSize = Formats.Size(); res = LoadFormats(); used = used || (Formats.Size() != startSize); } } } if (!used) Libs.DeleteBack(); return res; } HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; } #endif #ifndef _SFX static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size) { bb.SetCapacity(size); memmove((Byte *)bb, data, size); } #endif HRESULT CCodecs::Load() { Formats.Clear(); #ifdef EXTERNAL_CODECS Codecs.Clear(); #endif for (UInt32 i = 0; i < g_NumArcs; i++) { const CArcInfo &arc = *g_Arcs[i]; CArcInfoEx item; item.Name = arc.Name; item.CreateInArchive = arc.CreateInArchive; item.CreateOutArchive = arc.CreateOutArchive; item.AddExts(arc.Ext, arc.AddExt); item.UpdateEnabled = (arc.CreateOutArchive != 0); item.KeepName = arc.KeepName; #ifndef _SFX SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize); #endif Formats.Add(item); } #ifdef EXTERNAL_CODECS const CSysString baseFolder = GetBaseFolderPrefixFromRegistry(); RINOK(LoadDll(baseFolder + kMainDll)); RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR))); RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR))); #endif return S_OK; } #ifndef _SFX int CCodecs::FindFormatForArchiveName(const UString &arcPath) const { int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR); int slashPos2 = arcPath.ReverseFind(L'.'); int dotPos = arcPath.ReverseFind(L'.'); if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2) return -1; UString ext = arcPath.Mid(dotPos + 1); for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; // if (arc.FindExtension(ext) >= 0) UString mainExt = arc.GetMainExt(); if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) return i; } return -1; } int CCodecs::FindFormatForExtension(const UString &ext) const { if (ext.IsEmpty()) return -1; for (int i = 0; i < Formats.Size(); i++) if (Formats[i].FindExtension(ext) >= 0) return i; return -1; } int CCodecs::FindFormatForArchiveType(const UString &arcType) const { for (int i = 0; i < Formats.Size(); i++) if (Formats[i].Name.CompareNoCase(arcType) == 0) return i; return -1; } bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const { formatIndices.Clear(); for (int pos = 0; pos < arcType.Length();) { int pos2 = arcType.Find('.', pos); if (pos2 < 0) pos2 = arcType.Length(); const UString name = arcType.Mid(pos, pos2 - pos); int index = FindFormatForArchiveType(name); if (index < 0 && name != L"*") { formatIndices.Clear(); return false; } formatIndices.Add(index); pos = pos2 + 1; } return true; } #endif #ifdef EXTERNAL_CODECS #ifdef EXPORT_CODECS extern unsigned int g_NumCodecs; STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject); STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value); // STDAPI GetNumberOfMethods(UInt32 *numCodecs); #endif STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods) { *numMethods = #ifdef EXPORT_CODECS g_NumCodecs + #endif Codecs.Size(); return S_OK; } STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return GetMethodProperty(index, propID, value); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (propID == NMethodPropID::kDecoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.DecoderIsAssigned; propVariant.Detach(value); return S_OK; } if (propID == NMethodPropID::kEncoderIsAssigned) { NWindows::NCOM::CPropVariant propVariant; propVariant = ci.EncoderIsAssigned; propVariant.Detach(value); return S_OK; } return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value); } STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(false, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.DecoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder); return S_OK; } STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return CreateCoder2(true, index, iid, coder); #endif const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; if (ci.EncoderIsAssigned) return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder); return S_OK; } HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const { for (int i = 0; i < Codecs.Size(); i++) { const CDllCodecInfo &codec = Codecs[i]; if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned) continue; const CCodecLib &lib = Libs[codec.LibIndex]; UString res; NWindows::NCOM::CPropVariant prop; RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop)); if (prop.vt == VT_BSTR) res = prop.bstrVal; else if (prop.vt != VT_EMPTY) continue; if (name.CompareNoCase(res) == 0) return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder); } return CLASS_E_CLASSNOTAVAILABLE; } int CCodecs::GetCodecLibIndex(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) return -1; #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.LibIndex; #else return -1; #endif } bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index) { #ifdef EXPORT_CODECS if (index < g_NumCodecs) { NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK) if (prop.vt != VT_EMPTY) return true; return false; } #endif #ifdef EXTERNAL_CODECS const CDllCodecInfo &ci = Codecs[index #ifdef EXPORT_CODECS - g_NumCodecs #endif ]; return ci.EncoderIsAssigned; #else return false; #endif } HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id) { UString s; NWindows::NCOM::CPropVariant prop; RINOK(GetProperty(index, NMethodPropID::kID, &prop)); if (prop.vt != VT_UI8) return E_INVALIDARG; id = prop.uhVal.QuadPart; return S_OK; } UString CCodecs::GetCodecName(UInt32 index) { UString s; NWindows::NCOM::CPropVariant prop; if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK) if (prop.vt == VT_BSTR) s = prop.bstrVal; return s; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/LoadCodecs.h ================================================ // LoadCodecs.h #ifndef __LOADCODECS_H #define __LOADCODECS_H #include "../../../Common/Types.h" #include "../../../Common/MyCom.h" #include "../../../Common/MyString.h" #include "../../../Common/Buffer.h" #include "../../ICoder.h" #ifdef EXTERNAL_CODECS #include "../../../Windows/DLL.h" #endif struct CDllCodecInfo { CLSID Encoder; CLSID Decoder; bool EncoderIsAssigned; bool DecoderIsAssigned; int LibIndex; UInt32 CodecIndex; }; #include "../../Archive/IArchive.h" typedef IInArchive * (*CreateInArchiveP)(); typedef IOutArchive * (*CreateOutArchiveP)(); struct CArcExtInfo { UString Ext; UString AddExt; CArcExtInfo() {} CArcExtInfo(const UString &ext): Ext(ext) {} CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {} }; struct CArcInfoEx { #ifdef EXTERNAL_CODECS int LibIndex; UInt32 FormatIndex; CLSID ClassID; #endif bool UpdateEnabled; CreateInArchiveP CreateInArchive; CreateOutArchiveP CreateOutArchive; UString Name; CObjectVector<CArcExtInfo> Exts; #ifndef _SFX CByteBuffer StartSignature; // CByteBuffer FinishSignature; #ifdef NEW_FOLDER_INTERFACE UStringVector AssociateExts; #endif #endif bool KeepName; UString GetMainExt() const { if (Exts.IsEmpty()) return UString(); return Exts[0].Ext; } int FindExtension(const UString &ext) const { for (int i = 0; i < Exts.Size(); i++) if (ext.CompareNoCase(Exts[i].Ext) == 0) return i; return -1; } UString GetAllExtensions() const { UString s; for (int i = 0; i < Exts.Size(); i++) { if (i > 0) s += ' '; s += Exts[i].Ext; } return s; } void AddExts(const wchar_t* ext, const wchar_t* addExt); CArcInfoEx(): #ifdef EXTERNAL_CODECS LibIndex(-1), #endif UpdateEnabled(false), CreateInArchive(0), CreateOutArchive(0), KeepName(false) #ifndef _SFX #endif {} }; #ifdef EXTERNAL_CODECS typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); struct CCodecLib { NWindows::NDLL::CLibrary Lib; GetMethodPropertyFunc GetMethodProperty; CreateObjectFunc CreateObject; #ifdef NEW_FOLDER_INTERFACE struct CIconPair { UString Ext; UInt32 IconIndex; }; CSysString Path; CObjectVector<CIconPair> IconPairs; void LoadIcons(); int FindIconIndex(const UString &ext) const; #endif CCodecLib(): GetMethodProperty(0) {} }; #endif class CCodecs: #ifdef EXTERNAL_CODECS public ICompressCodecsInfo, #else public IUnknown, #endif public CMyUnknownImp { public: #ifdef EXTERNAL_CODECS CObjectVector<CCodecLib> Libs; CObjectVector<CDllCodecInfo> Codecs; HRESULT LoadCodecs(); HRESULT LoadFormats(); HRESULT LoadDll(const CSysString &path); HRESULT LoadDllsFromFolder(const CSysString &folderPrefix); HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const { return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive); } #endif public: CObjectVector<CArcInfoEx> Formats; HRESULT Load(); #ifndef _SFX int FindFormatForArchiveName(const UString &arcPath) const; int FindFormatForExtension(const UString &ext) const; int FindFormatForArchiveType(const UString &arcType) const; bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const; #endif MY_UNKNOWN_IMP #ifdef EXTERNAL_CODECS STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods); STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder); STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder); #endif int GetCodecLibIndex(UInt32 index); bool GetCodecEncoderIsAssigned(UInt32 index); HRESULT GetCodecId(UInt32 index, UInt64 &id); UString GetCodecName(UInt32 index); HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateInArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, false); #endif } HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const { const CArcInfoEx &ai = Formats[formatIndex]; #ifdef EXTERNAL_CODECS if (ai.LibIndex < 0) #endif { archive = ai.CreateOutArchive(); return S_OK; } #ifdef EXTERNAL_CODECS return CreateArchiveHandler(ai, (void **)&archive, true); #endif } int FindOutFormatFromName(const UString &name) const { for (int i = 0; i < Formats.Size(); i++) { const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; if (arc.Name.CompareNoCase(name) == 0) return i; } return -1; } #ifdef EXTERNAL_CODECS HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const; #endif }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/OpenArchive.cpp ================================================ // OpenArchive.cpp #include "StdAfx.h" #include "OpenArchive.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "Common/StringConvert.h" #include "DefaultName.h" using namespace NWindows; HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidPath, &prop)); if(prop.vt == VT_BSTR) result = prop.bstrVal; else if (prop.vt == VT_EMPTY) result.Empty(); else return E_FAIL; return S_OK; } HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) { RINOK(GetArchiveItemPath(archive, index, result)); if (result.IsEmpty()) { result = defaultName; NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; result += prop.bstrVal; } else if (prop.vt != VT_EMPTY) return E_FAIL; } return S_OK; } HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) fileTime = prop.filetime; else if (prop.vt == VT_EMPTY) fileTime = defaultFileTime; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; RINOK(archive->GetProperty(index, propID, &prop)); if(prop.vt == VT_BOOL) result = VARIANT_BOOLToBool(prop.boolVal); else if (prop.vt == VT_EMPTY) result = false; else return E_FAIL; return S_OK; } HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsDir, result); } HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) { return IsArchiveItemProp(archive, index, kpidIsAnti, result); } // Static-SFX (for Linux) can be big. const UInt64 kMaxCheckStartPosition = 1 << 22; HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); inStreamSpec->Open(fileName); return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); } #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { for (size_t i = 0; i < size; i++) if (p1[i] != p2[i]) return false; return true; } #endif HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { *archiveResult = NULL; UString extension; { int dotPos = fileName.ReverseFind(L'.'); if (dotPos >= 0) extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; if (arcTypeIndex >= 0) orderIndices.Add(arcTypeIndex); else { int i; int numFinded = 0; for (i = 0; i < codecs->Formats.Size(); i++) if (codecs->Formats[i].FindExtension(extension) >= 0) orderIndices.Insert(numFinded++, i); else orderIndices.Add(i); #ifndef _SFX if (numFinded != 1) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; const Byte *buf = byteBuffer; Byte hash[1 << 16]; memset(hash, 0xFF, 1 << 16); Byte prevs[256]; if (orderIndices.Size() > 255) return S_FALSE; int i; for (i = 0; i < orderIndices.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[orderIndices[i]]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() < 2) continue; UInt32 v = sig[0] | ((UInt32)sig[1] << 8); prevs[i] = hash[v]; hash[v] = (Byte)i; } processedSize--; for (UInt32 pos = 0; pos < processedSize; pos++) { for (; pos < processedSize && hash[buf[pos] | ((UInt32)buf[pos + 1] << 8)] == 0xFF; pos++); if (pos == processedSize) break; UInt32 v = buf[pos] | ((UInt32)buf[pos + 1] << 8); Byte *ptr = &hash[v]; int i = *ptr; do { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; const CByteBuffer &sig = ai.StartSignature; if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + 1) if (TestSignature(buf + pos, sig, sig.GetCapacity())) { orderIndices2.Add(index); orderIndices[i] = 0xFF; *ptr = prevs[i]; } ptr = &prevs[i]; i = *ptr; } while (i != 0xFF); } for (i = 0; i < orderIndices.Size(); i++) { int val = orderIndices[i]; if (val != 0xFF) orderIndices2.Add(val); } orderIndices = orderIndices2; if (orderIndices.Size() >= 2) { int isoIndex = codecs->FindFormatForArchiveType(L"iso"); int udfIndex = codecs->FindFormatForArchiveType(L"udf"); int iIso = -1; int iUdf = -1; for (int i = 0; i < orderIndices.Size(); i++) { if (orderIndices[i] == isoIndex) iIso = i; if (orderIndices[i] == udfIndex) iUdf = i; } if (iUdf == iIso + 1) { orderIndices[iUdf] = isoIndex; orderIndices[iIso] = udfIndex; } } } else if (extension == L"000" || extension == L"001") { CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; RINOK(ReadStream(inStream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0) { for (int i = 0; i < orderIndices.Size(); i++) { int index = orderIndices[i]; const CArcInfoEx &ai = codecs->Formats[index]; if (ai.Name.CompareNoCase(L"rar") != 0) continue; orderIndices.Delete(i--); orderIndices.Insert(0, index); break; } } } } #endif } for(int i = 0; i < orderIndices.Size(); i++) { inStream->Seek(0, STREAM_SEEK_SET, NULL); CMyComPtr<IInArchive> archive; formatIndex = orderIndices[i]; RINOK(codecs->CreateInArchive(formatIndex, archive)); if (!archive) continue; #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); if (result == S_FALSE) continue; RINOK(result); *archiveResult = archive.Detach(); const CArcInfoEx &format = codecs->Formats[formatIndex]; if (format.Exts.Size() == 0) { defaultItemName = GetDefaultName2(fileName, L"", L""); } else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; defaultItemName = GetDefaultName2(fileName, format.Exts[subExtIndex].Ext, format.Exts[subExtIndex].AddExt); } return S_OK; } return S_FALSE; } HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback) { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<IInStream> inStream(inStreamSpec); if (!inStreamSpec->Open(filePath)) return GetLastError(); return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), archiveResult, formatIndex, defaultItemName, openArchiveCallback); } static void MakeDefaultName(UString &name) { int dotPos = name.ReverseFind(L'.'); if (dotPos < 0) return; UString ext = name.Mid(dotPos + 1); if (ext.IsEmpty()) return; for (int pos = 0; pos < ext.Length(); pos++) if (ext[pos] < L'0' || ext[pos] > L'9') return; name = name.Left(dotPos); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &fileName, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback) { if (formatIndices.Size() >= 3) return E_NOTIMPL; int arcTypeIndex = -1; if (formatIndices.Size() >= 1) arcTypeIndex = formatIndices[formatIndices.Size() - 1]; HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, archive0, formatIndex0, defaultItemName0, openArchiveCallback); RINOK(result); if (formatIndices.Size() == 1) return S_OK; arcTypeIndex = -1; if (formatIndices.Size() >= 2) arcTypeIndex = formatIndices[formatIndices.Size() - 2]; HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); CMyComPtr<IInArchiveGetStream> getStream; result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); if (result != S_OK || !getStream) return resSpec; CMyComPtr<ISequentialInStream> subSeqStream; result = getStream->GetStream(0, &subSeqStream); if (result != S_OK || !subSeqStream) return resSpec; CMyComPtr<IInStream> subStream; result = subSeqStream.QueryInterface(IID_IInStream, &subStream); if (result != S_OK || !subStream) return resSpec; UInt32 numItems; RINOK((*archive0)->GetNumberOfItems(&numItems)); if (numItems < 1) return resSpec; UString subPath; RINOK(GetArchiveItemPath(*archive0, 0, subPath)) if (subPath.IsEmpty()) { MakeDefaultName(defaultItemName0); subPath = defaultItemName0; const CArcInfoEx &format = codecs->Formats[formatIndex0]; if (format.Name.CompareNoCase(L"7z") == 0) { if (subPath.Right(3).CompareNoCase(L".7z") != 0) subPath += L".7z"; } } else subPath = ExtractFileNameFromPath(subPath); CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); if (setSubArchiveName) setSubArchiveName->SetSubArchiveName(subPath); result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, archive1, formatIndex1, defaultItemName1, openArchiveCallback); resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); if (result != S_OK) return resSpec; return S_OK; } static void SetCallback(const UString &archiveName, IOpenCallbackUI *openCallbackUI, IArchiveOpenCallback *reOpenCallback, CMyComPtr<IArchiveOpenCallback> &openCallback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } HRESULT MyOpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &archiveName, IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) { CMyComPtr<IArchiveOpenCallback> openCallback; SetCallback(archiveName, openCallbackUI, NULL, openCallback); int formatInfo; return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); } HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, IInArchive **archive0, IInArchive **archive1, UString &defaultItemName0, UString &defaultItemName1, UStringVector &volumePaths, UInt64 &volumesSize, IOpenCallbackUI *openCallbackUI) { volumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; openCallbackSpec->Callback = openCallbackUI; UString fullName; int fileNamePartStartIndex; NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); UString prefix = fullName.Left(fileNamePartStartIndex); UString name = fullName.Mid(fileNamePartStartIndex); openCallbackSpec->Init(prefix, name); int formatIndex0, formatIndex1; RINOK(OpenArchive(codecs, formatIndices, archiveName, archive0, archive1, formatIndex0, formatIndex1, defaultItemName0, defaultItemName1, openCallback)); volumePaths.Add(prefix + name); for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); volumesSize = openCallbackSpec->TotalSize; return S_OK; } HRESULT CArchiveLink::Close() { if (Archive1 != 0) RINOK(Archive1->Close()); if (Archive0 != 0) RINOK(Archive0->Close()); IsOpen = false; return S_OK; } void CArchiveLink::Release() { IsOpen = false; Archive1.Release(); Archive0.Release(); } HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback) { HRESULT res = OpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.FormatIndex0, archiveLink.FormatIndex1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, openCallback); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT MyOpenArchive(CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI) { HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, &archiveLink.Archive0, &archiveLink.Archive1, archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, archiveLink.VolumePaths, archiveLink.VolumesSize, openCallbackUI); archiveLink.IsOpen = (res == S_OK); return res; } HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback) { if (archiveLink.GetNumLevels() > 1) return E_NOTIMPL; if (archiveLink.GetNumLevels() == 0) return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; SetCallback(fileName, NULL, openCallback, openCallbackNew); HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); archiveLink.IsOpen = (res == S_OK); return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/OpenArchive.h ================================================ // OpenArchive.h #ifndef __OPENARCHIVE_H #define __OPENARCHIVE_H #include "Common/MyString.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "LoadCodecs.h" #include "ArchiveOpenCallback.h" HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, const FILETIME &defaultFileTime, FILETIME &fileTime); HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); struct ISetSubArchiveName { virtual void SetSubArchiveName(const wchar_t *name) = 0; }; HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, IInStream *inStream, const UString &fileName, IInArchive **archiveResult, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, int arcTypeIndex, const UString &filePath, IInArchive **archive, int &formatIndex, UString &defaultItemName, IArchiveOpenCallback *openArchiveCallback); HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &filePath, IInArchive **archive0, IInArchive **archive1, int &formatIndex0, int &formatIndex1, UString &defaultItemName0, UString &defaultItemName1, IArchiveOpenCallback *openArchiveCallback); HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); struct CArchiveLink { CMyComPtr<IInArchive> Archive0; CMyComPtr<IInArchive> Archive1; UString DefaultItemName0; UString DefaultItemName1; int FormatIndex0; int FormatIndex1; UStringVector VolumePaths; bool IsOpen; UInt64 VolumesSize; int GetNumLevels() const { int result = 0; if (Archive0) { result++; if (Archive1) result++; } return result; } CArchiveLink(): IsOpen(false), VolumesSize(0) {}; IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } HRESULT Close(); void Release(); }; HRESULT OpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IArchiveOpenCallback *openCallback); HRESULT MyOpenArchive( CCodecs *codecs, const CIntVector &formatIndices, const UString &archiveName, CArchiveLink &archiveLink, IOpenCallbackUI *openCallbackUI); HRESULT ReOpenArchive( CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, IArchiveOpenCallback *openCallback); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/PropIDUtils.cpp ================================================ // PropIDUtils.cpp #include "StdAfx.h" #include "PropIDUtils.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" using namespace NWindows; static UString ConvertUInt32ToString(UInt32 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { int t = value & 0xF; value >>= 4; s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10))); } s[8] = L'\0'; } UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) { switch(propID) { case kpidCTime: case kpidATime: case kpidMTime: { if (propVariant.vt != VT_FILETIME) return UString(); // It is error; FILETIME localFileTime; if (propVariant.filetime.dwHighDateTime == 0 && propVariant.filetime.dwLowDateTime == 0) return UString(); if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { if(propVariant.vt != VT_UI4) break; wchar_t temp[12]; ConvertUInt32ToHex(propVariant.ulVal, temp); return temp; } case kpidAttrib: { if(propVariant.vt != VT_UI4) break; UString result; UInt32 attributes = propVariant.ulVal; if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; return result; } case kpidDictionarySize: { if(propVariant.vt != VT_UI4) break; UInt32 size = propVariant.ulVal; if (size % (1 << 20) == 0) return ConvertUInt32ToString(size >> 20) + L"MB"; if (size % (1 << 10) == 0) return ConvertUInt32ToString(size >> 10) + L"KB"; return ConvertUInt32ToString(size); } } return ConvertPropVariantToString(propVariant); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/PropIDUtils.h ================================================ // PropIDUtils.h #ifndef __PROPIDUTILS_H #define __PROPIDUTILS_H #include "Common/MyString.h" UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/Property.h ================================================ // Property.h #ifndef __PROPERTY_H #define __PROPERTY_H #include "Common/MyString.h" struct CProperty { UString Name; UString Value; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/SetProperties.cpp ================================================ // SetProperties.cpp #include "StdAfx.h" #include "SetProperties.h" #include "Windows/PropVariant.h" #include "Common/MyString.h" #include "Common/StringToInt.h" #include "Common/MyCom.h" #include "../../Archive/IArchive.h" using namespace NWindows; using namespace NCOM; static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop) { const wchar_t *endPtr; UInt64 result = ConvertStringToUInt64(s, &endPtr); if (endPtr - (const wchar_t *)s != s.Length()) prop = s; else if (result <= 0xFFFFFFFF) prop = (UInt32)result; else prop = result; } HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties) { if (properties.IsEmpty()) return S_OK; CMyComPtr<ISetProperties> setProperties; unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties); if (!setProperties) return S_OK; UStringVector realNames; CPropVariant *values = new CPropVariant[properties.Size()]; try { int i; for(i = 0; i < properties.Size(); i++) { const CProperty &property = properties[i]; NCOM::CPropVariant propVariant; UString name = property.Name; if (property.Value.IsEmpty()) { if (!name.IsEmpty()) { wchar_t c = name[name.Length() - 1]; if (c == L'-') propVariant = false; else if (c == L'+') propVariant = true; if (propVariant.vt != VT_EMPTY) name = name.Left(name.Length() - 1); } } else ParseNumberString(property.Value, propVariant); realNames.Add(name); values[i] = propVariant; } CRecordVector<const wchar_t *> names; for(i = 0; i < realNames.Size(); i++) names.Add((const wchar_t *)realNames[i]); RINOK(setProperties->SetProperties(&names.Front(), values, names.Size())); } catch(...) { delete []values; throw; } delete []values; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/SetProperties.h ================================================ // SetProperties.h #ifndef __SETPROPERTIES_H #define __SETPROPERTIES_H #include "Property.h" HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/SortUtils.cpp ================================================ // SortUtils.cpp #include "StdAfx.h" #include "SortUtils.h" #include "Common/Wildcard.h" static int CompareStrings(const int *p1, const int *p2, void *param) { const UStringVector &strings = *(const UStringVector *)param; return CompareFileNames(strings[*p1], strings[*p2]); } void SortFileNames(const UStringVector &strings, CIntVector &indices) { indices.Clear(); int numItems = strings.Size(); indices.Reserve(numItems); for(int i = 0; i < numItems; i++) indices.Add(i); indices.Sort(CompareStrings, (void *)&strings); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/SortUtils.h ================================================ // SortUtils.h #ifndef __SORTUTLS_H #define __SORTUTLS_H #include "Common/MyString.h" void SortFileNames(const UStringVector &strings, CIntVector &indices); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/StdAfx.h ================================================ // stdafx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/TempFiles.cpp ================================================ // TempFiles.cpp #include "StdAfx.h" #include "TempFiles.h" #include "Windows/FileDir.h" #include "Windows/FileIO.h" using namespace NWindows; using namespace NFile; void CTempFiles::Clear() { while(!Paths.IsEmpty()) { NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back()); Paths.DeleteBack(); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/TempFiles.h ================================================ // TempFiles.h #ifndef __TEMPFILES_H #define __TEMPFILES_H #include "Common/MyString.h" class CTempFiles { void Clear(); public: UStringVector Paths; ~CTempFiles() { Clear(); } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/Update.cpp ================================================ // Update.cpp #include "StdAfx.h" #include "Update.h" #include "Common/IntToString.h" #include "Common/StringConvert.h" #ifdef _WIN32 #include "Windows/DLL.h" #endif #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/FileName.h" #include "Windows/PropVariant.h" #include "Windows/PropVariantConversions.h" #include "Windows/Time.h" #include "../../Common/FileStreams.h" #include "../../Compress/CopyCoder.h" #include "../Common/DirItem.h" #include "../Common/EnumDirItems.h" #include "../Common/OpenArchive.h" #include "../Common/UpdateProduce.h" #include "EnumDirItems.h" #include "SetProperties.h" #include "TempFiles.h" #include "UpdateCallback.h" static const char *kUpdateIsNotSupoorted = "update operations are not supported for this archive"; using namespace NWindows; using namespace NCOM; using namespace NFile; using namespace NName; static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) { CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); } class COutMultiVolStream: public IOutStream, public CMyUnknownImp { int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { COutFileStream *StreamSpec; CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams; public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } HRESULT Close(); MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; // static NSynchronization::CCriticalSection g_TempPathsCS; HRESULT COutMultiVolStream::Close() { HRESULT res = S_OK; for (int i = 0; i < Streams.Size(); i++) { CSubStreamInfo &s = Streams[i]; if (s.StreamSpec) { HRESULT res2 = s.StreamSpec->Close(); if (res2 != S_OK) res = res2; } } return res; } STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; if(!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK; } STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK; } STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize) { if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK; } static const wchar_t *kDefaultArchiveType = L"7z"; static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endif bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath) { if (formatIndices.Size() > 1) return false; int arcTypeIndex = -1; if (formatIndices.Size() != 0) arcTypeIndex = formatIndices[0]; if (arcTypeIndex >= 0) MethodMode.FormatIndex = arcTypeIndex; else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } if (MethodMode.FormatIndex < 0) return false; const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex]; if (!arcInfo.UpdateEnabled) return false; UString typeExt = arcInfo.GetMainExt(); UString ext = typeExt; if (SfxMode) ext = kSFXExtension; ArchivePath.BaseExtension = ext; ArchivePath.VolExtension = typeExt; ArchivePath.ParseFromPath(arcPath); for (int i = 0; i < Commands.Size(); i++) { CUpdateArchiveCommand &uc = Commands[i]; uc.ArchivePath.BaseExtension = ext; uc.ArchivePath.VolExtension = typeExt; uc.ArchivePath.ParseFromPath(uc.UserArchivePath); } return true; } /* struct CUpdateProduceCallbackImp: public IUpdateProduceCallback { const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex) { return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name); } */ static HRESULT Compress( CCodecs *codecs, const CActionSet &actionSet, IInArchive *archive, const CCompressionMethodMode &compressionMethod, CArchivePath &archivePath, const CObjectVector<CArcItem> &arcItems, bool shareForWrite, bool stdInMode, /* const UString & stdInFileName, */ bool stdOutMode, const CDirItems &dirItems, bool sfxMode, const UString &sfxModule, const CRecordVector<UInt64> &volumesSizes, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; if(archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); if(result != S_OK) throw kUpdateIsNotSupoorted; } else { RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive)); #ifdef EXTERNAL_CODECS { CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs)); } } #endif } if (outArchive == 0) throw kUpdateIsNotSupoorted; NFileTimeType::EEnum fileTimeType; UInt32 value; RINOK(outArchive->GetFileTimeType(&value)); switch(value) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: fileTimeType = (NFileTimeType::EEnum)value; break; default: return E_FAIL; } CRecordVector<CUpdatePair2> updatePairs2; { CRecordVector<CUpdatePair> updatePairs; GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!! // CUpdateProduceCallbackImp upCallback(&arcItems, callback); UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */); } UInt32 numFiles = 0; for (int i = 0; i < updatePairs2.Size(); i++) if (updatePairs2[i].NewData) numFiles++; RINOK(callback->SetNumFiles(numFiles)); CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback; CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec); updateCallbackSpec->ShareForWrite = shareForWrite; updateCallbackSpec->StdInMode = stdInMode; updateCallbackSpec->Callback = callback; updateCallbackSpec->DirItems = &dirItems; updateCallbackSpec->ArcItems = &arcItems; updateCallbackSpec->UpdatePairs = &updatePairs2; CMyComPtr<ISequentialOutStream> outStream; const UString &archiveName = archivePath.GetFinalPath(); if (!stdOutMode) { UString resultPath; int pos; if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } COutFileStream *outStreamSpec = NULL; COutMultiVolStream *volStreamSpec = NULL; if (volumesSizes.Size() == 0) { if (stdOutMode) outStream = new CStdOutFileStream; else { outStreamSpec = new COutFileStream; outStream = outStreamSpec; bool isOK = false; UString realPath; for (int i = 0; i < (1 << 16); i++) { if (archivePath.Temp) { if (i > 0) { wchar_t s[32]; ConvertUInt64ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); } else realPath = archivePath.GetFinalPath(); if (outStreamSpec->Create(realPath, false)) { tempFiles.Paths.Add(realPath); isOK = true; break; } if (::GetLastError() != ERROR_FILE_EXISTS) break; if (!archivePath.Temp) break; } if (!isOK) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } } else { if (stdOutMode) return E_FAIL; volStreamSpec = new COutMultiVolStream; outStream = volStreamSpec; volStreamSpec->Sizes = volumesSizes; volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L"."); volStreamSpec->TempFiles = &tempFiles; volStreamSpec->Init(); /* updateCallbackSpec->VolumesSizes = volumesSizes; updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name; if (!archivePath.VolExtension.IsEmpty()) updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension; */ } RINOK(SetProperties(outArchive, compressionMethod.Properties)); if (sfxMode) { CInFileStream *sfxStreamSpec = new CInFileStream; CMyComPtr<IInStream> sfxStream(sfxStreamSpec); if (!sfxStreamSpec->Open(sfxModule)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"Can't open sfx module"; errorInfo.FileName = sfxModule; return E_FAIL; } CMyComPtr<ISequentialOutStream> sfxOutStream; COutFileStream *outStreamSpec = NULL; if (volumesSizes.Size() == 0) sfxOutStream = outStream; else { outStreamSpec = new COutFileStream; sfxOutStream = outStreamSpec; UString realPath = archivePath.GetFinalPath(); if (!outStreamSpec->Create(realPath, false)) { errorInfo.SystemError = ::GetLastError(); errorInfo.FileName = realPath; errorInfo.Message = L"Can not open file"; return E_FAIL; } } RINOK(CopyBlock(sfxStream, sfxOutStream)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); } } HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback); callback->Finilize(); RINOK(result); if (outStreamSpec) result = outStreamSpec->Close(); else if (volStreamSpec) result = volStreamSpec->Close(); return result; } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, IInArchive *archive, const UString &defaultItemName, const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; RINOK(GetArchiveItemPath(archive, i, ai.Name)); // check it: defaultItemName !!! if (ai.Name.IsEmpty()) ai.Name = defaultItemName; RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); { CPropVariant prop; RINOK(archive->GetProperty(i, kpidSize, &prop)); ai.SizeDefined = (prop.vt != VT_EMPTY); if (ai.SizeDefined) ai.Size = ConvertPropVariantToUInt64(prop); } { CPropVariant prop; RINOK(archive->GetProperty(i, kpidTimeType, &prop)); if (prop.vt == VT_UI4) { ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal; switch(ai.TimeType) { case NFileTimeType::kWindows: case NFileTimeType::kUnix: case NFileTimeType::kDOS: break; default: return E_FAIL; } } } ai.IndexInServer = i; arcItems.Add(ai); } return S_OK; } static HRESULT UpdateWithItemLists( CCodecs *codecs, CUpdateOptions &options, IInArchive *archive, const CObjectVector<CArcItem> &arcItems, CDirItems &dirItems, CTempFiles &tempFiles, CUpdateErrorInfo &errorInfo, IUpdateCallbackUI2 *callback) { for(int i = 0; i < options.Commands.Size(); i++) { CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { RINOK(callback->StartArchive(0, archive != 0)); } else { RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), i == 0 && options.UpdateArchiveItself && archive != 0)); } RINOK(Compress( codecs, command.ActionSet, archive, options.MethodMode, command.ArchivePath, arcItems, options.OpenShareForWrite, options.StdInMode, /* options.StdInFileName, */ options.StdOutMode, dirItems, options.SfxMode, options.SfxModule, options.VolumesSizes, tempFiles, errorInfo, callback)); RINOK(callback->FinishArchive()); } return S_OK; } #ifdef _WIN32 class CCurrentDirRestorer { UString m_CurrentDirectory; public: CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); } ~CCurrentDirRestorer() { RestoreDirectory();} bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); } }; #endif struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback { IUpdateCallbackUI2 *Callback; HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) { return Callback->ScanProgress(numFolders, numFiles, path); } }; #ifdef _WIN32 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)( ULONG_PTR ulUIParam, LPSTR lpszDelimChar, LPSTR lpszFilePaths, LPSTR lpszFileNames, ULONG ulReserved ); typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS; #endif HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback) { if (options.StdOutMode && options.EMailMode) return E_FAIL; if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode)) return E_NOTIMPL; if (options.SfxMode) { CProperty property; property.Name = L"rsfx"; property.Value = L"on"; options.MethodMode.Properties.Add(property); if (options.SfxModule.IsEmpty()) { errorInfo.Message = L"sfx file is not specified"; return E_FAIL; } UString name = options.SfxModule; if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule)) { errorInfo.Message = L"can't find specified sfx module"; return E_FAIL; } } const UString archiveName = options.ArchivePath.GetFinalPath(); UString defaultItemName; NFind::CFileInfoW archiveFileInfo; CArchiveLink archiveLink; IInArchive *archive = 0; if (NFind::FindFile(archiveName, archiveFileInfo)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; if (options.VolumesSizes.Size() > 0) return E_NOTIMPL; CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); RINOK(result); if (archiveLink.VolumePaths.Size() > 1) { errorInfo.SystemError = (DWORD)E_NOTIMPL; errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } archive = archiveLink.GetArchive(); defaultItemName = archiveLink.GetDefaultItemName(); } else { /* if (archiveType.IsEmpty()) throw "type of archive is not specified"; */ } CDirItems dirItems; if (options.StdInMode) { CDirItem di; di.Name = options.StdInFileName; di.Size = (UInt64)(Int64)-1; di.Attrib = 0; NTime::GetCurUtcFileTime(di.MTime); di.CTime = di.ATime = di.MTime; dirItems.Items.Add(di); } else { bool needScanning = false; for(int i = 0; i < options.Commands.Size(); i++) if (options.Commands[i].ActionSet.NeedScanning()) needScanning = true; if (needScanning) { CEnumDirItemUpdateCallback enumCallback; enumCallback.Callback = callback; RINOK(callback->StartScanning()); UStringVector errorPaths; CRecordVector<DWORD> errorCodes; HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes); for (int i = 0; i < errorPaths.Size(); i++) { RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i])); } if (res != S_OK) { if (res != E_ABORT) errorInfo.Message = L"Scanning error"; // errorInfo.FileName = errorPath; return res; } RINOK(callback->FinishScanning()); } } UString tempDirPrefix; bool usesTempDir = false; #ifdef _WIN32 NDirectory::CTempDirectoryW tempDirectory; if (options.EMailMode && options.EMailRemoveAfter) { tempDirectory.Create(kTempFolderPrefix); tempDirPrefix = tempDirectory.GetPath(); NormalizeDirPathPrefix(tempDirPrefix); usesTempDir = true; } #endif CTempFiles tempFiles; bool createTempFile = false; if(!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; if (!options.WorkingDir.IsEmpty()) { ap.TempPrefix = options.WorkingDir; NormalizeDirPathPrefix(ap.TempPrefix); } } } for(int i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; if (usesTempDir) { // Check it ap.Prefix = tempDirPrefix; // ap.Temp = true; // ap.TempPrefix = tempDirPrefix; } if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); if (NFind::DoesFileExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; errorInfo.FileName = path; return E_FAIL; } } } CObjectVector<CArcItem> arcItems; if (archive != NULL) { RINOK(EnumerateInArchiveItems(censor, archive, defaultItemName, archiveFileInfo, arcItems)); } RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, tempFiles, errorInfo, callback)); if (archive != NULL) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); if(createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); if (archive != NULL) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"delete file error"; errorInfo.FileName = archiveName; return E_FAIL; } if (!NDirectory::MyMoveFile(tempPath, archiveName)) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"move file error"; errorInfo.FileName = tempPath; errorInfo.FileName2 = archiveName; return E_FAIL; } } catch(...) { throw; } } #ifdef _WIN32 if (options.EMailMode) { NDLL::CLibrary mapiLib; if (!mapiLib.Load(TEXT("Mapi32.dll"))) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not load Mapi32.dll"; return E_FAIL; } MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS) mapiLib.GetProcAddress("MAPISendDocuments"); if (fnSend == 0) { errorInfo.SystemError = ::GetLastError(); errorInfo.Message = L"can not find MAPISendDocuments function"; return E_FAIL; } UStringVector fullPaths; int i; for(i = 0; i < options.Commands.Size(); i++) { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; } fullPaths.Add(arcPath); } CCurrentDirRestorer curDirRestorer; for(i = 0; i < fullPaths.Size(); i++) { UString arcPath = fullPaths[i]; UString fileName = ExtractFileNameFromPath(arcPath); AString path = GetAnsiString(arcPath); AString name = GetAnsiString(fileName); // Warning!!! MAPISendDocuments function changes Current directory fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); } } #endif return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/Update.h ================================================ // Update.h #ifndef __UPDATE_H #define __UPDATE_H #include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" #include "UpdateAction.h" #include "ArchiveOpenCallback.h" #include "UpdateCallback.h" #include "Property.h" #include "LoadCodecs.h" struct CArchivePath { UString Prefix; // path(folder) prefix including slash UString Name; // base name UString BaseExtension; // archive type extension or "exe" extension UString VolExtension; // archive type extension for volumes bool Temp; UString TempPrefix; // path(folder) for temp location UString TempPostfix; CArchivePath(): Temp(false) {}; void ParseFromPath(const UString &path) { SplitPathToParts(path, Prefix, Name); if (Name.IsEmpty()) return; int dotPos = Name.ReverseFind(L'.'); if (dotPos <= 0) return; if (dotPos == Name.Length() - 1) { Name = Name.Left(dotPos); BaseExtension.Empty(); return; } if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0) { BaseExtension = Name.Mid(dotPos + 1); Name = Name.Left(dotPos); } else BaseExtension.Empty(); } UString GetPathWithoutExt() const { return Prefix + Name; } UString GetFinalPath() const { UString path = GetPathWithoutExt(); if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; return path; } UString GetTempPath() const { UString path = TempPrefix + Name; if (!BaseExtension.IsEmpty()) path += UString(L'.') + BaseExtension; path += L".tmp"; path += TempPostfix; return path; } }; struct CUpdateArchiveCommand { UString UserArchivePath; CArchivePath ArchivePath; NUpdateArchive::CActionSet ActionSet; }; struct CCompressionMethodMode { int FormatIndex; CObjectVector<CProperty> Properties; CCompressionMethodMode(): FormatIndex(-1) {} }; struct CUpdateOptions { CCompressionMethodMode MethodMode; CObjectVector<CUpdateArchiveCommand> Commands; bool UpdateArchiveItself; CArchivePath ArchivePath; bool SfxMode; UString SfxModule; bool OpenShareForWrite; bool StdInMode; UString StdInFileName; bool StdOutMode; bool EMailMode; bool EMailRemoveAfter; UString EMailAddress; UString WorkingDir; bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath); CUpdateOptions(): UpdateArchiveItself(true), SfxMode(false), StdInMode(false), StdOutMode(false), EMailMode(false), EMailRemoveAfter(false), OpenShareForWrite(false) {}; CRecordVector<UInt64> VolumesSizes; }; struct CErrorInfo { DWORD SystemError; UString FileName; UString FileName2; UString Message; // UStringVector ErrorPaths; // CRecordVector<DWORD> ErrorCodes; CErrorInfo(): SystemError(0) {}; }; struct CUpdateErrorInfo: public CErrorInfo { }; #define INTERFACE_IUpdateCallbackUI2(x) \ INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \ virtual HRESULT StartScanning() x; \ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT FinishScanning() x; \ virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \ virtual HRESULT FinishArchive() x; \ struct IUpdateCallbackUI2: public IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI2(=0) }; HRESULT UpdateArchive( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateErrorInfo &errorInfo, IOpenCallbackUI *openCallback, IUpdateCallbackUI2 *callback); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateAction.cpp ================================================ // UpdateAction.cpp #include "StdAfx.h" #include "UpdateAction.h" namespace NUpdateArchive { const CActionSet kAddActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress, NPairAction::kCompress }; const CActionSet kUpdateActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kFreshActionSet = { NPairAction::kCopy, NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress }; const CActionSet kSynchronizeActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, NPairAction::kCopy, NPairAction::kCompress, }; const CActionSet kDeleteActionSet = { NPairAction::kCopy, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore, NPairAction::kIgnore }; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateAction.h ================================================ // UpdateAction.h #ifndef __UPDATE_ACTION_H #define __UPDATE_ACTION_H namespace NUpdateArchive { namespace NPairState { const int kNumValues = 7; enum EEnum { kNotMasked = 0, kOnlyInArchive, kOnlyOnDisk, kNewInArchive, kOldInArchive, kSameFiles, kUnknowNewerFiles }; } namespace NPairAction { enum EEnum { kIgnore = 0, kCopy, kCompress, kCompressAsAnti }; } struct CActionSet { NPairAction::EEnum StateActions[NPairState::kNumValues]; bool NeedScanning() const { int i; for (i = 0; i < NPairState::kNumValues; i++) if (StateActions[i] == NPairAction::kCompress) return true; for (i = 1; i < NPairState::kNumValues; i++) if (StateActions[i] != NPairAction::kIgnore) return true; return false; } }; extern const CActionSet kAddActionSet; extern const CActionSet kUpdateActionSet; extern const CActionSet kFreshActionSet; extern const CActionSet kSynchronizeActionSet; extern const CActionSet kDeleteActionSet; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateCallback.cpp ================================================ // UpdateCallback.cpp #include "StdAfx.h" #include "UpdateCallback.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" #include "Common/Defs.h" #include "Common/ComTry.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): Callback(0), ShareForWrite(false), StdInMode(false), DirItems(0), ArcItems(0), UpdatePairs(0), NewNames(0) {} STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size) { COM_TRY_BEGIN return Callback->SetTotal(size); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue) { COM_TRY_BEGIN return Callback->SetCompleted(completeValue); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { COM_TRY_BEGIN return Callback->SetRatioInfo(inSize, outSize); COM_TRY_END } /* STATPROPSTG kProperties[] = { { NULL, kpidPath, VT_BSTR}, { NULL, kpidIsDir, VT_BOOL}, { NULL, kpidSize, VT_UI8}, { NULL, kpidCTime, VT_FILETIME}, { NULL, kpidATime, VT_FILETIME}, { NULL, kpidMTime, VT_FILETIME}, { NULL, kpidAttrib, VT_UI4}, { NULL, kpidIsAnti, VT_BOOL} }; STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **) { return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator); } */ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) { COM_TRY_BEGIN RINOK(Callback->CheckBreak()); const CUpdatePair2 &up = (*UpdatePairs)[index]; if (newData != NULL) *newData = BoolToInt(up.NewData); if (newProps != NULL) *newProps = BoolToInt(up.NewProps); if (indexInArchive != NULL) { *indexInArchive = (UInt32)-1; if (up.ExistInArchive()) *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer; } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NWindows::NCOM::CPropVariant prop; if (propID == kpidIsAnti) { prop = up.IsAnti; prop.Detach(value); return S_OK; } if (up.IsAnti) { switch(propID) { case kpidIsDir: case kpidPath: break; case kpidSize: prop = (UInt64)0; prop.Detach(value); return S_OK; default: prop.Detach(value); return S_OK; } } if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch(propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; } } else { if (propID == kpidPath) { if (up.NewNameIndex >= 0) { prop = (*NewNames)[up.NewNameIndex]; prop.Detach(value); return S_OK; } } if (up.ExistInArchive() && Archive) { UInt32 indexInArchive; if (ArcItems == 0) indexInArchive = up.ArcIndex; else indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer; return Archive->GetProperty(indexInArchive, propID, value); } } prop.Detach(value); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); RINOK(Callback->Finilize()); if (up.IsAnti) { return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true); } const CDirItem &di = DirItems->Items[up.DirIndex]; RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false)); if (di.IsDir()) return S_OK; if (StdInMode) { CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); const UString path = DirItems->GetPhyPath(up.DirIndex); if (!inStreamSpec->OpenShared(path, ShareForWrite)) { return Callback->OpenFileError(path, ::GetLastError()); } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult) { COM_TRY_BEGIN return Callback->SetOperationResult(operationResult); COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) { if (VolumesSizes.Size() == 0) return S_FALSE; if (index >= (UInt32)VolumesSizes.Size()) index = VolumesSizes.Size() - 1; *size = VolumesSizes[index]; return S_OK; } STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN wchar_t temp[32]; ConvertUInt64ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; UString fileName = VolName; fileName += L'.'; fileName += res; fileName += VolExt; COutFileStream *streamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> streamLoc(streamSpec); if (!streamSpec->Create(fileName, false)) return ::GetLastError(); *volumeStream = streamLoc.Detach(); return S_OK; COM_TRY_END } STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { COM_TRY_BEGIN return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateCallback.h ================================================ // UpdateCallback.h #ifndef __UPDATECALLBACK_H #define __UPDATECALLBACK_H #include "Common/MyCom.h" #include "Common/MyString.h" #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdatePair.h" #include "../Common/UpdateProduce.h" #define INTERFACE_IUpdateCallbackUI(x) \ virtual HRESULT SetTotal(UInt64 size) x; \ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \ virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \ virtual HRESULT CheckBreak() x; \ virtual HRESULT Finilize() x; \ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \ virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; struct IUpdateCallbackUI { INTERFACE_IUpdateCallbackUI(=0) }; class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public ICompressProgressInfo, public CMyUnknownImp { public: MY_UNKNOWN_IMP3( IArchiveUpdateCallback2, ICryptoGetTextPassword2, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); public: CRecordVector<UInt64> VolumesSizes; UString VolName; UString VolExt; IUpdateCallbackUI *Callback; bool ShareForWrite; bool StdInMode; const CDirItems *DirItems; const CObjectVector<CArcItem> *ArcItems; const CRecordVector<CUpdatePair2> *UpdatePairs; const UStringVector *NewNames; CMyComPtr<IInArchive> Archive; CArchiveUpdateCallback(); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdatePair.cpp ================================================ // UpdatePair.cpp #include "StdAfx.h" #include <time.h> #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "UpdatePair.h" #include "SortUtils.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime)) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: if (ai.SizeDefined) if (di.Size != ai.Size) pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; else pair.State = NUpdateArchive::NPairState::kSameFiles; else pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdatePair.h ================================================ // UpdatePair.h #ifndef __UPDATE_PAIR_H #define __UPDATE_PAIR_H #include "DirItem.h" #include "UpdateAction.h" #include "../../Archive/IArchive.h" struct CUpdatePair { NUpdateArchive::NPairState::EEnum State; int ArcIndex; int DirIndex; CUpdatePair(): ArcIndex(-1), DirIndex(-1) {} }; void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector<CArcItem> &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector<CUpdatePair> &updatePairs); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateProduce.cpp ================================================ // UpdateProduce.cpp #include "StdAfx.h" #include "UpdateProduce.h" using namespace NUpdateArchive; static const char *kUpdateActionSetCollision = "Internal collision in update action set"; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback) { for (int i = 0; i < updatePairs.Size(); i++) { const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; up2.IsAnti = false; up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; switch(actionSet.StateActions[pair.State]) { case NPairAction::kIgnore: /* if (pair.State != NPairState::kOnlyOnDisk) IgnoreArchiveItem(m_ArchiveItems[pair.ArcIndex]); // cout << "deleting"; */ if (callback) callback->ShowDeleteFile(pair.ArcIndex); continue; case NPairAction::kCopy: if (pair.State == NPairState::kOnlyOnDisk) throw kUpdateActionSetCollision; up2.NewData = up2.NewProps = false; break; case NPairAction::kCompress: if (pair.State == NPairState::kOnlyInArchive || pair.State == NPairState::kNotMasked) throw kUpdateActionSetCollision; break; case NPairAction::kCompressAsAnti: up2.IsAnti = true; break; } operationChain.Add(up2); } operationChain.ReserveDown(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/UpdateProduce.h ================================================ // UpdateProduce.h #ifndef __UPDATE_PRODUCE_H #define __UPDATE_PRODUCE_H #include "UpdatePair.h" struct CUpdatePair2 { bool NewData; bool NewProps; bool IsAnti; int DirIndex; int ArcIndex; int NewNameIndex; bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {} }; struct IUpdateProduceCallback { virtual HRESULT ShowDeleteFile(int arcIndex) = 0; }; void UpdateProduce( const CRecordVector<CUpdatePair> &updatePairs, const NUpdateArchive::CActionSet &actionSet, CRecordVector<CUpdatePair2> &operationChain, IUpdateProduceCallback *callback); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/WorkDir.cpp ================================================ // WorkDir.cpp #include "StdAfx.h" #include "WorkDir.h" #include "Common/StringConvert.h" #include "Common/Wildcard.h" #include "Windows/FileName.h" #include "Windows/FileDir.h" static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } using namespace NWindows; using namespace NFile; using namespace NName; UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path) { NWorkDir::NMode::EEnum mode = workDirInfo.Mode; if (workDirInfo.ForRemovableOnly) { mode = NWorkDir::NMode::kCurrent; UString prefix = path.Left(3); if (prefix[1] == L':' && prefix[2] == L'\\') { UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage())); if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE) mode = workDirInfo.Mode; } /* CParsedPath parsedPath; parsedPath.ParsePath(archiveName); UINT driveType = GetDriveType(parsedPath.Prefix); if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE)) mode = NZipSettings::NWorkDir::NMode::kCurrent; */ } switch(mode) { case NWorkDir::NMode::kCurrent: { return ExtractDirPrefixFromPath(path); } case NWorkDir::NMode::kSpecified: { UString tempDir = workDirInfo.Path; NormalizeDirPathPrefix(tempDir); return tempDir; } default: { UString tempDir; if(!NFile::NDirectory::MyGetTempPath(tempDir)) throw 141717; return tempDir; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/WorkDir.h ================================================ // WorkDir.h #ifndef __WORKDIR_H #define __WORKDIR_H #include "ZipRegistry.h" UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Common/ZipRegistry.h ================================================ // ZipRegistry.h #ifndef __ZIPREGISTRY_H #define __ZIPREGISTRY_H #include "Common/MyString.h" #include "Common/Types.h" #include "ExtractMode.h" namespace NExtract { struct CInfo { NPathMode::EEnum PathMode; NOverwriteMode::EEnum OverwriteMode; UStringVector Paths; bool ShowPassword; }; } namespace NCompression { struct CFormatOptions { CSysString FormatID; UString Options; UString Method; UString EncryptionMethod; UInt32 Level; UInt32 Dictionary; UInt32 Order; UInt32 BlockLogSize; UInt32 NumThreads; void ResetForLevelChange() { BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); Method.Empty(); // EncryptionMethod.Empty(); // Options.Empty(); } CFormatOptions() { ResetForLevelChange(); } }; struct CInfo { UStringVector HistoryArchives; UInt32 Level; UString ArchiveType; CObjectVector<CFormatOptions> FormatOptionsVector; bool ShowPassword; bool EncryptHeaders; }; } namespace NWorkDir{ namespace NMode { enum EEnum { kSystem, kCurrent, kSpecified }; } struct CInfo { NMode::EEnum Mode; UString Path; bool ForRemovableOnly; void SetForRemovableOnlyDefault() { ForRemovableOnly = true; } void SetDefault() { Mode = NMode::kSystem; Path.Empty(); SetForRemovableOnlyDefault(); } }; } void SaveExtractionInfo(const NExtract::CInfo &info); void ReadExtractionInfo(NExtract::CInfo &info); void SaveCompressionInfo(const NCompression::CInfo &info); void ReadCompressionInfo(NCompression::CInfo &info); void SaveWorkDirInfo(const NWorkDir::CInfo &info); void ReadWorkDirInfo(NWorkDir::CInfo &info); void SaveCascadedMenu(bool enabled); bool ReadCascadedMenu(); void SaveContextMenuStatus(UInt32 value); bool ReadContextMenuStatus(UInt32 &value); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/ConsoleClose.cpp ================================================ // ConsoleClose.cpp #include "StdAfx.h" #include "ConsoleClose.h" static int g_BreakCounter = 0; static const int kBreakAbortThreshold = 2; namespace NConsoleClose { static BOOL WINAPI HandlerRoutine(DWORD ctrlType) { if (ctrlType == CTRL_LOGOFF_EVENT) { // printf("\nCTRL_LOGOFF_EVENT\n"); return TRUE; } g_BreakCounter++; if (g_BreakCounter < kBreakAbortThreshold) return TRUE; return FALSE; /* switch(ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: if (g_BreakCounter < kBreakAbortThreshold) return TRUE; } return FALSE; */ } bool TestBreakSignal() { /* if (g_BreakCounter > 0) return true; */ return (g_BreakCounter > 0); } void CheckCtrlBreak() { if (TestBreakSignal()) throw CCtrlBreakException(); } CCtrlHandlerSetter::CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE)) throw "SetConsoleCtrlHandler fails"; } CCtrlHandlerSetter::~CCtrlHandlerSetter() { if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE)) throw "SetConsoleCtrlHandler fails"; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/ConsoleClose.h ================================================ // ConsoleCloseUtils.h #ifndef __CONSOLECLOSEUTILS_H #define __CONSOLECLOSEUTILS_H namespace NConsoleClose { bool TestBreakSignal(); class CCtrlHandlerSetter { public: CCtrlHandlerSetter(); virtual ~CCtrlHandlerSetter(); }; class CCtrlBreakException {}; void CheckCtrlBreak(); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp ================================================ // ExtractCallbackConsole.h #include "StdAfx.h" #include "ExtractCallbackConsole.h" #include "UserInputUtils.h" #include "ConsoleClose.h" #include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" #include "Windows/Time.h" #include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "Windows/Error.h" #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" using namespace NWindows; using namespace NFile; using namespace NDirectory; static const char *kTestString = "Testing "; static const char *kExtractString = "Extracting "; static const char *kSkipString = "Skipping "; // static const char *kCantAutoRename = "can not create file with auto name\n"; // static const char *kCantRenameFile = "can not rename existing file\n"; // static const char *kCantDeleteOutputFile = "can not delete output file "; static const char *kError = "ERROR: "; static const char *kMemoryExceptionMessage = "Can't allocate required memory!"; static const char *kProcessing = "Processing archive: "; static const char *kEverythingIsOk = "Everything is Ok"; static const char *kNoFiles = "No files to process"; static const char *kUnsupportedMethod = "Unsupported Method"; static const char *kCrcFailed = "CRC Failed"; static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?"; static const char *kDataError = "Data Error"; static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?"; static const char *kUnknownError = "Unknown Error"; STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } STDMETHODIMP CExtractCallbackConsole::AskOverwrite( const wchar_t *existName, const FILETIME *, const UInt64 *, const wchar_t *newName, const FILETIME *, const UInt64 *, Int32 *answer) { (*OutStream) << "file " << existName << "\nalready exists. Overwrite with " << endl; (*OutStream) << newName; NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream); switch(overwriteAnswer) { case NUserAnswerMode::kQuit: return E_ABORT; case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break; case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break; case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break; case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break; case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break; default: return E_FAIL; } return S_OK; } STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position) { switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break; case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break; case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break; }; (*OutStream) << name; if (position != 0) (*OutStream) << " <" << *position << ">"; return S_OK; } STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message) { (*OutStream) << message << endl; NumFileErrorsInCurrentArchive++; NumFileErrors++; return S_OK; } STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted) { switch(operationResult) { case NArchive::NExtract::NOperationResult::kOK: break; default: { NumFileErrorsInCurrentArchive++; NumFileErrors++; (*OutStream) << " "; switch(operationResult) { case NArchive::NExtract::NOperationResult::kUnSupportedMethod: (*OutStream) << kUnsupportedMethod; break; case NArchive::NExtract::NOperationResult::kCRCError: (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed); break; case NArchive::NExtract::NOperationResult::kDataError: (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError); break; default: (*OutStream) << kUnknownError; } } } (*OutStream) << endl; return S_OK; } #ifndef _NO_CRYPTO HRESULT CExtractCallbackConsole::SetPassword(const UString &password) { PasswordIsDefined = true; Password = password; return S_OK; } STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password) { if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } #endif HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name) { NumArchives++; NumFileErrorsInCurrentArchive = 0; (*OutStream) << endl << kProcessing << name << endl; return S_OK; } HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted) { (*OutStream) << endl; if (result != S_OK) { (*OutStream) << "Error: "; if (result == S_FALSE) { (*OutStream) << (encrypted ? "Can not open encrypted archive. Wrong password?" : "Can not open file as archive"); } else { if (result == E_OUTOFMEMORY) (*OutStream) << "Can't allocate required memory"; else (*OutStream) << NError::MyFormatMessage(result); } (*OutStream) << endl; NumArchiveErrors++; } return S_OK; } HRESULT CExtractCallbackConsole::ThereAreNoFiles() { (*OutStream) << endl << kNoFiles << endl; return S_OK; } HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result) { if (result == S_OK) { (*OutStream) << endl; if (NumFileErrorsInCurrentArchive == 0) (*OutStream) << kEverythingIsOk << endl; else { NumArchiveErrors++; (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl; } } if (result == S_OK) return result; NumArchiveErrors++; if (result == E_ABORT || result == ERROR_DISK_FULL) return result; (*OutStream) << endl << kError; if (result == E_OUTOFMEMORY) (*OutStream) << kMemoryExceptionMessage; else { UString message; NError::MyFormatMessage(result, message); (*OutStream) << message; } (*OutStream) << endl; return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/ExtractCallbackConsole.h ================================================ // ExtractCallbackConsole.h #ifndef __EXTRACTCALLBACKCONSOLE_H #define __EXTRACTCALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "../../Common/FileStreams.h" #include "../../IPassword.h" #include "../../Archive/IArchive.h" #include "../Common/ArchiveExtractCallback.h" class CExtractCallbackConsole: public IExtractCallbackUI, #ifndef _NO_CRYPTO public ICryptoGetTextPassword, #endif public CMyUnknownImp { public: MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback) #ifndef _NO_CRYPTO MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(SetTotal)(UInt64 total); STDMETHOD(SetCompleted)(const UInt64 *completeValue); // IFolderArchiveExtractCallback STDMETHOD(AskOverwrite)( const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, Int32 *answer); STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position); STDMETHOD(MessageError)(const wchar_t *message); STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted); HRESULT BeforeOpen(const wchar_t *name); HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted); HRESULT ThereAreNoFiles(); HRESULT ExtractResult(HRESULT result); #ifndef _NO_CRYPTO HRESULT SetPassword(const UString &password); STDMETHOD(CryptoGetTextPassword)(BSTR *password); bool PasswordIsDefined; UString Password; #endif UInt64 NumArchives; UInt64 NumArchiveErrors; UInt64 NumFileErrors; UInt64 NumFileErrorsInCurrentArchive; CStdOutStream *OutStream; void Init() { NumArchives = 0; NumArchiveErrors = 0; NumFileErrors = 0; NumFileErrorsInCurrentArchive = 0; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/List.cpp ================================================ // List.cpp #include "StdAfx.h" #include "List.h" #include "ConsoleClose.h" #include "Common/StringConvert.h" #include "Common/StdOutStream.h" #include "Common/IntToString.h" #include "Common/MyCom.h" #include "Windows/PropVariant.h" #include "Windows/Defs.h" #include "Windows/PropVariantConversions.h" #include "Windows/FileDir.h" #include "Windows/Error.h" #include "../../Archive/IArchive.h" #include "../Common/PropIDUtils.h" #include "../Common/OpenArchive.h" #include "OpenCallbackConsole.h" using namespace NWindows; struct CPropIdToName { PROPID PropID; const wchar_t *Name; }; static CPropIdToName kPropIdToName[] = { { kpidPath, L"Path" }, { kpidName, L"Name" }, { kpidIsDir, L"Folder" }, { kpidSize, L"Size" }, { kpidPackSize, L"Packed Size" }, { kpidAttrib, L"Attributes" }, { kpidCTime, L"Created" }, { kpidATime, L"Accessed" }, { kpidMTime, L"Modified" }, { kpidSolid, L"Solid" }, { kpidCommented, L"Commented" }, { kpidEncrypted, L"Encrypted" }, { kpidSplitBefore, L"Split Before" }, { kpidSplitAfter, L"Split After" }, { kpidDictionarySize, L"Dictionary Size" }, { kpidCRC, L"CRC" }, { kpidType, L"Type" }, { kpidIsAnti, L"Anti" }, { kpidMethod, L"Method" }, { kpidHostOS, L"Host OS" }, { kpidFileSystem, L"File System" }, { kpidUser, L"User" }, { kpidGroup, L"Group" }, { kpidBlock, L"Block" }, { kpidComment, L"Comment" }, { kpidPosition, L"Position" }, { kpidPrefix, L"Prefix" }, { kpidNumSubDirs, L"Folders" }, { kpidNumSubFiles, L"Files" }, { kpidUnpackVer, L"Version" }, { kpidVolume, L"Volume" }, { kpidIsVolume, L"Multivolume" }, { kpidOffset, L"Offset" }, { kpidLinks, L"Links" }, { kpidNumBlocks, L"Blocks" }, { kpidNumVolumes, L"Volumes" }, { kpidBit64, L"64-bit" }, { kpidBigEndian, L"Big-endian" }, { kpidCpu, L"CPU" }, { kpidPhySize, L"Physical Size" }, { kpidHeadersSize, L"Headers Size" }, { kpidChecksum, L"Checksum" }, { kpidCharacts, L"Characteristics" }, { kpidVa, L"Virtual Address" }, { kpidFreeSpace, L"Free Space" }, { kpidClusterSize, L"Cluster Size" } }; static const char kEmptyAttribChar = '.'; static const char *kListing = "Listing archive: "; static const wchar_t *kFilesMessage = L"files"; static const wchar_t *kDirsMessage = L"folders"; static void GetAttribString(DWORD wa, bool isDir, char *s) { s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar; s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar; s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar; s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar; s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar; s[5] = '\0'; } enum EAdjustment { kLeft, kCenter, kRight }; struct CFieldInfo { PROPID PropID; UString Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; struct CFieldInfoInit { PROPID PropID; const wchar_t *Name; EAdjustment TitleAdjustment; EAdjustment TextAdjustment; int PrefixSpacesWidth; int Width; }; CFieldInfoInit kStandardFieldTable[] = { { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 }, { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 }, { kpidSize, L"Size", kRight, kRight, 1, 12 }, { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 }, { kpidPath, L"Name", kLeft, kLeft, 2, 24 } }; void PrintSpaces(int numSpaces) { for (int i = 0; i < numSpaces; i++) g_StdOut << ' '; } void PrintString(EAdjustment adjustment, int width, const UString &textString) { const int numSpaces = width - textString.Length(); int numLeftSpaces = 0; switch (adjustment) { case kLeft: numLeftSpaces = 0; break; case kCenter: numLeftSpaces = numSpaces / 2; break; case kRight: numLeftSpaces = numSpaces; break; } PrintSpaces(numLeftSpaces); g_StdOut << textString; PrintSpaces(numSpaces - numLeftSpaces); } class CFieldPrinter { CObjectVector<CFieldInfo> _fields; public: void Clear() { _fields.Clear(); } void Init(const CFieldInfoInit *standardFieldTable, int numItems); HRESULT Init(IInArchive *archive); void PrintTitle(); void PrintTitleLines(); HRESULT PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode); HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize); }; void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems) { Clear(); for (int i = 0; i < numItems; i++) { CFieldInfo fieldInfo; const CFieldInfoInit &fieldInfoInit = standardFieldTable[i]; fieldInfo.PropID = fieldInfoInit.PropID; fieldInfo.Name = fieldInfoInit.Name; fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment; fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment; fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth; fieldInfo.Width = fieldInfoInit.Width; _fields.Add(fieldInfo); } } static UString GetPropName(PROPID propID, BSTR name) { for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++) { const CPropIdToName &propIdToName = kPropIdToName[i]; if (propIdToName.PropID == propID) return propIdToName.Name; } if (name) return name; wchar_t s[32]; ConvertUInt64ToString(propID, s); return s; } HRESULT CFieldPrinter::Init(IInArchive *archive) { Clear(); UInt32 numProps; RINOK(archive->GetNumberOfProperties(&numProps)); for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt)); CFieldInfo fieldInfo; fieldInfo.PropID = propID; fieldInfo.Name = GetPropName(propID, name); _fields.Add(fieldInfo); } return S_OK; } void CFieldPrinter::PrintTitle() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); PrintString(fieldInfo.TitleAdjustment, ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name); } } void CFieldPrinter::PrintTitleLines() { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); for (int i = 0; i < fieldInfo.Width; i++) g_StdOut << '-'; } } BOOL IsFileTimeZero(CONST FILETIME *lpFileTime) { return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0); } static const char *kEmptyTimeString = " "; void PrintTime(const NCOM::CPropVariant &prop) { if (prop.vt != VT_FILETIME) throw "incorrect item"; if (IsFileTimeZero(&prop.filetime)) g_StdOut << kEmptyTimeString; else { FILETIME localFileTime; if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) throw "FileTimeToLocalFileTime error"; char s[32]; if (ConvertFileTimeToString(localFileTime, s, true, true)) g_StdOut << s; else g_StdOut << kEmptyTimeString; } } HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, const UString &defaultItemName, UInt32 index, bool techMode) { /* if (techMode) { g_StdOut << "Index = "; g_StdOut << (UInt64)index; g_StdOut << endl; } */ for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; if (!techMode) PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidPath) { UString s; RINOK(GetArchiveItemPath(archive, index, defaultItemName, s)); prop = s; } else { RINOK(archive->GetProperty(index, fieldInfo.PropID, &prop)); } if (techMode) { g_StdOut << fieldInfo.Name << " = "; } int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width; if (prop.vt == VT_EMPTY) { switch(fieldInfo.PropID) { case kpidPath: prop = defaultItemName; break; default: if (techMode) g_StdOut << endl; else PrintSpaces(width); continue; } } if (fieldInfo.PropID == kpidMTime) { PrintTime(prop); } else if (fieldInfo.PropID == kpidAttrib) { if (prop.vt != VT_UI4) throw "incorrect item"; UInt32 attributes = prop.ulVal; bool isFolder; RINOK(IsArchiveItemFolder(archive, index, isFolder)); char s[8]; GetAttribString(attributes, isFolder, s); g_StdOut << s; } else if (prop.vt == VT_BSTR) { if (techMode) g_StdOut << prop.bstrVal; else PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal); } else { UString s = ConvertPropertyToString(prop, fieldInfo.PropID); s.Replace(wchar_t(0xA), L' '); s.Replace(wchar_t(0xD), L' '); if (techMode) g_StdOut << s; else PrintString(fieldInfo.TextAdjustment, width, s); } if (techMode) g_StdOut << endl; } return S_OK; } void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value) { wchar_t textString[32] = { 0 }; if (value != NULL) ConvertUInt64ToString(*value, textString); PrintString(adjustment, width, textString); } HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, const UInt64 *size, const UInt64 *compressedSize) { for (int i = 0; i < _fields.Size(); i++) { const CFieldInfo &fieldInfo = _fields[i]; PrintSpaces(fieldInfo.PrefixSpacesWidth); NCOM::CPropVariant prop; if (fieldInfo.PropID == kpidSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size); else if (fieldInfo.PropID == kpidPackSize) PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize); else if (fieldInfo.PropID == kpidPath) { wchar_t textString[32]; ConvertUInt64ToString(numFiles, textString); UString temp = textString; temp += L" "; temp += kFilesMessage; temp += L", "; ConvertUInt64ToString(numDirs, textString); temp += textString; temp += L" "; temp += kDirsMessage; PrintString(fieldInfo.TextAdjustment, 0, temp); } else PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L""); } return S_OK; } bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value) { NCOM::CPropVariant prop; if (archive->GetProperty(index, propID, &prop) != S_OK) throw "GetPropertyValue error"; if (prop.vt == VT_EMPTY) return false; value = ConvertPropVariantToUInt64(prop); return true; } HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archiveName, fi) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) g_StdOut << "is not supported archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/List.h ================================================ // List.h #ifndef __LIST_H #define __LIST_H #include "Common/Wildcard.h" #include "../Common/LoadCodecs.h" HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &errors); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/Main.cpp ================================================ // Main.cpp #include "StdAfx.h" #include "Common/MyInitGuid.h" #include "Common/CommandLineParser.h" #include "Common/MyException.h" #include "Common/IntToString.h" #include "Common/StdOutStream.h" #include "Common/StringConvert.h" #include "Common/StringToInt.h" #include "Windows/FileDir.h" #include "Windows/FileName.h" #include "Windows/Defs.h" #include "Windows/Error.h" #ifdef _WIN32 #include "Windows/MemoryLock.h" #endif #include "../../IPassword.h" #include "../../ICoder.h" #include "../Common/UpdateAction.h" #include "../Common/Update.h" #include "../Common/Extract.h" #include "../Common/ArchiveCommandLine.h" #include "../Common/ExitCode.h" #ifdef EXTERNAL_CODECS #include "../Common/LoadCodecs.h" #endif #include "../../Compress/LZMA_Alone/LzmaBenchCon.h" #include "List.h" #include "OpenCallbackConsole.h" #include "ExtractCallbackConsole.h" #include "UpdateCallbackConsole.h" #include "../../MyVersion.h" #if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES) extern "C" { #include "../../../../C/Alloc.h" } #endif using namespace NWindows; using namespace NFile; using namespace NCommandLineParser; HINSTANCE g_hInstance = 0; extern CStdOutStream *g_StdStream; static const char *kCopyrightString = "\n7-Zip" #ifndef EXTERNAL_CODECS " (A)" #endif #ifdef _WIN64 " [64]" #endif " " MY_VERSION_COPYRIGHT_DATE "\n"; static const char *kHelpString = "\nUsage: 7z" #ifdef _NO_CRYPTO "r" #else #ifndef EXTERNAL_CODECS "a" #endif #endif " <command> [<switches>...] <archive_name> [<file_names>...]\n" " [<@listfiles...>]\n" "\n" "<Commands>\n" " a: Add files to archive\n" " b: Benchmark\n" " d: Delete files from archive\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" // " l[a|t][f]: List contents of archive\n" // " a - with Additional fields\n" // " t - with all fields\n" // " f - with Full pathnames\n" " t: Test integrity of archive\n" " u: Update files to archive\n" " x: eXtract files with full paths\n" "<Switches>\n" " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n" " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n" " -bd: Disable percentage indicator\n" " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n" " -m{Parameters}: set compression Method\n" " -o{Directory}: set Output directory\n" #ifndef _NO_CRYPTO " -p{Password}: set Password\n" #endif " -r[-|0]: Recurse subdirectories\n" " -scs{UTF-8 | WIN | DOS}: set charset for list files\n" " -sfx[{name}]: Create SFX archive\n" " -si[{name}]: read data from stdin\n" " -slt: show technical information for l (List) command\n" " -so: write data to stdout\n" " -ssc[-]: set sensitive case mode\n" " -ssw: compress shared files\n" " -t{Type}: Set type of archive\n" " -v{Size}[b|k|m|g]: Create volumes\n" " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n" " -w[{path}]: assign Work directory. Empty path means a temporary directory\n" " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n" " -y: assume Yes on all queries\n"; // --------------------------- // exception messages static const char *kEverythingIsOk = "Everything is Ok"; static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError static const char *kNoFormats = "7-Zip cannot find the code that works with archives."; static const wchar_t *kDefaultSfxModule = L"7zCon.sfx"; static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code) { s << message << endl; throw code; } static void PrintHelpAndExit(CStdOutStream &s) // yyy { s << kHelpString; ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError); } #ifndef _WIN32 static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts) { parts.Clear(); for(int i = 0; i < numArguments; i++) { UString s = MultiByteToUnicodeString(arguments[i]); parts.Add(s); } } #endif static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp) { s << kCopyrightString; // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n"; if (needHelp) s << kHelpString; } #ifdef EXTERNAL_CODECS static void PrintString(CStdOutStream &stdStream, const AString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } #endif static void PrintString(CStdOutStream &stdStream, const UString &s, int size) { int len = s.Length(); stdStream << s; for (int i = len; i < size; i++) stdStream << ' '; } static inline char GetHex(Byte value) { return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); } const char *kUnsupportedArcTypeMessage = "Unsupported archive type"; int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif if(commandStrings.Size() == 1) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } commandStrings.Delete(0); CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); if(options.HelpMode) { ShowCopyrightAndHelp(g_StdOut, true); return 0; } #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) { SetLargePageSize(); NSecurity::EnableLockMemoryPrivilege(); } #endif CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut; g_StdStream = &stdStream; if (options.EnableHeaders) ShowCopyrightAndHelp(stdStream, false); parser.Parse2(options); CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) throw kUnsupportedArcTypeMessage; if (options.Command.CommandType == NCommandType::kInfo) { stdStream << endl << "Formats:" << endl; int i; for (i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &arc = codecs->Formats[i]; #ifdef EXTERNAL_CODECS if (arc.LibIndex >= 0) { char s[32]; ConvertUInt64ToString(arc.LibIndex, s); PrintString(stdStream, s, 2); } else #endif stdStream << " "; stdStream << ' '; stdStream << (char)(arc.UpdateEnabled ? 'C' : ' '); stdStream << (char)(arc.KeepName ? 'K' : ' '); stdStream << " "; PrintString(stdStream, arc.Name, 6); stdStream << " "; UString s; for (int t = 0; t < arc.Exts.Size(); t++) { const CArcExtInfo &ext = arc.Exts[t]; s += ext.Ext; if (!ext.AddExt.IsEmpty()) { s += L" ("; s += ext.AddExt; s += L')'; } s += L' '; } PrintString(stdStream, s, 14); stdStream << " "; const CByteBuffer &sig = arc.StartSignature; for (size_t j = 0; j < sig.GetCapacity(); j++) { Byte b = sig[j]; if (b > 0x20 && b < 0x80) { stdStream << (char)b; } else { stdStream << GetHex((Byte)((b >> 4) & 0xF)); stdStream << GetHex((Byte)(b & 0xF)); } stdStream << ' '; } stdStream << endl; } stdStream << endl << "Codecs:" << endl; #ifdef EXTERNAL_CODECS UInt32 numMethods; if (codecs->GetNumberOfMethods(&numMethods) == S_OK) for (UInt32 j = 0; j < numMethods; j++) { int libIndex = codecs->GetCodecLibIndex(j); if (libIndex >= 0) { char s[32]; ConvertUInt64ToString(libIndex, s); PrintString(stdStream, s, 2); } else stdStream << " "; stdStream << ' '; stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' '); UInt64 id; stdStream << " "; HRESULT res = codecs->GetCodecId(j, id); if (res != S_OK) id = (UInt64)(Int64)-1; char s[32]; ConvertUInt64ToString(id, s, 16); PrintString(stdStream, s, 8); stdStream << " "; PrintString(stdStream, codecs->GetCodecName(j), 11); stdStream << endl; /* if (res != S_OK) throw "incorrect Codec ID"; */ } #endif return S_OK; } else if (options.Command.CommandType == NCommandType::kBenchmark) { if (options.Method.CompareNoCase(L"CRC") == 0) { HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nCRC Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } else { HRESULT res = LzmaBenchCon( #ifdef EXTERNAL_LZMA codecs, #endif (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize); if (res != S_OK) { if (res == S_FALSE) { stdStream << "\nDecoding Error\n"; return NExitCode::kFatalError; } throw CSystemException(res); } } } else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) { if(isExtractGroupCommand) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = &stdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = options.PasswordEnabled; openCallback.Password = options.Password; #endif CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.OverwriteMode = options.OverwriteMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; #ifdef COMPRESS_MT eo.Properties = options.ExtractProperties; #endif UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { stdStream << endl << "Error: " << errorMessage; if (result == S_OK) result = E_FAIL; } stdStream << endl; if (ecs->NumArchives > 1) stdStream << "Archives: " << ecs->NumArchives << endl; if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchives > 1) { stdStream << endl; if (ecs->NumArchiveErrors != 0) stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl; } if (result != S_OK) throw CSystemException(result); return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); if (stat.NumFolders != 0) stdStream << "Folders: " << stat.NumFolders << endl; if (stat.NumFiles != 1 || stat.NumFolders != 0) stdStream << "Files: " << stat.NumFiles << endl; stdStream << "Size: " << stat.UnpackSize << endl << "Compressed: " << stat.PackSize << endl; } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, options.EnableHeaders, options.TechMode, #ifndef _NO_CRYPTO options.PasswordEnabled, options.Password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } else if(options.Command.IsFromUpdateGroup()) { UString workingDir; CUpdateOptions &uo = options.UpdateOptions; if (uo.SfxMode && uo.SfxModule.IsEmpty()) uo.SfxModule = kDefaultSfxModule; COpenCallbackConsole openCallback; openCallback.OutStream = &stdStream; #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); openCallback.PasswordIsDefined = passwordIsDefined; openCallback.Password = options.Password; #endif CUpdateCallbackConsole callback; callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif callback.StdOutMode = uo.StdOutMode; callback.Init(&stdStream); CUpdateErrorInfo errorInfo; if (!uo.Init(codecs, formatIndices, options.ArchiveName)) throw kUnsupportedArcTypeMessage; HRESULT result = UpdateArchive(codecs, options.WildcardCensor, uo, errorInfo, &openCallback, &callback); int exitCode = NExitCode::kSuccess; if (callback.CantFindFiles.Size() > 0) { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; int numErrors = callback.CantFindFiles.Size(); for (int i = 0; i < numErrors; i++) { stdStream << callback.CantFindFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot find " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } if (result != S_OK) { UString message; if (!errorInfo.Message.IsEmpty()) { message += errorInfo.Message; message += L"\n"; } if (!errorInfo.FileName.IsEmpty()) { message += errorInfo.FileName; message += L"\n"; } if (!errorInfo.FileName2.IsEmpty()) { message += errorInfo.FileName2; message += L"\n"; } if (errorInfo.SystemError != 0) { message += NError::MyFormatMessageW(errorInfo.SystemError); message += L"\n"; } if (!message.IsEmpty()) stdStream << L"\nError:\n" << message; throw CSystemException(result); } int numErrors = callback.FailedFiles.Size(); if (numErrors == 0) { if (callback.CantFindFiles.Size() == 0) stdStream << kEverythingIsOk << endl; } else { stdStream << endl; stdStream << "WARNINGS for files:" << endl << endl; for (int i = 0; i < numErrors; i++) { stdStream << callback.FailedFiles[i] << " : "; stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl; } stdStream << "----------------" << endl; stdStream << "WARNING: Cannot open " << numErrors << " file"; if (numErrors > 1) stdStream << "s"; stdStream << endl; exitCode = NExitCode::kWarning; } return exitCode; } else PrintHelpAndExit(stdStream); return 0; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/MainAr.cpp ================================================ // MainAr.cpp #include "StdAfx.h" // #include <locale.h> #include "Windows/Error.h" #include "Common/StdOutStream.h" #include "Common/NewHandler.h" #include "Common/MyException.h" #include "Common/StringConvert.h" #include "../Common/ExitCode.h" #include "../Common/ArchiveCommandLine.h" #include "ConsoleClose.h" using namespace NWindows; CStdOutStream *g_StdStream = 0; #ifdef _WIN32 #ifndef _UNICODE bool g_IsNT = false; #endif #if !defined(_UNICODE) || !defined(_WIN64) static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif #endif extern int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ); static const char *kExceptionErrorMessage = "\n\nError:\n"; static const char *kUserBreak = "\nBreak signaled\n"; static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n"; static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n"; static const char *kInternalExceptionMessage = "\n\nInternal Error #"; int MY_CDECL main ( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { g_StdStream = &g_StdOut; #ifdef _WIN32 #ifdef _UNICODE #ifndef _WIN64 if (!IsItWindowsNT()) { (*g_StdStream) << "This program requires Windows NT/2000/2003/2008/XP/Vista"; return NExitCode::kFatalError; } #endif #else g_IsNT = IsItWindowsNT(); #endif #endif // setlocale(LC_COLLATE, ".OCP"); NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter; int res = 0; try { res = Main2( #ifndef _WIN32 numArguments, arguments #endif ); } catch(const CNewException &) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } catch(const NConsoleClose::CCtrlBreakException &) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } catch(const CArchiveCommandLineException &e) { (*g_StdStream) << kExceptionErrorMessage << e << endl; return (NExitCode::kUserError); } catch(const CSystemException &systemError) { if (systemError.ErrorCode == E_OUTOFMEMORY) { (*g_StdStream) << kMemoryExceptionMessage; return (NExitCode::kMemoryError); } if (systemError.ErrorCode == E_ABORT) { (*g_StdStream) << endl << kUserBreak; return (NExitCode::kUserBreak); } UString message; NError::MyFormatMessage(systemError.ErrorCode, message); (*g_StdStream) << endl << endl << "System error:" << endl << message << endl; return (NExitCode::kFatalError); } catch(NExitCode::EEnum &exitCode) { (*g_StdStream) << kInternalExceptionMessage << exitCode << endl; return (exitCode); } /* catch(const NExitCode::CMultipleErrors &multipleErrors) { (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl; return (NExitCode::kFatalError); } */ catch(const UString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const AString &s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(const char *s) { (*g_StdStream) << kExceptionErrorMessage << s << endl; return (NExitCode::kFatalError); } catch(int t) { (*g_StdStream) << kInternalExceptionMessage << t << endl; return (NExitCode::kFatalError); } catch(...) { (*g_StdStream) << kUnknownExceptionMessage; return (NExitCode::kFatalError); } return res; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/OpenCallbackConsole.cpp ================================================ // OpenCallbackConsole.cpp #include "StdAfx.h" #include "OpenCallbackConsole.h" #include "ConsoleClose.h" #include "UserInputUtils.h" HRESULT COpenCallbackConsole::Open_CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *) { return Open_CheckBreak(); } #ifndef _NO_CRYPTO HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password) { PasswordWasAsked = true; RINOK(Open_CheckBreak()); if (!PasswordIsDefined) { Password = GetPassword(OutStream); PasswordIsDefined = true; } return StringToBstr(Password, password); } HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password) { if (PasswordIsDefined) password = Password; return S_OK; } bool COpenCallbackConsole::Open_WasPasswordAsked() { return PasswordWasAsked; } void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag() { PasswordWasAsked = false; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/OpenCallbackConsole.h ================================================ // OpenCallbackConsole.h #ifndef __OPENCALLBACKCONSOLE_H #define __OPENCALLBACKCONSOLE_H #include "Common/StdOutStream.h" #include "../Common/ArchiveOpenCallback.h" class COpenCallbackConsole: public IOpenCallbackUI { public: INTERFACE_IOpenCallbackUI(;) CStdOutStream *OutStream; #ifndef _NO_CRYPTO bool PasswordIsDefined; bool PasswordWasAsked; UString Password; COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {} #endif }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/PercentPrinter.cpp ================================================ // PercentPrinter.cpp #include "StdAfx.h" #include "Common/IntToString.h" #include "Common/MyString.h" #include "PercentPrinter.h" const int kPaddingSize = 2; const int kPercentsSize = 4; const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize; static void ClearPrev(char *p, int num) { int i; for (i = 0; i < num; i++) *p++ = '\b'; for (i = 0; i < num; i++) *p++ = ' '; for (i = 0; i < num; i++) *p++ = '\b'; *p = '\0'; } void CPercentPrinter::ClosePrint() { if (m_NumExtraChars == 0) return; char s[kMaxExtraSize * 3 + 1]; ClearPrev(s, m_NumExtraChars); (*OutStream) << s; m_NumExtraChars = 0; } void CPercentPrinter::PrintString(const char *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintString(const wchar_t *s) { ClosePrint(); (*OutStream) << s; } void CPercentPrinter::PrintNewLine() { ClosePrint(); (*OutStream) << "\n"; } void CPercentPrinter::RePrintRatio() { char s[32]; ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s); int size = (int)strlen(s); s[size++] = '%'; s[size] = '\0'; int extraSize = kPaddingSize + MyMax(size, kPercentsSize); if (extraSize < m_NumExtraChars) extraSize = m_NumExtraChars; char fullString[kMaxExtraSize * 3]; char *p = fullString; int i; if (m_NumExtraChars == 0) { for (i = 0; i < extraSize; i++) *p++ = ' '; m_NumExtraChars = extraSize; } for (i = 0; i < m_NumExtraChars; i++) *p++ = '\b'; m_NumExtraChars = extraSize; for (; size < m_NumExtraChars; size++) *p++ = ' '; MyStringCopy(p, s); (*OutStream) << fullString; OutStream->Flush(); m_PrevValue = m_CurValue; } void CPercentPrinter::PrintRatio() { if (m_CurValue < m_PrevValue + m_MinStepSize && m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0) return; RePrintRatio(); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/PercentPrinter.h ================================================ // PercentPrinter.h #ifndef __PERCENTPRINTER_H #define __PERCENTPRINTER_H #include "Common/Types.h" #include "Common/StdOutStream.h" class CPercentPrinter { UInt64 m_MinStepSize; UInt64 m_PrevValue; UInt64 m_CurValue; UInt64 m_Total; int m_NumExtraChars; public: CStdOutStream *OutStream; CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {} void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; } void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; } void PrintString(const char *s); void PrintString(const wchar_t *s); void PrintNewLine(); void ClosePrint(); void RePrintRatio(); void PrintRatio(); }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #include "../../../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp ================================================ // UpdateCallbackConsole.cpp #include "StdAfx.h" #include "UpdateCallbackConsole.h" #include "Windows/Error.h" #ifdef COMPRESS_MT #include "Windows/Synchronization.h" #endif #include "ConsoleClose.h" #include "UserInputUtils.h" using namespace NWindows; #ifdef COMPRESS_MT static NSynchronization::CCriticalSection g_CriticalSection; #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection); #else #define MT_LOCK #endif static const wchar_t *kEmptyFileAlias = L"[Content]"; static const char *kCreatingArchiveMessage = "Creating archive "; static const char *kUpdatingArchiveMessage = "Updating archive "; static const char *kScanningMessage = "Scanning"; HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result) { (*OutStream) << endl; if (result != S_OK) (*OutStream) << "Error: " << name << " is not supported archive" << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartScanning() { (*OutStream) << kScanningMessage; return S_OK; } HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */) { return CheckBreak(); } HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError) { CantFindFiles.Add(name); CantFindCodes.Add(systemError); // m_PercentPrinter.ClosePrint(); if (!m_WarningsMode) { (*OutStream) << endl << endl; m_PercentPrinter.PrintNewLine(); m_WarningsMode = true; } m_PercentPrinter.PrintString(name); m_PercentPrinter.PrintString(": WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); m_PercentPrinter.PrintNewLine(); return S_OK; } HRESULT CUpdateCallbackConsole::FinishScanning() { (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating) { if(updating) (*OutStream) << kUpdatingArchiveMessage; else (*OutStream) << kCreatingArchiveMessage; if (name != 0) (*OutStream) << name; else (*OutStream) << "StdOut"; (*OutStream) << endl << endl; return S_OK; } HRESULT CUpdateCallbackConsole::FinishArchive() { (*OutStream) << endl; return S_OK; } HRESULT CUpdateCallbackConsole::CheckBreak() { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::Finilize() { MT_LOCK if (m_NeedBeClosed) { if (EnablePercents) { m_PercentPrinter.ClosePrint(); } if (!StdOutMode && m_NeedNewLine) { m_PercentPrinter.PrintNewLine(); m_NeedNewLine = false; } m_NeedBeClosed = false; } return S_OK; } HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */) { return S_OK; } HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size) { MT_LOCK if (EnablePercents) m_PercentPrinter.SetTotal(size); return S_OK; } HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue) { MT_LOCK if (completeValue != NULL) { if (EnablePercents) { m_PercentPrinter.SetRatio(*completeValue); m_PercentPrinter.PrintRatio(); m_NeedBeClosed = true; } } if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; return S_OK; } HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti) { MT_LOCK if (StdOutMode) return S_OK; if(isAnti) m_PercentPrinter.PrintString("Anti item "); else m_PercentPrinter.PrintString("Compressing "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); return S_OK; } HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError) { MT_LOCK FailedCodes.Add(systemError); FailedFiles.Add(name); // if (systemError == ERROR_SHARING_VIOLATION) { m_PercentPrinter.ClosePrint(); m_PercentPrinter.PrintNewLine(); m_PercentPrinter.PrintString("WARNING: "); m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError)); return S_FALSE; } // return systemError; } HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 ) { m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) { #ifdef _NO_CRYPTO *passwordIsDefined = false; return StringToBstr(L"", password); #else if (!PasswordIsDefined) { if (AskPassword) { Password = GetPassword(OutStream); PasswordIsDefined = true; } } *passwordIsDefined = BoolToInt(PasswordIsDefined); return StringToBstr(Password, password); #endif } /* HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name) { // MT_LOCK if (StdOutMode) return S_OK; RINOK(Finilize()); m_PercentPrinter.PrintString("Deleting "); if (name[0] == 0) name = kEmptyFileAlias; m_PercentPrinter.PrintString(name); if (EnablePercents) m_PercentPrinter.RePrintRatio(); m_NeedBeClosed = true; m_NeedNewLine = true; return S_OK; } */ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/UpdateCallbackConsole.h ================================================ // UpdateCallbackConsole.h #ifndef __UPDATECALLBACKCONSOLE_H #define __UPDATECALLBACKCONSOLE_H #include "Common/MyString.h" #include "Common/StdOutStream.h" #include "PercentPrinter.h" #include "../Common/Update.h" class CUpdateCallbackConsole: public IUpdateCallbackUI2 { CPercentPrinter m_PercentPrinter; bool m_NeedBeClosed; bool m_NeedNewLine; bool m_WarningsMode; CStdOutStream *OutStream; public: bool EnablePercents; bool StdOutMode; #ifndef _NO_CRYPTO bool PasswordIsDefined; UString Password; bool AskPassword; #endif CUpdateCallbackConsole(): m_PercentPrinter(1 << 16), #ifndef _NO_CRYPTO PasswordIsDefined(false), AskPassword(false), #endif StdOutMode(false), EnablePercents(true), m_WarningsMode(false) {} ~CUpdateCallbackConsole() { Finilize(); } void Init(CStdOutStream *outStream) { m_NeedBeClosed = false; m_NeedNewLine = false; FailedFiles.Clear(); FailedCodes.Clear(); OutStream = outStream; m_PercentPrinter.OutStream = outStream; } INTERFACE_IUpdateCallbackUI2(;) UStringVector FailedFiles; CRecordVector<HRESULT> FailedCodes; UStringVector CantFindFiles; CRecordVector<HRESULT> CantFindCodes; }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/UserInputUtils.cpp ================================================ // UserInputUtils.cpp #include "StdAfx.h" #include "Common/StdInStream.h" #include "Common/StringConvert.h" #include "UserInputUtils.h" static const char kYes = 'Y'; static const char kNo = 'N'; static const char kYesAll = 'A'; static const char kNoAll = 'S'; static const char kAutoRenameAll = 'U'; static const char kQuit = 'Q'; static const char *kFirstQuestionMessage = "?\n"; static const char *kHelpQuestionMessage = "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? "; // return true if pressed Quite; NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream) { (*outStream) << kFirstQuestionMessage; for(;;) { (*outStream) << kHelpQuestionMessage; AString scannedString = g_StdIn.ScanStringUntilNewLine(); scannedString.Trim(); if(!scannedString.IsEmpty()) switch(::MyCharUpper(scannedString[0])) { case kYes: return NUserAnswerMode::kYes; case kNo: return NUserAnswerMode::kNo; case kYesAll: return NUserAnswerMode::kYesAll; case kNoAll: return NUserAnswerMode::kNoAll; case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll; case kQuit: return NUserAnswerMode::kQuit; } } } UString GetPassword(CStdOutStream *outStream) { (*outStream) << "\nEnter password:"; outStream->Flush(); AString oemPassword = g_StdIn.ScanStringUntilNewLine(); return MultiByteToUnicodeString(oemPassword, CP_OEMCP); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/UserInputUtils.h ================================================ // UserInputUtils.h #ifndef __USERINPUTUTILS_H #define __USERINPUTUTILS_H #include "Common/StdOutStream.h" namespace NUserAnswerMode { enum EEnum { kYes, kNo, kYesAll, kNoAll, kAutoRenameAll, kQuit }; } NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream); UString GetPassword(CStdOutStream *outStream); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/7zip/UI/Console/makefile ================================================ PROG = 7z.exe LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib CFLAGS = $(CFLAGS) -I ../../../ \ -DCOMPRESS_MT \ -DWIN_LONG_PATH \ -DEXTERNAL_LZMA \ -DEXTERNAL_CODECS \ -DBREAK_HANDLER \ -DBENCH_MT \ -D_7ZIP_LARGE_PAGES \ CONSOLE_OBJS = \ $O\ConsoleClose.obj \ $O\ExtractCallbackConsole.obj \ $O\List.obj \ $O\Main.obj \ $O\MainAr.obj \ $O\OpenCallbackConsole.obj \ $O\PercentPrinter.obj \ $O\UpdateCallbackConsole.obj \ $O\UserInputUtils.obj \ COMMON_OBJS = \ $O\CommandLineParser.obj \ $O\CRC.obj \ $O\IntToString.obj \ $O\ListFileUtils.obj \ $O\NewHandler.obj \ $O\StdInStream.obj \ $O\StdOutStream.obj \ $O\MyString.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ $O\MyVector.obj \ $O\Wildcard.obj \ WIN_OBJS = \ $O\DLL.obj \ $O\Error.obj \ $O\FileDir.obj \ $O\FileFind.obj \ $O\FileIO.obj \ $O\FileName.obj \ $O\MemoryLock.obj \ $O\PropVariant.obj \ $O\PropVariantConversions.obj \ $O\Registry.obj \ $O\System.obj \ $O\Time.obj \ 7ZIP_COMMON_OBJS = \ $O\FilePathAutoRename.obj \ $O\FileStreams.obj \ $O\ProgressUtils.obj \ $O\StreamUtils.obj \ UI_COMMON_OBJS = \ $O\ArchiveCommandLine.obj \ $O\ArchiveExtractCallback.obj \ $O\ArchiveOpenCallback.obj \ $O\DefaultName.obj \ $O\EnumDirItems.obj \ $O\Extract.obj \ $O\ExtractingFilePath.obj \ $O\LoadCodecs.obj \ $O\OpenArchive.obj \ $O\PropIDUtils.obj \ $O\SetProperties.obj \ $O\SortUtils.obj \ $O\TempFiles.obj \ $O\Update.obj \ $O\UpdateAction.obj \ $O\UpdateCallback.obj \ $O\UpdatePair.obj \ $O\UpdateProduce.obj \ $O\WorkDir.obj \ LZMA_BENCH_OBJS = \ $O\LzmaBench.obj \ $O\LzmaBenchCon.obj \ C_OBJS = \ $O\Alloc.obj \ $O\Threads.obj \ !include "../../Crc2.mak" OBJS = \ $O\StdAfx.obj \ $(CONSOLE_OBJS) \ $(COMMON_OBJS) \ $(WIN_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(UI_COMMON_OBJS) \ $O\CopyCoder.obj \ $(LZMA_BENCH_OBJS) \ $(C_OBJS) \ $(CRC_OBJS) \ $O\resource.res !include "../../../Build.mak" $(CONSOLE_OBJS): $(*B).cpp $(COMPL) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(WIN_OBJS): ../../../Windows/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(UI_COMMON_OBJS): ../Common/$(*B).cpp $(COMPL) $O\CopyCoder.obj: ../../Compress/$(*B).cpp $(COMPL) $(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp $(COMPL) $(C_OBJS): ../../../../C/$(*B).c $(COMPL_O2) !include "../../Crc.mak" ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Build.mak ================================================ !IFDEF CPU !IFNDEF NO_BUFFEROVERFLOWU LIBS = $(LIBS) bufferoverflowU.lib !ENDIF !ENDIF !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF !IF "$(CPU)" != "IA64" !IF "$(CPU)" != "AMD64" MY_ML = ml !ELSE MY_ML = ml64 !ENDIF !ENDIF COMPL_ASM = $(MY_ML) -c -Fo$O/ $** CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -WX -EHsc -Gr -Gy -GR- !IFDEF MY_STATIC_LINK !IFNDEF MY_SINGLE_THREAD CFLAGS = $(CFLAGS) -MT !ENDIF !ELSE CFLAGS = $(CFLAGS) -MD !ENDIF !IFDEF NEW_COMPILER CFLAGS = $(CFLAGS) -W4 -GS- -Zc:forScope !ELSE CFLAGS = $(CFLAGS) -W3 !ENDIF CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF -OPT:ICF !IFDEF DEF_FILE LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE) !ENDIF PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL_PCH = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** COMPL = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $** all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) $(DEF_FILE) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\resource.res: $(*B).rc rc -fo$@ $** $O\StdAfx.obj: $(*B).cpp $(COMPL_PCH) ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/AutoPtr.h ================================================ // Common/AutoPtr.h #ifndef __COMMON_AUTOPTR_H #define __COMMON_AUTOPTR_H template<class T> class CMyAutoPtr { T *_p; public: CMyAutoPtr(T *p = 0) : _p(p) {} CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {} CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) { reset(p.release()); return (*this); } ~CMyAutoPtr() { delete _p; } T& operator*() const { return *_p; } // T* operator->() const { return (&**this); } T* get() const { return _p; } T* release() { T *tmp = _p; _p = 0; return tmp; } void reset(T* p = 0) { if (p != _p) delete _p; _p = p; } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/Buffer.h ================================================ // Common/Buffer.h #ifndef __COMMON_BUFFER_H #define __COMMON_BUFFER_H #include "Defs.h" template <class T> class CBuffer { protected: size_t _capacity; T *_items; public: void Free() { delete []_items; _items = 0; _capacity = 0; } CBuffer(): _capacity(0), _items(0) {}; CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; } CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); } virtual ~CBuffer() { delete []_items; } operator T *() { return _items; }; operator const T *() const { return _items; }; size_t GetCapacity() const { return _capacity; } void SetCapacity(size_t newCapacity) { if (newCapacity == _capacity) return; T *newBuffer; if (newCapacity > 0) { newBuffer = new T[newCapacity]; if (_capacity > 0) memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T)); } else newBuffer = 0; delete []_items; _items = newBuffer; _capacity = newCapacity; } CBuffer& operator=(const CBuffer &buffer) { Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } }; template <class T> bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2) { if (b1.GetCapacity() != b2.GetCapacity()) return false; for (size_t i = 0; i < b1.GetCapacity(); i++) if (b1[i] != b2[i]) return false; return true; } template <class T> bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2) { return !(b1 == b2); } typedef CBuffer<char> CCharBuffer; typedef CBuffer<wchar_t> CWCharBuffer; typedef CBuffer<unsigned char> CByteBuffer; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" extern "C" { #include "../../C/7zCrc.h" } struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit; ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if (_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } bool CInFile::OpenShared(const char *name, bool) { return Open(name); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } bool COutFile::Open(const char *name, DWORD creationDisposition) { return Create(name, false); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; int GetHandle() const { return _handle; } }; class CInFile: public CFileBase { public: bool Open(const char *name); bool OpenShared(const char *name, bool shareForWrite); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); bool Open(const char *name, DWORD creationDisposition); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); for (;;) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) break; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while (pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for (int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for (int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "MyString.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/DynamicBuffer.h ================================================ // Common/DynamicBuffer.h #ifndef __COMMON_DYNAMICBUFFER_H #define __COMMON_DYNAMICBUFFER_H #include "Buffer.h" template <class T> class CDynamicBuffer: public CBuffer<T> { void GrowLength(size_t size) { size_t delta; if (this->_capacity > 64) delta = this->_capacity / 4; else if (this->_capacity > 8) delta = 16; else delta = 4; delta = MyMax(delta, size); SetCapacity(this->_capacity + delta); } public: CDynamicBuffer(): CBuffer<T>() {}; CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {}; CDynamicBuffer(size_t size): CBuffer<T>(size) {}; CDynamicBuffer& operator=(const CDynamicBuffer &buffer) { this->Free(); if (buffer._capacity > 0) { SetCapacity(buffer._capacity); memmove(this->_items, buffer._items, buffer._capacity * sizeof(T)); } return *this; } void EnsureCapacity(size_t capacity) { if (this->_capacity < capacity) GrowLength(capacity - this->_capacity); } }; typedef CDynamicBuffer<char> CCharDynamicBuffer; typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer; typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/IntToString.cpp ================================================ // Common/IntToString.cpp #include "StdAfx.h" #include "IntToString.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base) { if (base < 2 || base > 36) { *s = '\0'; return; } char temp[72]; int pos = 0; do { int delta = (int)(value % base); temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10))); value /= base; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; } void ConvertUInt64ToString(UInt64 value, wchar_t *s) { wchar_t temp[32]; int pos = 0; do { temp[pos++] = (wchar_t)(L'0' + (int)(value % 10)); value /= 10; } while (value != 0); do *s++ = temp[--pos]; while (pos > 0); *s = L'\0'; } void ConvertInt64ToString(Int64 value, char *s) { if (value < 0) { *s++ = '-'; value = -value; } ConvertUInt64ToString(value, s); } void ConvertInt64ToString(Int64 value, wchar_t *s) { if (value < 0) { *s++ = L'-'; value = -value; } ConvertUInt64ToString(value, s); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/IntToString.h ================================================ // Common/IntToString.h #ifndef __COMMON_INTTOSTRING_H #define __COMMON_INTTOSTRING_H #include <stddef.h> #include "Types.h" void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10); void ConvertUInt64ToString(UInt64 value, wchar_t *s); void ConvertInt64ToString(Int64 value, char *s); void ConvertInt64ToString(Int64 value, wchar_t *s); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/ListFileUtils.cpp ================================================ // Common/ListFileUtils.cpp #include "StdAfx.h" #include "MyWindows.h" #include "../Windows/FileIO.h" #include "ListFileUtils.h" #include "StringConvert.h" #include "UTFConvert.h" static const char kQuoteChar = '\"'; static void RemoveQuote(UString &s) { if (s.Length() >= 2) if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar) s = s.Mid(1, s.Length() - 2); } bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 length; if (!file.GetLength(length)) return false; if (length > ((UInt32)1 << 31)) return false; AString s; char *p = s.GetBuffer((int)length + 1); UInt32 processed; if (!file.Read(p, (UInt32)length, processed)) return false; p[(UInt32)length] = 0; s.ReleaseBuffer(); file.Close(); UString u; #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else #endif u = MultiByteToUnicodeString(s, codePage); if (!u.IsEmpty()) { if (u[0] == 0xFEFF) u.Delete(0); } UString t; for (int i = 0; i < u.Length(); i++) { wchar_t c = u[i]; if (c == L'\n' || c == 0xD) { t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); t.Empty(); } else t += c; } t.Trim(); RemoveQuote(t); if (!t.IsEmpty()) resultStrings.Add(t); return true; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/ListFileUtils.h ================================================ // Common/ListFileUtils.h #ifndef __COMMON_LISTFILEUTILS_H #define __COMMON_LISTFILEUTILS_H #include "MyString.h" #include "Types.h" bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #ifndef RINOK #define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } #endif template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) { *bstr = ::SysAllocString(src); return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; } class CMyComBSTR { public: BSTR m_str; CMyComBSTR(): m_str(NULL) {} CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR src) { ::SysFreeString(m_str); m_str = ::SysAllocString(src); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memcpy(res, m_str, byteLen); return res; } /* void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } */ void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyException.h ================================================ // Common/Exception.h #ifndef __COMMON_EXCEPTION_H #define __COMMON_EXCEPTION_H #include "MyWindows.h" struct CSystemException { HRESULT ErrorCode; CSystemException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline int operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return 0; return 1; } inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyString.cpp ================================================ // Common/MyString.cpp #include "StdAfx.h" #ifndef _WIN32 #include <ctype.h> #endif #ifndef _UNICODE #include "StringConvert.h" #endif #include "MyString.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)(UINT_PTR)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { for (;;) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { for (;;) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } /* int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } */ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyString.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "MyVector.h" #ifdef _WIN32 #include "MyWindows.h" #endif template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while ((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); // int MyStringCompareNoCase(const char *s1, const char *s2); int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if (realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if (newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if (_capacity > 0) { for (int i = 0; i < _length; i++) newBuffer[i] = _chars[i]; delete []_chars; } _chars = newBuffer; _chars[_length] = 0; _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(3); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if (minBufLength >= _capacity) SetCapacity(minBufLength); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if (newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if (&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int Compare(const T *s) const { return MyStringCompare(_chars, s); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } int CompareNoCase(const T *s) const { return MyStringCompareNoCase(_chars, s); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; for (;;) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; for (;;) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for (int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; charSet += (T)' '; charSet += (T)'\n'; charSet += (T)'\t'; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if (pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for (int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyVector.cpp ================================================ // Common/MyVector.cpp #include "StdAfx.h" #include <string.h> #include "MyVector.h" CBaseRecordVector::~CBaseRecordVector() { ClearAndFree(); } void CBaseRecordVector::ClearAndFree() { Clear(); delete []((unsigned char *)_items); _capacity = 0; _size = 0; _items = 0; } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if (_size != _capacity) return; int delta = 1; if (_capacity >= 64) delta = _capacity / 4; else if (_capacity >= 8) delta = 8; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { // if (newCapacity <= _capacity) if (newCapacity == _capacity) return; if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1))) throw 1052353; size_t newSize = (size_t)(unsigned)newCapacity * _itemSize; if (newSize / _itemSize != (size_t)(unsigned)newCapacity) throw 1052354; unsigned char *p = NULL; if (newSize > 0) { p = new unsigned char[newSize]; if (p == 0) throw 1052355; int numRecordsToMove = (_size < newCapacity ? _size : newCapacity); memcpy(p, _items, _itemSize * numRecordsToMove); } delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::ReserveDown() { Reserve(_size); } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyVector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); void ClearAndFree(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); void ReserveDown(); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector(): CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v; } CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToUniqueSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param) { T temp = p[k]; for (;;) { int s = (k << 1); if (s > size) break; if (s < size && compare(p + s + 1, p + s, param) > 0) s++; if (compare(&temp, p + s, param) >= 0) break; p[k] = p[s]; k = s; } p[k] = temp; } void Sort(int (*compare)(const T*, const T*, void *), void *param) { int size = _size; if (size <= 1) return; T* p = (&Front()) - 1; { int i = size / 2; do SortRefDown(p, i, size, compare, param); while (--i != 0); } do { T temp = p[size]; p[size--] = p[1]; p[1] = temp; SortRefDown(p, 1, size, compare, param); } while (size > 1); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector() {}; ~CObjectVector() { Clear(); }; CObjectVector(const CObjectVector &v) { *this = v; } CObjectVector& operator=(const CObjectVector &v) { Clear(); return (*this += v); } CObjectVector& operator+=(const CObjectVector &v) { int size = v.Size(); Reserve(Size() + size); for (int i = 0; i < size; i++) Add(v[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for (int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for (int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #define CHAR_PATH_SEPARATOR '\\' #define WCHAR_PATH_SEPARATOR L'\\' #define STRING_PATH_SEPARATOR "\\" #define WSTRING_PATH_SEPARATOR L"\\" #else #define CHAR_PATH_SEPARATOR '/' #define WCHAR_PATH_SEPARATOR L'/' #define STRING_PATH_SEPARATOR "/" #define WSTRING_PATH_SEPARATOR L"/" #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; #undef BYTE typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; #undef WORD typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; #undef DWORD typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOTIMPL ((HRESULT)0x80004001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct #ifdef __cplusplus #ifndef INITGUID #define INITGUID DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); #endif struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; #ifndef _WIN32 virtual ~IUnknown() {} #endif }; typedef IUnknown *LPUNKNOWN; #endif #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; #ifdef __cplusplus typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); #endif MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK #ifdef _WIN32 void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #endif #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; #ifdef _WIN32 void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StdInStream.cpp ================================================ // Common/StdInStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdInStream.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kIllegalChar = '\0'; static const char kNewLineChar = '\n'; static const char *kEOFMessage = "Unexpected end of input stream"; static const char *kReadErrorMessage ="Error reading input stream"; static const char *kIllegalCharMessage = "Illegal character in input stream"; static LPCTSTR kFileOpenMode = TEXT("r"); CStdInStream g_StdIn(stdin); bool CStdInStream::Open(LPCTSTR fileName) { Close(); _stream = _tfopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdInStream::Close() { if (!_streamIsOpen) return true; _streamIsOpen = (fclose(_stream) != 0); return !_streamIsOpen; } CStdInStream::~CStdInStream() { Close(); } AString CStdInStream::ScanStringUntilNewLine() { AString s; for (;;) { int intChar = GetChar(); if (intChar == EOF) throw kEOFMessage; char c = char(intChar); if (c == kIllegalChar) throw kIllegalCharMessage; if (c == kNewLineChar) break; s += c; } return s; } void CStdInStream::ReadToString(AString &resultString) { resultString.Empty(); int c; while ((c = GetChar()) != EOF) resultString += char(c); } bool CStdInStream::Eof() { return (feof(_stream) != 0); } int CStdInStream::GetChar() { int c = fgetc(_stream); // getc() doesn't work in BeOS? if (c == EOF && !Eof()) throw kReadErrorMessage; return c; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StdInStream.h ================================================ // Common/StdInStream.h #ifndef __COMMON_STDINSTREAM_H #define __COMMON_STDINSTREAM_H #include <stdio.h> #include "MyString.h" #include "Types.h" class CStdInStream { bool _streamIsOpen; FILE *_stream; public: CStdInStream(): _streamIsOpen(false) {}; CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdInStream(); bool Open(LPCTSTR fileName); bool Close(); AString ScanStringUntilNewLine(); void ReadToString(AString &resultString); bool Eof(); int GetChar(); }; extern CStdInStream g_StdIn; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StdOutStream.cpp ================================================ // Common/StdOutStream.cpp #include "StdAfx.h" #include <tchar.h> #include "StdOutStream.h" #include "IntToString.h" #include "StringConvert.h" #ifdef _MSC_VER // "was declared deprecated" disabling #pragma warning(disable : 4996 ) #endif static const char kNewLineChar = '\n'; static const char *kFileOpenMode = "wt"; CStdOutStream g_StdOut(stdout); CStdOutStream g_StdErr(stderr); bool CStdOutStream::Open(const char *fileName) { Close(); _stream = fopen(fileName, kFileOpenMode); _streamIsOpen = (_stream != 0); return _streamIsOpen; } bool CStdOutStream::Close() { if (!_streamIsOpen) return true; if (fclose(_stream) != 0) return false; _stream = 0; _streamIsOpen = false; return true; } bool CStdOutStream::Flush() { return (fflush(_stream) == 0); } CStdOutStream::~CStdOutStream () { Close(); } CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream &)) { (*aFunction)(*this); return *this; } CStdOutStream & endl(CStdOutStream & outStream) { return outStream << kNewLineChar; } CStdOutStream & CStdOutStream::operator<<(const char *string) { fputs(string, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(const wchar_t *string) { *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP); return *this; } CStdOutStream & CStdOutStream::operator<<(char c) { fputc(c, _stream); return *this; } CStdOutStream & CStdOutStream::operator<<(int number) { char textString[32]; ConvertInt64ToString(number, textString); return operator<<(textString); } CStdOutStream & CStdOutStream::operator<<(UInt64 number) { char textString[32]; ConvertUInt64ToString(number, textString); return operator<<(textString); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StdOutStream.h ================================================ // Common/StdOutStream.h #ifndef __COMMON_STDOUTSTREAM_H #define __COMMON_STDOUTSTREAM_H #include <stdio.h> #include "Types.h" class CStdOutStream { bool _streamIsOpen; FILE *_stream; public: CStdOutStream (): _streamIsOpen(false), _stream(0) {}; CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {}; ~CStdOutStream (); operator FILE *() { return _stream; } bool Open(const char *fileName); bool Close(); bool Flush(); CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream &)); CStdOutStream & operator<<(const char *string); CStdOutStream & operator<<(const wchar_t *string); CStdOutStream & operator<<(char c); CStdOutStream & operator<<(int number); CStdOutStream & operator<<(UInt64 number); }; CStdOutStream & endl(CStdOutStream & outStream); extern CStdOutStream g_StdOut; extern CStdOutStream g_StdErr; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if (!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if (numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed) { AString dest; defaultCharWasUsed = false; if (!s.IsEmpty()) { int numRequiredBytes = s.Length() * 2; BOOL defUsed; int numChars = WideCharToMultiByte(codePage, 0, s, s.Length(), dest.GetBuffer(numRequiredBytes), numRequiredBytes + 1, &defaultChar, &defUsed); defaultCharWasUsed = (defUsed != FALSE); #ifndef _WIN32_WCE if (numChars == 0) throw 282229; #endif dest.ReleaseBuffer(numChars); } return dest; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { bool defaultCharWasUsed; return UnicodeStringToMultiByte(srcString, codePage, '_', defaultCharWasUsed); } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if (!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if (!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "MyString.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage, char defaultChar, bool &defaultCharWasUsed); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertHexStringToUInt64(const char *s, const char **end) { UInt64 result = 0; for (;;) { char c = *s; UInt32 v; if (c >= '0' && c <= '9') v = (c - '0'); else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A'); else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a'); else { if (end != NULL) *end = s; return result; } result <<= 4; result |= v; s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; for (;;) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertHexStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H extern "C" { #include "../../C/Types.h" } typedef int HRes; #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/UTFConvert.cpp ================================================ // UTFConvert.cpp #include "StdAfx.h" #include "UTFConvert.h" #include "Types.h" static const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; static Bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { Byte c; int numAdds; if (srcPos == srcLen) { *destLen = destPos; return True; } c = (Byte)src[srcPos++]; if (c < 0x80) { if (dest) dest[destPos] = (wchar_t)c; destPos++; continue; } if (c < 0xC0) break; for (numAdds = 1; numAdds < 5; numAdds++) if (c < kUtf8Limits[numAdds]) break; UInt32 value = (c - kUtf8Limits[numAdds - 1]); do { Byte c2; if (srcPos == srcLen) break; c2 = (Byte)src[srcPos++]; if (c2 < 0x80 || c2 >= 0xC0) break; value <<= 6; value |= (c2 - 0x80); } while (--numAdds != 0); if (value < 0x10000) { if (dest) dest[destPos] = (wchar_t)value; destPos++; } else { value -= 0x10000; if (value >= 0x100000) break; if (dest) { dest[destPos + 0] = (wchar_t)(0xD800 + (value >> 10)); dest[destPos + 1] = (wchar_t)(0xDC00 + (value & 0x3FF)); } destPos += 2; } } *destLen = destPos; return False; } static Bool Utf16_To_Utf8(char *dest, size_t *destLen, const wchar_t *src, size_t srcLen) { size_t destPos = 0, srcPos = 0; for (;;) { unsigned numAdds; UInt32 value; if (srcPos == srcLen) { *destLen = destPos; return True; } value = src[srcPos++]; if (value < 0x80) { if (dest) dest[destPos] = (char)value; destPos++; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00 || srcPos == srcLen) break; c2 = src[srcPos++]; if (c2 < 0xDC00 || c2 >= 0xE000) break; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; if (dest) dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); destPos++; do { numAdds--; if (dest) dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); destPos++; } while (numAdds != 0); } *destLen = destPos; return False; } bool ConvertUTF8ToUnicode(const AString &src, UString &dest) { dest.Empty(); size_t destLen = 0; Utf8_To_Utf16(NULL, &destLen, src, src.Length()); wchar_t *p = dest.GetBuffer((int)destLen); Bool res = Utf8_To_Utf16(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } bool ConvertUnicodeToUTF8(const UString &src, AString &dest) { dest.Empty(); size_t destLen = 0; Utf16_To_Utf8(NULL, &destLen, src, src.Length()); char *p = dest.GetBuffer((int)destLen); Bool res = Utf16_To_Utf8(p, &destLen, src, src.Length()); p[destLen] = 0; dest.ReleaseBuffer(); return res ? true : false; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/UTFConvert.h ================================================ // Common/UTFConvert.h #ifndef __COMMON_UTFCONVERT_H #define __COMMON_UTFCONVERT_H #include "MyString.h" bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString); bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/Wildcard.cpp ================================================ // Common/Wildcard.cpp #include "StdAfx.h" #include "Wildcard.h" bool g_CaseSensitive = #ifdef _WIN32 false; #else true; #endif static const wchar_t kAnyCharsChar = L'*'; static const wchar_t kAnyCharChar = L'?'; #ifdef _WIN32 static const wchar_t kDirDelimiter1 = L'\\'; #endif static const wchar_t kDirDelimiter2 = L'/'; static const UString kWildCardCharSet = L"?*"; static const UString kIllegalWildCardFileNameChars= L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" L"\"/:<>\\|"; static inline bool IsCharDirLimiter(wchar_t c) { return ( #ifdef _WIN32 c == kDirDelimiter1 || #endif c == kDirDelimiter2); } int CompareFileNames(const UString &s1, const UString &s2) { if (g_CaseSensitive) return s1.Compare(s2); return s1.CompareNoCase(s2); } // ----------------------------------------- // this function compares name with mask // ? - any char // * - any char or empty static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) { for (;;) { wchar_t m = *mask; wchar_t c = *name; if (m == 0) return (c == 0); if (m == kAnyCharsChar) { if (EnhancedMaskTest(mask + 1, name)) return true; if (c == 0) return false; } else { if (m == kAnyCharChar) { if (c == 0) return false; } else if (m != c) if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) return false; mask++; } name++; } } // -------------------------------------------------- // Splits path to strings void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); UString name; int len = path.Length(); if (len == 0) return; for (int i = 0; i < len; i++) { wchar_t c = path[i]; if (IsCharDirLimiter(c)) { pathParts.Add(name); name.Empty(); } else name += c; } pathParts.Add(name); } void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; dirPrefix = path.Left(i + 1); name = path.Mid(i + 1); } UString ExtractDirPrefixFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Left(i + 1); } UString ExtractFileNameFromPath(const UString &path) { int i; for (i = path.Length() - 1; i >= 0; i--) if (IsCharDirLimiter(path[i])) break; return path.Mid(i + 1); } bool CompareWildCardWithName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } bool DoesNameContainWildCard(const UString &path) { return (path.FindOneOf(kWildCardCharSet) >= 0); } // ----------------------------------------------------------' // NWildcard namespace NWildcard { /* M = MaskParts.Size(); N = TestNameParts.Size(); File Dir ForFile req M<=N [N-M, N) - nonreq M=N [0, M) - ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File nonreq [0, M) same as ForBoth-File ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File nonreq [0, M) same as ForBoth-File */ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; int start = 0; int finish = 0; if (isFile) { if (!ForDir && !Recursive && delta !=0) return false; if (!ForFile && delta == 0) return false; if (!ForDir && Recursive) start = delta; } if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } for (int d = start; d <= finish; d++) { int i; for (i = 0; i < PathParts.Size(); i++) if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) break; if (i == PathParts.Size()) return true; } return false; } int CCensorNode::FindSubNode(const UString &name) const { for (int i = 0; i < SubNodes.Size(); i++) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; } void CCensorNode::AddItemSimple(bool include, CItem &item) { if (include) IncludeItems.Add(item); else ExcludeItems.Add(item); } void CCensorNode::AddItem(bool include, CItem &item) { if (item.PathParts.Size() <= 1) { AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); if (DoesNameContainWildCard(front)) { AddItemSimple(include, item); return; } int index = FindSubNode(front); if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); SubNodes[index].AddItem(include, item); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { for (int i = 0; i < IncludeItems.Size(); i++) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) return true; } return false; } bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; for (int i = 0; i < SubNodes.Size(); i++) if (SubNodes[i].AreThereIncludeItems()) return true; return false; } bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; for (int i = 0; i < items.Size(); i++) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { include = false; return true; } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); if (pathParts.Size() == 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); if (SubNodes[index].CheckPath(pathParts2, isFile, include)) return true; } return finded; } bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPath(pathParts, isFile, include); } bool CCensorNode::CheckPath(const UString &path, bool isFile) const { bool include; if (CheckPath(path, isFile, include)) return include; return false; } bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { if (CheckPathCurrent(include, pathParts, isFile)) return true; if (Parent == 0) return false; pathParts.Insert(0, Name); return Parent->CheckPathToRoot(include, pathParts, isFile); } /* bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const { UStringVector pathParts; SplitPathToParts(path, pathParts); return CheckPathToRoot(include, pathParts, isFile); } */ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; if (IsCharDirLimiter(path[path.Length() - 1])) { path2.Delete(path.Length() - 1); forFile = false; } AddItem(include, path2, recursive, forFile, forFolder); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; for (int i = 0; i < fromNodes.SubNodes.Size(); i++) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); if (subNodeIndex < 0) subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); SubNodes[subNodeIndex].ExtendExclude(node); } } int CCensor::FindPrefix(const UString &prefix) const { for (int i = 0; i < Pairs.Size(); i++) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); } bool CCensor::CheckPath(const UString &path, bool isFile) const { bool finded = false; for (int i = 0; i < Pairs.Size(); i++) { bool include; if (Pairs[i].Head.CheckPath(path, isFile, include)) { if (!include) return false; finded = true; } } return finded; } void CCensor::ExtendExclude() { int i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; int index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Common/Wildcard.h ================================================ // Common/Wildcard.h #ifndef __COMMON_WILDCARD_H #define __COMMON_WILDCARD_H #include "MyString.h" int CompareFileNames(const UString &s1, const UString &s2); void SplitPathToParts(const UString &path, UStringVector &pathParts); void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name); UString ExtractDirPrefixFromPath(const UString &path); UString ExtractFileNameFromPath(const UString &path); bool DoesNameContainWildCard(const UString &path); bool CompareWildCardWithName(const UString &mask, const UString &name); namespace NWildcard { struct CItem { UStringVector PathParts; bool Recursive; bool ForFile; bool ForDir; bool CheckPath(const UStringVector &pathParts, bool isFile) const; }; class CCensorNode { CCensorNode *Parent; bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const; void AddItemSimple(bool include, CItem &item); bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const; public: CCensorNode(): Parent(0) { }; CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { }; UString Name; CObjectVector<CCensorNode> SubNodes; CObjectVector<CItem> IncludeItems; CObjectVector<CItem> ExcludeItems; int FindSubNode(const UString &path) const; void AddItem(bool include, CItem &item); void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir); void AddItem2(bool include, const UString &path, bool recursive); bool NeedCheckSubDirs() const; bool AreThereIncludeItems() const; bool CheckPath(const UString &path, bool isFile, bool &include) const; bool CheckPath(const UString &path, bool isFile) const; bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const; // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const; void ExtendExclude(const CCensorNode &fromNodes); }; struct CPair { UString Prefix; CCensorNode Head; CPair(const UString &prefix): Prefix(prefix) { }; }; class CCensor { int FindPrefix(const UString &prefix) const; public: CObjectVector<CPair> Pairs; bool AllAreRelative() const { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); } void AddItem(bool include, const UString &path, bool recursive); bool CheckPath(const UString &path, bool isFile) const; void ExtendExclude(); }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/DLL.cpp ================================================ // Windows/DLL.cpp #include "StdAfx.h" #include "DLL.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NDLL { CLibrary::~CLibrary() { Free(); } bool CLibrary::Free() { if (_module == 0) return true; // MessageBox(0, TEXT(""), TEXT("Free"), 0); // Sleep(5000); if (!::FreeLibrary(_module)) return false; _module = 0; return true; } bool CLibrary::LoadOperations(HMODULE newModule) { if (newModule == NULL) return false; if (!Free()) return false; _module = newModule; return true; } bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags) { // MessageBox(0, fileName, TEXT("LoadEx"), 0); return LoadOperations(::LoadLibraryEx(fileName, NULL, flags)); } bool CLibrary::Load(LPCTSTR fileName) { // MessageBox(0, fileName, TEXT("Load"), 0); // Sleep(5000); // OutputDebugString(fileName); // OutputDebugString(TEXT("\n")); return LoadOperations(::LoadLibrary(fileName)); } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags) { if (g_IsNT) return LoadOperations(::LoadLibraryExW(fileName, NULL, flags)); return LoadEx(GetSysPath(fileName), flags); } bool CLibrary::Load(LPCWSTR fileName) { if (g_IsNT) return LoadOperations(::LoadLibraryW(fileName)); return Load(GetSysPath(fileName)); } #endif bool MyGetModuleFileName(HMODULE hModule, CSysString &result) { result.Empty(); TCHAR fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result) { result.Empty(); if (g_IsNT) { wchar_t fullPath[MAX_PATH + 2]; DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1); if (size <= MAX_PATH && size != 0) { result = fullPath; return true; } return false; } CSysString resultSys; if (!MyGetModuleFileName(hModule, resultSys)) return false; result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage()); return true; } #endif }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/DLL.h ================================================ // Windows/DLL.h #ifndef __WINDOWS_DLL_H #define __WINDOWS_DLL_H #include "../Common/MyString.h" namespace NWindows { namespace NDLL { class CLibrary { bool LoadOperations(HMODULE newModule); protected: HMODULE _module; public: operator HMODULE() const { return _module; } HMODULE* operator&() { return &_module; } CLibrary():_module(NULL) {}; ~CLibrary(); void Attach(HMODULE m) { Free(); _module = m; } HMODULE Detach() { HMODULE m = _module; _module = NULL; return m; } // operator HMODULE() const { return _module; }; bool IsLoaded() const { return (_module != NULL); }; bool Free(); bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCTSTR fileName); #ifndef _UNICODE bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE); bool Load(LPCWSTR fileName); #endif FARPROC GetProcAddress(LPCSTR procName) const { return ::GetProcAddress(_module, procName); } }; bool MyGetModuleFileName(HMODULE hModule, CSysString &result); #ifndef _UNICODE bool MyGetModuleFileName(HMODULE hModule, UString &result); #endif }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } #ifdef _WIN32 inline bool LRESULTToBool(LRESULT value) { return (value != FALSE); } #endif inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Error.cpp ================================================ // Windows/Error.h #include "StdAfx.h" #include "Windows/Error.h" #ifndef _UNICODE #include "Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message) { LPVOID msgBuf; if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0) return false; message = (LPCTSTR)msgBuf; ::LocalFree(msgBuf); return true; } #ifndef _UNICODE bool MyFormatMessage(DWORD messageID, UString &message) { if (g_IsNT) { LPVOID msgBuf; if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0) return false; message = (LPCWSTR)msgBuf; ::LocalFree(msgBuf); return true; } CSysString messageSys; bool result = MyFormatMessage(messageID, messageSys); message = GetUnicodeString(messageSys); return result; } #endif }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Error.h ================================================ // Windows/Error.h #ifndef __WINDOWS_ERROR_H #define __WINDOWS_ERROR_H #include "Common/MyString.h" namespace NWindows { namespace NError { bool MyFormatMessage(DWORD messageID, CSysString &message); inline CSysString MyFormatMessage(DWORD messageID) { CSysString message; MyFormatMessage(messageID, message); return message; } #ifdef _UNICODE inline UString MyFormatMessageW(DWORD messageID) { return MyFormatMessage(messageID); } #else bool MyFormatMessage(DWORD messageID, UString &message); inline UString MyFormatMessageW(DWORD messageID) { UString message; MyFormatMessage(messageID, message); return message; } #endif }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileDir.cpp ================================================ // Windows/FileDir.cpp #include "StdAfx.h" #include "FileDir.h" #include "FileName.h" #include "FileFind.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif // SetCurrentDirectory doesn't support \\?\ prefix #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR fileName, UString &res); bool GetLongPath(LPCWSTR fileName, UString &res); #endif namespace NDirectory { #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static UString GetUnicodePath(const CSysString &sysPath) { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } static CSysString GetSysPath(LPCWSTR sysPath) { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } #endif bool MyGetWindowsDirectory(CSysString &path) { UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } bool MyGetSystemDirectory(CSysString &path) { UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetWindowsDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } bool MyGetSystemDirectory(UString &path) { if (g_IsNT) { UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetSystemDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { #ifndef _UNICODE if (!g_IsNT) { ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return false; } #endif HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); #ifdef WIN_LONG_PATH if (hDir == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) hDir = ::CreateFileW(longPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); } #endif bool res = false; if (hDir != INVALID_HANDLE_VALUE) { res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); ::CloseHandle(hDir); } return res; } bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) { if (::SetFileAttributes(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCTSTR pathName) { if (::RemoveDirectory(pathName)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) { if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) return false; if (d1.IsEmpty() && d2.IsEmpty()) return false; if (d1.IsEmpty()) d1 = s1; if (d2.IsEmpty()) d2 = s2; return true; } #endif bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) { if (::MoveFile(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH2 UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) { if (!g_IsNT) return MySetFileAttributes(GetSysPath(fileName), fileAttributes); if (::SetFileAttributesW(fileName, fileAttributes)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(fileName, longPath)) return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); #endif return false; } bool MyRemoveDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyRemoveDirectory(GetSysPath(pathName)); if (::RemoveDirectoryW(pathName)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::RemoveDirectoryW(longPath)); #endif return false; } bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) { if (!g_IsNT) return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); if (::MoveFileW(existFileName, newFileName)) return true; #ifdef WIN_LONG_PATH UString d1, d2; if (GetLongPaths(existFileName, newFileName, d1, d2)) return BOOLToBool(::MoveFileW(d1, d2)); #endif return false; } #endif bool MyCreateDirectory(LPCTSTR pathName) { if (::CreateDirectory(pathName, NULL)) return true; #ifdef WIN_LONG_PATH2 if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #ifndef _UNICODE bool MyCreateDirectory(LPCWSTR pathName) { if (!g_IsNT) return MyCreateDirectory(GetSysPath(pathName)); if (::CreateDirectoryW(pathName, NULL)) return true; #ifdef WIN_LONG_PATH if (::GetLastError() != ERROR_ALREADY_EXISTS) { UString longPath; if (GetLongPath(pathName, longPath)) return BOOLToBool(::CreateDirectoryW(longPath, NULL)); } #endif return false; } #endif /* bool CreateComplexDirectory(LPCTSTR pathName) { NName::CParsedPath path; path.ParsePath(pathName); CSysString fullPath = path.Prefix; DWORD errorCode = ERROR_SUCCESS; for (int i = 0; i < path.PathParts.Size(); i++) { const CSysString &string = path.PathParts[i]; if (string.IsEmpty()) { if (i != path.PathParts.Size() - 1) return false; return true; } fullPath += path.PathParts[i]; if (!MyCreateDirectory(fullPath)) { DWORD errorCode = GetLastError(); if (errorCode != ERROR_ALREADY_EXISTS) return false; } fullPath += NName::kDirDelimiter; } return true; } */ bool CreateComplexDirectory(LPCTSTR _aPathName) { CSysString pathName = _aPathName; int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == ':') return true; // Disk folder; pathName.Delete(pos); } CSysString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfo fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == ':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #ifndef _UNICODE bool CreateComplexDirectory(LPCWSTR _aPathName) { UString pathName = _aPathName; int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos > 0 && pos == pathName.Length() - 1) { if (pathName.Length() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } UString pathName2 = pathName; pos = pathName.Length(); for (;;) { if (MyCreateDirectory(pathName)) break; if (::GetLastError() == ERROR_ALREADY_EXISTS) { NFind::CFileInfoW fileInfo; if (!NFind::FindFile(pathName, fileInfo)) // For network folders return true; if (!fileInfo.IsDir()) return false; break; } pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') return false; pathName = pathName.Left(pos); } pathName = pathName2; while (pos < pathName.Length()) { pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) pos = pathName.Length(); if (!MyCreateDirectory(pathName.Left(pos))) return false; } return true; } #endif bool DeleteFileAlways(LPCTSTR name) { if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFile(name)) return true; #ifdef WIN_LONG_PATH2 UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #ifndef _UNICODE bool DeleteFileAlways(LPCWSTR name) { if (!g_IsNT) return DeleteFileAlways(GetSysPath(name)); if (!MySetFileAttributes(name, 0)) return false; if (::DeleteFileW(name)) return true; #ifdef WIN_LONG_PATH UString longPath; if (GetLongPath(name, longPath)) return BOOLToBool(::DeleteFileW(longPath)); #endif return false; } #endif static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const CSysString &path) { NFind::CFileInfo fileInfo; CSysString pathPrefix = path + NName::kDirDelimiter; { NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #ifndef _UNICODE static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } bool RemoveDirectoryWithSubItems(const UString &path) { NFind::CFileInfoW fileInfo; UString pathPrefix = path + UString(NName::kDirDelimiter); { NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } if (!MySetFileAttributes(path, 0)) return false; return MyRemoveDirectory(path); } #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) { DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); shortPath.ReleaseBuffer(); return (needLength > 0 && needLength < MAX_PATH); } bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); LPTSTR fileNamePointer = 0; LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH2 needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = lstrlen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); return true; } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) { resultPath.Empty(); if (g_IsNT) { LPWSTR fileNamePointer = 0; LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength == 0) return false; if (needLength >= MAX_PATH) { #ifdef WIN_LONG_PATH needLength++; buffer = resultPath.GetBuffer(needLength + 1); DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); resultPath.ReleaseBuffer(); if (needLength2 == 0 || needLength2 > needLength) #endif return false; } if (fileNamePointer == 0) fileNamePartStartIndex = MyStringLen(fileName); else fileNamePartStartIndex = (int)(fileNamePointer - buffer); } else { CSysString sysPath; if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); fileNamePartStartIndex = resultPath1.Length(); resultPath = resultPath1 + resultPath2; } return true; } #endif bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) { int index; return MyGetFullPathName(fileName, path, index); } #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &path) { int index; return MyGetFullPathName(fileName, path, index); } #endif bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #ifndef _UNICODE bool GetOnlyName(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Mid(index); return true; } #endif bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #ifndef _UNICODE bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) { int index; if (!MyGetFullPathName(fileName, resultName, index)) return false; resultName = resultName.Left(index); return true; } #endif bool MyGetCurrentDirectory(CSysString &path) { DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path) { if (g_IsNT) return BOOLToBool(::SetCurrentDirectoryW(path)); return MySetCurrentDirectory(GetSysPath(path)); } bool MyGetCurrentDirectory(UString &path) { if (g_IsNT) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetCurrentDirectory(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart) { LPTSTR filePartPointer; DWORD value = ::SearchPath(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart) { if (g_IsNT) { LPWSTR filePartPointer = 0; DWORD value = ::SearchPathW(path, fileName, extension, MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); resultPath.ReleaseBuffer(); return (value > 0 && value <= MAX_PATH); } CSysString sysPath; if (!MySearchPath( path != 0 ? (LPCTSTR)GetSysPath(path): 0, fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, sysPath, filePart)) return false; UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); filePart = resultPath1.Length(); resultPath = resultPath1 + resultPath2; return true; } #endif bool MyGetTempPath(CSysString &path) { DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } #ifndef _UNICODE bool MyGetTempPath(UString &path) { path.Empty(); if (g_IsNT) { DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return (needLength > 0 && needLength <= MAX_PATH); } CSysString sysPath; if (!MyGetTempPath(sysPath)) return false; path = GetUnicodePath(sysPath); return true; } #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) { UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); path.ReleaseBuffer(); return number; } #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) { if (g_IsNT) { UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); path.ReleaseBuffer(); return number; } CSysString sysPath; UINT number = MyGetTempFileName( dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, prefix ? (LPCTSTR)GetSysPath(prefix): 0, sysPath); path = GetUnicodePath(sysPath); return number; } #endif UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) { CSysString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFile::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #ifndef _UNICODE UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) { Remove(); UINT number = MyGetTempFileName(dirPath, prefix, resultPath); if (number != 0) { _fileName = resultPath; _mustBeDeleted = true; } return number; } bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) { UString tempPath; if (!MyGetTempPath(tempPath)) return false; if (Create(tempPath, prefix, resultPath) != 0) return true; if (!MyGetWindowsDirectory(tempPath)) return false; return (Create(tempPath, prefix, resultPath) != 0); } bool CTempFileW::Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !DeleteFileAlways(_fileName); return !_mustBeDeleted; } #endif bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFile tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!::DeleteFile(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectory::Create(LPCTSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #ifndef _UNICODE bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) { /* CSysString prefix = tempPath + prefixChars; CRandom random; random.Init(); */ for (;;) { CTempFileW tempFile; if (!tempFile.Create(prefix, dirName)) return false; if (!DeleteFileAlways(dirName)) return false; /* UINT32 randomNumber = random.Generate(); TCHAR randomNumberString[32]; _stprintf(randomNumberString, _T("%04X"), randomNumber); dirName = prefix + randomNumberString; */ if (NFind::DoesFileExist(dirName)) continue; if (MyCreateDirectory(dirName)) return true; if (::GetLastError() != ERROR_ALREADY_EXISTS) return false; } } bool CTempDirectoryW::Create(LPCWSTR prefix) { Remove(); return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); } #endif }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileDir.h ================================================ // Windows/FileDir.h #ifndef __WINDOWS_FILEDIR_H #define __WINDOWS_FILEDIR_H #include "../Common/MyString.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NDirectory { #ifdef WIN_LONG_PATH bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2); #endif bool MyGetWindowsDirectory(CSysString &path); bool MyGetSystemDirectory(CSysString &path); #ifndef _UNICODE bool MyGetWindowsDirectory(UString &path); bool MyGetSystemDirectory(UString &path); #endif bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName); bool MyRemoveDirectory(LPCTSTR pathName); bool MyCreateDirectory(LPCTSTR pathName); bool CreateComplexDirectory(LPCTSTR pathName); bool DeleteFileAlways(LPCTSTR name); bool RemoveDirectoryWithSubItems(const CSysString &path); #ifndef _UNICODE bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes); bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName); bool MyRemoveDirectory(LPCWSTR pathName); bool MyCreateDirectory(LPCWSTR pathName); bool CreateComplexDirectory(LPCWSTR pathName); bool DeleteFileAlways(LPCWSTR name); bool RemoveDirectoryWithSubItems(const UString &path); #endif #ifndef _WIN32_WCE bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath); bool GetOnlyName(LPCTSTR fileName, CSysString &resultName); bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName); #ifndef _UNICODE bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex); bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath); bool GetOnlyName(LPCWSTR fileName, UString &resultName); bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName); #endif inline bool MySetCurrentDirectory(LPCTSTR path) { return BOOLToBool(::SetCurrentDirectory(path)); } bool MyGetCurrentDirectory(CSysString &resultPath); #ifndef _UNICODE bool MySetCurrentDirectory(LPCWSTR path); bool MyGetCurrentDirectory(UString &resultPath); #endif #endif bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath, UINT32 &filePart); #ifndef _UNICODE bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath, UINT32 &filePart); #endif inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, CSysString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #ifndef _UNICODE inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) { UINT32 value; return MySearchPath(path, fileName, extension, resultPath, value); } #endif bool MyGetTempPath(CSysString &resultPath); #ifndef _UNICODE bool MyGetTempPath(UString &resultPath); #endif UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); #ifndef _UNICODE UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); #endif class CTempFile { bool _mustBeDeleted; CSysString _fileName; public: CTempFile(): _mustBeDeleted(false) {} ~CTempFile() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath); bool Create(LPCTSTR prefix, CSysString &resultPath); bool Remove(); }; #ifdef _UNICODE typedef CTempFile CTempFileW; #else class CTempFileW { bool _mustBeDeleted; UString _fileName; public: CTempFileW(): _mustBeDeleted(false) {} ~CTempFileW() { Remove(); } void DisableDeleting() { _mustBeDeleted = false; } UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath); bool Create(LPCWSTR prefix, UString &resultPath); bool Remove(); }; #endif bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName); class CTempDirectory { bool _mustBeDeleted; CSysString _tempDir; public: const CSysString &GetPath() const { return _tempDir; } CTempDirectory(): _mustBeDeleted(false) {} ~CTempDirectory() { Remove(); } bool Create(LPCTSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #ifdef _UNICODE typedef CTempDirectory CTempDirectoryW; #else class CTempDirectoryW { bool _mustBeDeleted; UString _tempDir; public: const UString &GetPath() const { return _tempDir; } CTempDirectoryW(): _mustBeDeleted(false) {} ~CTempDirectoryW() { Remove(); } bool Create(LPCWSTR prefix) ; bool Remove() { if (!_mustBeDeleted) return true; _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir); return (!_mustBeDeleted); } void DisableDeleting() { _mustBeDeleted = false; } }; #endif }}} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileFind.cpp ================================================ // Windows/FileFind.cpp #include "StdAfx.h" #include "FileFind.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif bool GetLongPath(LPCWSTR fileName, UString &res); namespace NFind { static const TCHAR kDot = TEXT('.'); bool CFileInfo::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #ifndef _UNICODE bool CFileInfoW::IsDots() const { if (!IsDir() || Name.IsEmpty()) return false; if (Name[0] != kDot) return false; return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2); } #endif static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #ifndef _UNICODE static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = fd.cFileName; #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi) { fi.Attrib = fd.dwFileAttributes; fi.CTime = fd.ftCreationTime; fi.ATime = fd.ftLastAccessTime; fi.MTime = fd.ftLastWriteTime; fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage()); #ifndef _WIN32_WCE fi.ReparseTag = fd.dwReserved0; #else fi.ObjectID = fd.dwOID; #endif } #endif //////////////////////////////// // CFindFile bool CFindFile::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::FindClose(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo) { if (!Close()) return false; WIN32_FIND_DATA fd; _handle = ::FindFirstFile(wildcard, &fd); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle == INVALID_HANDLE_VALUE) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return true; } #ifndef _UNICODE bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo) { if (!Close()) return false; if (g_IsNT) { WIN32_FIND_DATAW fd; _handle = ::FindFirstFileW(wildcard, &fd); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(wildcard, longPath)) _handle = ::FindFirstFileW(longPath, &fd); } #endif if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, GetCurrentCodePage()), &fd); if (_handle != INVALID_HANDLE_VALUE) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFindFile::FindNext(CFileInfo &fileInfo) { WIN32_FIND_DATA fd; bool result = BOOLToBool(::FindNextFile(_handle, &fd)); if (result) ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); return result; } #ifndef _UNICODE bool CFindFile::FindNext(CFileInfoW &fileInfo) { if (g_IsNT) { WIN32_FIND_DATAW fd; if (!::FindNextFileW(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } else { WIN32_FIND_DATAA fd; if (!::FindNextFileA(_handle, &fd)) return false; ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo); } return true; } #endif bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo) { CFindFile finder; return finder.FindFirst(wildcard, fileInfo); } #endif bool DoesFileExist(LPCTSTR name) { CFileInfo fileInfo; return FindFile(name, fileInfo); } #ifndef _UNICODE bool DoesFileExist(LPCWSTR name) { CFileInfoW fileInfo; return FindFile(name, fileInfo); } #endif ///////////////////////////////////// // CEnumerator bool CEnumerator::NextAny(CFileInfo &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumerator::Next(CFileInfo &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumerator::Next(CFileInfo &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #ifndef _UNICODE bool CEnumeratorW::NextAny(CFileInfoW &fileInfo) { if (_findFile.IsHandleAllocated()) return _findFile.FindNext(fileInfo); else return _findFile.FindFirst(_wildcard, fileInfo); } bool CEnumeratorW::Next(CFileInfoW &fileInfo) { for (;;) { if (!NextAny(fileInfo)) return false; if (!fileInfo.IsDots()) return true; } } bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found) { if (Next(fileInfo)) { found = true; return true; } found = false; return (::GetLastError() == ERROR_NO_MORE_FILES); } #endif //////////////////////////////// // CFindChangeNotification // FindFirstChangeNotification can return 0. MSDN doesn't tell about it. bool CFindChangeNotification::Close() { if (!IsHandleAllocated()) return true; if (!::FindCloseChangeNotification(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter) { _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH2 if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #ifndef _UNICODE HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter) { if (!g_IsNT) return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter); _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter); #ifdef WIN_LONG_PATH if (!IsHandleAllocated()) { UString longPath; if (GetLongPath(pathName, longPath)) _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter); } #endif return _handle; } #endif #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings) { driveStrings.Clear(); UINT32 size = GetLogicalDriveStrings(0, NULL); if (size == 0) return false; CSysString buffer; UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; CSysString string; for (UINT32 i = 0; i < newSize; i++) { TCHAR c = buffer[i]; if (c == TEXT('\0')) { driveStrings.Add(string); string.Empty(); } else string += c; } if (!string.IsEmpty()) return false; return true; } #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings) { driveStrings.Clear(); if (g_IsNT) { UINT32 size = GetLogicalDriveStringsW(0, NULL); if (size == 0) return false; UString buffer; UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); if (newSize == 0) return false; if (newSize > size) return false; UString string; for (UINT32 i = 0; i < newSize; i++) { WCHAR c = buffer[i]; if (c == L'\0') { driveStrings.Add(string); string.Empty(); } else string += c; } return string.IsEmpty(); } CSysStringVector driveStringsA; bool res = MyGetLogicalDriveStrings(driveStringsA); for (int i = 0; i < driveStringsA.Size(); i++) driveStrings.Add(GetUnicodeString(driveStringsA[i])); return res; } #endif #endif }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileFind.h ================================================ // Windows/FileFind.h #ifndef __WINDOWS_FILEFIND_H #define __WINDOWS_FILEFIND_H #include "../Common/MyString.h" #include "../Common/Types.h" #include "FileName.h" #include "Defs.h" namespace NWindows { namespace NFile { namespace NFind { namespace NAttributes { inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; } inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; } inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; } inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } } class CFileInfoBase { bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } public: UInt64 Size; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD Attrib; #ifndef _WIN32_WCE UINT32 ReparseTag; #else DWORD ObjectID; #endif bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); } bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); } bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); } bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); } bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); } bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); } bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); } bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); } bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } }; class CFileInfo: public CFileInfoBase { public: CSysString Name; bool IsDots() const; }; #ifdef _UNICODE typedef CFileInfo CFileInfoW; #else class CFileInfoW: public CFileInfoBase { public: UString Name; bool IsDots() const; }; #endif class CFindFile { friend class CEnumerator; HANDLE _handle; public: bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; } CFindFile(): _handle(INVALID_HANDLE_VALUE) {} ~CFindFile() { Close(); } bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo); bool FindNext(CFileInfo &fileInfo); #ifndef _UNICODE bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo); bool FindNext(CFileInfoW &fileInfo); #endif bool Close(); }; bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo); bool DoesFileExist(LPCTSTR name); #ifndef _UNICODE bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo); bool DoesFileExist(LPCWSTR name); #endif class CEnumerator { CFindFile _findFile; CSysString _wildcard; bool NextAny(CFileInfo &fileInfo); public: CEnumerator(): _wildcard(NName::kAnyStringWildcard) {} CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfo &fileInfo); bool Next(CFileInfo &fileInfo, bool &found); }; #ifdef _UNICODE typedef CEnumerator CEnumeratorW; #else class CEnumeratorW { CFindFile _findFile; UString _wildcard; bool NextAny(CFileInfoW &fileInfo); public: CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {} CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {} bool Next(CFileInfoW &fileInfo); bool Next(CFileInfoW &fileInfo, bool &found); }; #endif class CFindChangeNotification { HANDLE _handle; public: operator HANDLE () { return _handle; } bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; } CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {} ~CFindChangeNotification() { Close(); } bool Close(); HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter); #ifndef _UNICODE HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter); #endif bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); } }; #ifndef _WIN32_WCE bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings); #ifndef _UNICODE bool MyGetLogicalDriveStrings(UStringVector &driveStrings); #endif #endif }}} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifdef WIN_LONG_PATH #include "../Common/MyString.h" #endif #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { #if defined(WIN_LONG_PATH) && defined(_UNICODE) #define WIN_LONG_PATH2 #endif #ifdef WIN_LONG_PATH bool GetLongPathBase(LPCWSTR s, UString &res) { res.Empty(); int len = MyStringLen(s); wchar_t c = s[0]; if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.')) return true; UString curDir; bool isAbs = false; if (len > 3) isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z')); if (!isAbs) { DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1)); curDir.ReleaseBuffer(); if (needLength == 0 || needLength > MAX_PATH) return false; if (curDir[curDir.Length() - 1] != L'\\') curDir += L'\\'; } res = UString(L"\\\\?\\") + curDir + s; return true; } bool GetLongPath(LPCWSTR path, UString &longPath) { if (GetLongPathBase(path, longPath)) return !longPath.IsEmpty(); return false; } #endif namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!Close()) return false; _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH2 if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (!g_IsNT) return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); if (!Close()) return false; _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); #ifdef WIN_LONG_PATH if (_handle == INVALID_HANDLE_VALUE) { UString longPath; if (GetLongPath(fileName, longPath)) _handle = ::CreateFileW(longPath, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL); } #endif return (_handle != INVALID_HANDLE_VALUE); } #endif bool CFileBase::Close() { if (_handle == INVALID_HANDLE_VALUE) return true; if (!::CloseHandle(_handle)) return false; _handle = INVALID_HANDLE_VALUE; return true; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if (sizeLow == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if (::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if (!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CTime = winFileInfo.ftCreationTime; fileInfo.ATime = winFileInfo.ftLastAccessTime; fileInfo.MTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCTSTR fileName) { return OpenShared(fileName, false); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite) { return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } bool CInFile::Open(LPCWSTR fileName) { return OpenShared(fileName, false); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). // Probably in some version of Windows there are problems with other sizes: // for 32 MB (maybe also for 16 MB). // And message can be "Network connection was lost" static UInt32 kChunkSizeMax = (1 << 22); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } bool COutFile::SetMTime(const FILETIME *mTime) { return SetTime(NULL, NULL, mTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if (!Seek(length, newPosition)) return false; if (newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CTime; FILETIME ATime; FILETIME MTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _handle(INVALID_HANDLE_VALUE){}; ~CFileBase(); bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCTSTR fileName, bool shareForWrite); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool OpenShared(LPCWSTR fileName, bool shareForWrite); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); bool SetMTime(const FILETIME *mTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileMapping.cpp ================================================ // Windows/FileMapping.cpp #include "StdAfx.h" #include "Windows/FileMapping.h" namespace NWindows { namespace NFile { namespace NMapping { }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileMapping.h ================================================ // Windows/FileMapping.h #ifndef __WINDOWS_FILEMAPPING_H #define __WINDOWS_FILEMAPPING_H #include "Windows/Handle.h" #include "Windows/Defs.h" namespace NWindows { // namespace NFile { // namespace NMapping { class CFileMapping: public CHandle { public: bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes, DWORD protect, UINT64 maximumSize, LPCTSTR name) { _handle = ::CreateFileMapping(file, attributes, protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name); return (_handle != NULL); } bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name); return (_handle != NULL); } LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap) { return ::MapViewOfFile(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap); } LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress) { return ::MapViewOfFileEx(_handle, desiredAccess, DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap, baseAddress); } }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileName.cpp ================================================ // Windows/FileName.cpp #include "StdAfx.h" #include "Windows/FileName.h" #include "Common/Wildcard.h" namespace NWindows { namespace NFile { namespace NName { void NormalizeDirPathPrefix(CSysString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1) dirPath += kDirDelimiter; } #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath) { if (dirPath.IsEmpty()) return; if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1) dirPath += wchar_t(kDirDelimiter); } #endif const wchar_t kExtensionDelimiter = L'.'; void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension) { int index = fullName.ReverseFind(kExtensionDelimiter); if (index < 0) { pureName = fullName; extensionDelimiter.Empty(); extension.Empty(); } else { pureName = fullName.Left(index); extensionDelimiter = kExtensionDelimiter; extension = fullName.Mid(index + 1); } } }}} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/FileName.h ================================================ // Windows/FileName.h #ifndef __WINDOWS_FILENAME_H #define __WINDOWS_FILENAME_H #include "../Common/MyString.h" namespace NWindows { namespace NFile { namespace NName { const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR; const TCHAR kAnyStringWildcard = '*'; void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\' #ifndef _UNICODE void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\' #endif void SplitNameToPureNameAndExtension(const UString &fullName, UString &pureName, UString &extensionDelimiter, UString &extension); }}} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Handle.h ================================================ // Windows/Handle.h #ifndef __WINDOWS_HANDLE_H #define __WINDOWS_HANDLE_H namespace NWindows { class CHandle { protected: HANDLE _handle; public: operator HANDLE() { return _handle; } CHandle(): _handle(NULL) {} ~CHandle() { Close(); } bool Close() { if (_handle == NULL) return true; if (!::CloseHandle(_handle)) return false; _handle = NULL; return true; } void Attach(HANDLE handle) { _handle = handle; } HANDLE Detach() { HANDLE handle = _handle; _handle = NULL; return handle; } }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/MemoryLock.cpp ================================================ // Common/MemoryLock.cpp #include "StdAfx.h" namespace NWindows { namespace NSecurity { #ifndef _UNICODE typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle); typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid); typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength); #endif #ifdef _UNICODE bool EnableLockMemoryPrivilege( #else static bool EnableLockMemoryPrivilege2(HMODULE hModule, #endif bool enable) { #ifndef _UNICODE if (hModule == NULL) return false; OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken"); LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" ); AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges"); if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL) return false; #endif HANDLE token; if (! #ifdef _UNICODE ::OpenProcessToken #else openProcessToken #endif (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return false; TOKEN_PRIVILEGES tp; bool res = false; if ( #ifdef _UNICODE ::LookupPrivilegeValue #else lookupPrivilegeValue #endif (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid))) { tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0; if ( #ifdef _UNICODE ::AdjustTokenPrivileges #else adjustTokenPrivileges #endif (token, FALSE, &tp, 0, NULL, NULL)) res = (GetLastError() == ERROR_SUCCESS); } ::CloseHandle(token); return res; } #ifndef _UNICODE bool EnableLockMemoryPrivilege(bool enable) { HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll")); if (hModule == NULL) return false; bool res = EnableLockMemoryPrivilege2(hModule, enable); ::FreeLibrary(hModule); return res; } #endif }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/MemoryLock.h ================================================ // Windows/MemoryLock.h #ifndef __WINDOWS_MEMORYLOCK_H #define __WINDOWS_MEMORYLOCK_H namespace NWindows { namespace NSecurity { bool EnableLockMemoryPrivilege(bool enable = true); }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/PropVariant.cpp ================================================ // Windows/PropVariant.cpp #include "StdAfx.h" #include "PropVariant.h" #include "../Common/Defs.h" namespace NWindows { namespace NCOM { CPropVariant::CPropVariant(const PROPVARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(const CPropVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CPropVariant::CPropVariant(BSTR bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CPropVariant::CPropVariant(LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc) { InternalCopy(&varSrc); return *this; } CPropVariant& CPropVariant::operator=(BSTR bstrSrc) { *this = (LPCOLESTR)bstrSrc; return *this; } CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) { InternalClear(); vt = VT_BSTR; wReserved1 = 0; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; } return *this; } CPropVariant& CPropVariant::operator=(bool bSrc) { if (vt != VT_BOOL) { InternalClear(); vt = VT_BOOL; } boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; return *this; } CPropVariant& CPropVariant::operator=(UInt32 value) { if (vt != VT_UI4) { InternalClear(); vt = VT_UI4; } ulVal = value; return *this; } CPropVariant& CPropVariant::operator=(UInt64 value) { if (vt != VT_UI8) { InternalClear(); vt = VT_UI8; } uhVal.QuadPart = value; return *this; } CPropVariant& CPropVariant::operator=(const FILETIME &value) { if (vt != VT_FILETIME) { InternalClear(); vt = VT_FILETIME; } filetime = value; return *this; } CPropVariant& CPropVariant::operator=(Int32 value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } CPropVariant& CPropVariant::operator=(Byte value) { if (vt != VT_UI1) { InternalClear(); vt = VT_UI1; } bVal = value; return *this; } CPropVariant& CPropVariant::operator=(Int16 value) { if (vt != VT_I2) { InternalClear(); vt = VT_I2; } iVal = value; return *this; } /* CPropVariant& CPropVariant::operator=(LONG value) { if (vt != VT_I4) { InternalClear(); vt = VT_I4; } lVal = value; return *this; } */ static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) { switch(propVariant->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: propVariant->vt = VT_EMPTY; propVariant->wReserved1 = 0; return S_OK; } return ::VariantClear((VARIANTARG *)propVariant); } HRESULT CPropVariant::Clear() { return MyPropVariantClear(this); } HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) { ::VariantClear((tagVARIANT *)this); switch(pSrc->vt) { case VT_UI1: case VT_I1: case VT_I2: case VT_UI2: case VT_BOOL: case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: case VT_FILETIME: case VT_UI8: case VT_R8: case VT_CY: case VT_DATE: memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); return S_OK; } return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); } HRESULT CPropVariant::Attach(PROPVARIANT* pSrc) { HRESULT hr = Clear(); if (FAILED(hr)) return hr; memcpy(this, pSrc, sizeof(PROPVARIANT)); pSrc->vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::Detach(PROPVARIANT* pDest) { HRESULT hr = MyPropVariantClear(pDest); if (FAILED(hr)) return hr; memcpy(pDest, this, sizeof(PROPVARIANT)); vt = VT_EMPTY; return S_OK; } HRESULT CPropVariant::InternalClear() { HRESULT hr = Clear(); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } return hr; } void CPropVariant::InternalCopy(const PROPVARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; } } int CPropVariant::Compare(const CPropVariant &a) { if (vt != a.vt) return 0; // it's mean some bug switch (vt) { case VT_EMPTY: return 0; /* case VT_I1: return MyCompare(cVal, a.cVal); */ case VT_UI1: return MyCompare(bVal, a.bVal); case VT_I2: return MyCompare(iVal, a.iVal); case VT_UI2: return MyCompare(uiVal, a.uiVal); case VT_I4: return MyCompare(lVal, a.lVal); /* case VT_INT: return MyCompare(intVal, a.intVal); */ case VT_UI4: return MyCompare(ulVal, a.ulVal); /* case VT_UINT: return MyCompare(uintVal, a.uintVal); */ case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); case VT_BOOL: return -MyCompare(boolVal, a.boolVal); case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); case VT_BSTR: return 0; // Not implemented // return MyCompare(aPropVarint.cVal); default: return 0; } } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/PropVariant.h ================================================ // Windows/PropVariant.h #ifndef __WINDOWS_PROPVARIANT_H #define __WINDOWS_PROPVARIANT_H #include "../Common/MyWindows.h" #include "../Common/Types.h" namespace NWindows { namespace NCOM { class CPropVariant : public tagPROPVARIANT { public: CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } ~CPropVariant() { Clear(); } CPropVariant(const PROPVARIANT& varSrc); CPropVariant(const CPropVariant& varSrc); CPropVariant(BSTR bstrSrc); CPropVariant(LPCOLESTR lpszSrc); CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; } CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; } CPropVariant& operator=(const CPropVariant& varSrc); CPropVariant& operator=(const PROPVARIANT& varSrc); CPropVariant& operator=(BSTR bstrSrc); CPropVariant& operator=(LPCOLESTR lpszSrc); CPropVariant& operator=(bool bSrc); CPropVariant& operator=(UInt32 value); CPropVariant& operator=(UInt64 value); CPropVariant& operator=(const FILETIME &value); CPropVariant& operator=(Int32 value); CPropVariant& operator=(Byte value); CPropVariant& operator=(Int16 value); // CPropVariant& operator=(LONG value); HRESULT Clear(); HRESULT Copy(const PROPVARIANT* pSrc); HRESULT Attach(PROPVARIANT* pSrc); HRESULT Detach(PROPVARIANT* pDest); HRESULT InternalClear(); void InternalCopy(const PROPVARIANT* pSrc); int Compare(const CPropVariant &a1); }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/PropVariantConversions.cpp ================================================ // PropVariantConversions.cpp #include "StdAfx.h" #include "PropVariantConversions.h" #include "Windows/Defs.h" #include "Common/StringConvert.h" #include "Common/IntToString.h" static UString ConvertUInt64ToString(UInt64 value) { wchar_t buffer[32]; ConvertUInt64ToString(value, buffer); return buffer; } static UString ConvertInt64ToString(Int64 value) { wchar_t buffer[32]; ConvertInt64ToString(value, buffer); return buffer; } static char *UIntToStringSpec(char c, UInt32 value, char *s, int numPos) { if (c != 0) *s++ = c; char temp[16]; int pos = 0; do { temp[pos++] = (char)('0' + value % 10); value /= 10; } while (value != 0); int i; for (i = 0; i < numPos - pos; i++) *s++ = '0'; do *s++ = temp[--pos]; while (pos > 0); *s = '\0'; return s; } bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds) { s[0] = '\0'; SYSTEMTIME st; if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) return false; s = UIntToStringSpec(0, st.wYear, s, 4); s = UIntToStringSpec('-', st.wMonth, s, 2); s = UIntToStringSpec('-', st.wDay, s, 2); if (includeTime) { s = UIntToStringSpec(' ', st.wHour, s, 2); s = UIntToStringSpec(':', st.wMinute, s, 2); if (includeSeconds) UIntToStringSpec(':', st.wSecond, s, 2); } return true; } UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds) { char s[32]; ConvertFileTimeToString(fileTime, s, includeTime, includeSeconds); return GetUnicodeString(s); } UString ConvertPropVariantToString(const PROPVARIANT &prop) { switch (prop.vt) { case VT_EMPTY: return UString(); case VT_BSTR: return prop.bstrVal; case VT_UI1: return ConvertUInt64ToString(prop.bVal); case VT_UI2: return ConvertUInt64ToString(prop.uiVal); case VT_UI4: return ConvertUInt64ToString(prop.ulVal); case VT_UI8: return ConvertUInt64ToString(prop.uhVal.QuadPart); case VT_FILETIME: return ConvertFileTimeToString(prop.filetime, true, true); // case VT_I1: return ConvertInt64ToString(prop.cVal); case VT_I2: return ConvertInt64ToString(prop.iVal); case VT_I4: return ConvertInt64ToString(prop.lVal); case VT_I8: return ConvertInt64ToString(prop.hVal.QuadPart); case VT_BOOL: return VARIANT_BOOLToBool(prop.boolVal) ? L"+" : L"-"; default: #ifndef _WIN32_WCE throw 150245; #else return UString(); #endif } } UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &prop) { switch (prop.vt) { case VT_UI1: return prop.bVal; case VT_UI2: return prop.uiVal; case VT_UI4: return prop.ulVal; case VT_UI8: return (UInt64)prop.uhVal.QuadPart; default: #ifndef _WIN32_WCE throw 151199; #else return 0; #endif } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/PropVariantConversions.h ================================================ // Windows/PropVariantConversions.h #ifndef __PROPVARIANTCONVERSIONS_H #define __PROPVARIANTCONVERSIONS_H #include "Common/Types.h" #include "Common/MyString.h" bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true); UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true); UString ConvertPropVariantToString(const PROPVARIANT &propVariant); UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant); #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Synchronization.cpp ================================================ // Windows/Synchronization.cpp #include "StdAfx.h" #include "Synchronization.h" namespace NWindows { namespace NSynchronization { }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Synchronization.h ================================================ // Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } operator HANDLE() { return _object.handle; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (_object.handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object.handle != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated() { if (IsCreated()) return 0; return AutoResetEvent_CreateNotSignaled(&_object); } }; #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES securityAttributes = NULL) { _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif class CSemaphore { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } operator HANDLE() { return _object.handle; } WRes Create(UInt32 initiallyCount, UInt32 maxCount) { return Semaphore_Create(&_object, initiallyCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/System.cpp ================================================ // Windows/System.cpp #include "StdAfx.h" #include "System.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors() { SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); return (UInt32)systemInfo.dwNumberOfProcessors; } #if !defined(_WIN64) && defined(__GNUC__) typedef struct _MY_MEMORYSTATUSEX { DWORD dwLength; DWORD dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual; } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX; #else #define MY_MEMORYSTATUSEX MEMORYSTATUSEX #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX #endif typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer); UInt64 GetRamSize() { MY_MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); #ifdef _WIN64 if (!::GlobalMemoryStatusEx(&stat)) return 0; return stat.ullTotalPhys; #else GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GlobalMemoryStatusEx"); if (globalMemoryStatusEx != 0) if (globalMemoryStatusEx(&stat)) return stat.ullTotalPhys; { MEMORYSTATUS stat; stat.dwLength = sizeof(stat); GlobalMemoryStatus(&stat); return stat.dwTotalPhys; } #endif } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/System.h ================================================ // Windows/System.h #ifndef __WINDOWS_SYSTEM_H #define __WINDOWS_SYSTEM_H #include "../Common/Types.h" namespace NWindows { namespace NSystem { UInt32 GetNumberOfProcessors(); UInt64 GetRamSize(); }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Thread.h ================================================ // Windows/Thread.h #ifndef __WINDOWS_THREAD_H #define __WINDOWS_THREAD_H #include "Defs.h" extern "C" { #include "../../C/Threads.h" } namespace NWindows { class CThread { ::CThread thread; public: CThread() { Thread_Construct(&thread); } ~CThread() { Close(); } bool IsCreated() { return Thread_WasCreated(&thread) != 0; } WRes Close() { return Thread_Close(&thread); } WRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter) { return Thread_Create(&thread, startAddress, parameter); } WRes Wait() { return Thread_Wait(&thread); } #ifdef _WIN32 operator HANDLE() { return thread.handle; } void Attach(HANDLE handle) { thread.handle = handle; } HANDLE Detach() { HANDLE h = thread.handle; thread.handle = NULL; return h; } DWORD Resume() { return ::ResumeThread(thread.handle); } DWORD Suspend() { return ::SuspendThread(thread.handle); } bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); } int GetPriority() { return ::GetThreadPriority(thread.handle); } bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); } #endif }; } #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Time.cpp ================================================ // Windows/Time.cpp #include "StdAfx.h" #include "Time.h" #include "Windows/Defs.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) { return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &fileTime)); } static const UInt32 kHighDosTime = 0xFF9FBF7D; static const UInt32 kLowDosTime = 0x210000; bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) { WORD datePart, timePart; if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart)) { dosTime = (fileTime.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime; return false; } dosTime = (((UInt32)datePart) << 16) + timePart; return true; } static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774; void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) { UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond; fileTime.dwLowDateTime = (DWORD)v; fileTime.dwHighDateTime = (DWORD)(v >> 32); } bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) { UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime; if (winTime < kUnixTimeStartValue) { unixTime = 0; return false; } winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond; if (winTime > 0xFFFFFFFF) { unixTime = 0xFFFFFFFF; return false; } unixTime = (UInt32)winTime; return true; } bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) { resSeconds = 0; if (year < 1601 || year >= 10000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59) return false; UInt32 numYears = year - 1601; UInt32 numDays = numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ms[1] = 29; month--; for (unsigned i = 0; i < month; i++) numDays += ms[i]; numDays += day - 1; resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec; return true; } void GetCurUtcFileTime(FILETIME &ft) { SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); } }} ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CPP/Windows/Time.h ================================================ // Windows/Time.h #ifndef __WINDOWS_TIME_H #define __WINDOWS_TIME_H #include "Common/Types.h" namespace NWindows { namespace NTime { bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime); bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime); void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime); bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime); bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds); void GetCurUtcFileTime(FILETIME &ft); }} #endif ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void SetStream(System.IO.Stream inStream); void Init(); void ReleaseStream(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetMatches(UInt32[] distances); void Skip(UInt32 num); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize = 0; UInt32 _matchMaxLen; UInt32[] _son; UInt32[] _hash; UInt32 _cutValue = 0xFF; UInt32 _hashMask; UInt32 _hashSizeSum = 0; bool HASH_ARRAY = true; const UInt32 kHash2Size = 1 << 10; const UInt32 kHash3Size = 1 << 16; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kStartMaxLen = 1; const UInt32 kHash3Offset = kHash2Size; const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 kNumHashDirectBytes = 0; UInt32 kMinMatchCheck = 4; UInt32 kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (UInt32 i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) throw new Exception(); _cutValue = 16 + (matchMaxLen >> 1); UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; UInt32 cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; UInt32 hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new UInt32[_hashSizeSum = hs]; } public UInt32 GetMatches(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } UInt32 offset = 0; UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { UInt32 curMatch2 = _hash[hash2Value]; UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(UInt32 num) { do { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue; if (HASH_ARRAY) { UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; UInt32 hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); UInt32 hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; } else hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); UInt32 curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; UInt32 ptr1 = (_cyclicBufferPos << 1); UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; UInt32 pby1 = _bufferOffset + curMatch; UInt32 len = Math.Min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(System.IO.Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public uint TrainSize = 0; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; TrainSize = 0; } } public bool Train(System.IO.Stream stream) { long len = stream.Length; uint size = (len < _windowSize) ? (uint)len : _windowSize; TrainSize = size; stream.Position = len - size; _streamPos = _pos = 0; while (size > 0) { uint curSize = _windowSize - _pos; if (size < curSize) curSize = size; int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); if (numReadBytes == 0) return false; size -= (uint)numReadBytes; _pos += (uint)numReadBytes; _streamPos += (uint)numReadBytes; if (_pos == _windowSize) _streamPos = _pos = 0; } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; // public const int kDicLogSizeMax = 30; // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } bool _solid = false; void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } public bool Train(System.IO.Stream stream) { _solid = true; return m_OutWindow.Train(stream); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, }; const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1 << 11]; static Encoder() { const Byte kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (UInt32)(g_FastPos[pos >> 10] + 20); return (UInt32)(g_FastPos[pos >> 20] + 40); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 17)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (UInt32)(g_FastPos[pos >> 16] + 32); return (UInt32)(g_FastPos[pos >> 26] + 52); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 22; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) { UInt32 a0 = _choice.GetPrice0(); UInt32 a1 = _choice.GetPrice1(); UInt32 b0 = a1 + _choice2.GetPrice0(); UInt32 b1 = a1 + _choice2.GetPrice1(); UInt32 i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(UInt32 posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; public UInt32 BackPrev; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _numDistancePairs; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark = false; bool _needReleaseMFStream; void Create() { if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderType.BT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) { lenRes = 0; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs > 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; } void MovePos(UInt32 num) { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) { UInt32 price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; UInt32 lenMain, numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain, out numDistancePairs); } else { lenMain = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = 0xFFFFFFFF; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = (UInt32)0xFFFFFFFF; return 1; } _optimum[0].State = _state; UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if(lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; if (repLen < 2) continue; UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { UInt32 offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { UInt32 distance = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } UInt32 cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(out backRes, cur); UInt32 newLen; ReadMatchDistances(out newLen, out numDistancePairs); if (newLen >= _numFastBytes) { _numDistancePairs = numDistancePairs; _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); { UInt32 offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } UInt32 startLen = 2; // speed optimization for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (UInt32 lenTest = startLen; ; lenTest++) { UInt32 curBack = _matchDistances[offs + 1]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize > 0) _matchFinder.Skip(_trainSize); } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len, numDistancePairs; // it's not used ReadMatchDistances(out len, out numDistancePairs); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 len = GetOptimum((UInt32)nowPos64, out pos); UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; UInt32 _matchPriceCount; void FillDistancesPrices() { for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; UInt32 st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); UInt32 st2 = lenToPosState * Base.kNumFullDistances; UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } static string[] kMatchFinderIDs = { "BT2", "BT4", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { /* if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); */ break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 30; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } uint _trainSize = 0; public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; public class CDoubleStream: Stream { public System.IO.Stream s1; public System.IO.Stream s2; public int fileIndex; public long skipSize; public override bool CanRead { get { return true; }} public override bool CanWrite { get { return false; }} public override bool CanSeek { get { return false; }} public override long Length { get { return s1.Length + s2.Length - skipSize; } } public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { int numTotal = 0; while (count > 0) { if (fileIndex == 0) { int num = s1.Read(buffer, offset, count); offset += num; count -= num; numTotal += num; if (num == 0) fileIndex++; } if (fileIndex == 1) { numTotal += s2.Read(buffer, offset, count); return numTotal; } } return numTotal; } public override void Write(byte[] buffer, int offset, int count) { throw (new Exception("can't Write")); } public override long Seek(long offset, System.IO.SeekOrigin origin) { throw (new Exception("can't Seek")); } public override void SetLength(long value) { throw (new Exception("can't SetLength")); } } class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut, Train }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0, 29], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.61 2008-11-23\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[13]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary); } string train = ""; if (parser[(int)Key.Train].ThereIs) train = (string)parser[(int)Key.Train].PostStrings[0]; bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; Stream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } FileStream trainStream = null; if (train.Length != 0) trainStream = new FileStream(train, FileMode.Open, FileAccess.Read); if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); if (trainStream != null) { CDoubleStream doubleStream = new CDoubleStream(); doubleStream.s1 = trainStream; doubleStream.s2 = inStream; doubleStream.fileIndex = 0; inStream = doubleStream; long trainFileSize = trainStream.Length; doubleStream.skipSize = 0; if (trainFileSize > dictionary) doubleStream.skipSize = trainFileSize - dictionary; trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin); encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize)); } encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); if (trainStream != null) { if (!decoder.Train(trainStream)) throw (new Exception("can't train")); } long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.50727</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>LzmaAlone</RootNamespace> <AssemblyName>Lzma#</AssemblyName> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>.\bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugSymbols>false</DebugSymbols> <Optimize>true</Optimize> <OutputPath>.\bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\CommandLineParser.cs"> <Link>Common\CommandLineParser.cs</Link> </Compile> <Compile Include="..\..\Common\CRC.cs"> <Link>Common\CRC.cs</Link> </Compile> <Compile Include="..\..\ICoder.cs"> <Link>ICoder.cs</Link> </Compile> <Compile Include="..\LZ\IMatchFinder.cs"> <Link>LZ\IMatchFinder.cs</Link> </Compile> <Compile Include="..\LZ\LzBinTree.cs"> <Link>LZ\LzBinTree.cs</Link> </Compile> <Compile Include="..\LZ\LzInWindow.cs"> <Link>LZ\LzInWindow.cs</Link> </Compile> <Compile Include="..\LZ\LzOutWindow.cs"> <Link>LZ\LzOutWindow.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaBase.cs"> <Link>LZMA\LzmaBase.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaDecoder.cs"> <Link>LZMA\LzmaDecoder.cs</Link> </Compile> <Compile Include="..\LZMA\LzmaEncoder.cs"> <Link>LZMA\LzmaEncoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoder.cs"> <Link>RangeCoder\RangeCoder.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBit.cs"> <Link>RangeCoder\RangeCoderBit.cs</Link> </Compile> <Compile Include="..\RangeCoder\RangeCoderBitTree.cs"> <Link>RangeCoder\RangeCoderBitTree.cs</Link> </Compile> <Compile Include="LzmaAlone.cs"> <SubType>Code</SubType> </Compile> <Compile Include="LzmaBench.cs"> <SubType>Code</SubType> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.cs"> <AutoGen>True</AutoGen> <DependentUpon>Settings.settings</DependentUpon> </Compile> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> </Project> ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// <summary> /// LZMA Benchmark /// </summary> internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; UInt32 Rep0; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)RG.GetRnd(8); else { UInt32 len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) { UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, }; object[] properties = { (Int32)(dictionarySize), }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// <summary> /// A strongly-typed resource class, for looking up localized strings, etc. /// </summary> // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// <summary> /// Returns the cached ResourceManager instance used by this class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// <summary> /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// </summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // <autogenerated> // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// <summary> /// The exception that is thrown when an error in input stream occurs during decoding. /// </summary> class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// <summary> /// The exception that is thrown when the value of an argument is outside the allowable range. /// </summary> class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// <summary> /// Callback progress. /// </summary> /// <param name="inSize"> /// input size. -1 if unknown. /// </param> /// <param name="outSize"> /// output size. -1 if unknown. /// </param> void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// <summary> /// Codes streams. /// </summary> /// <param name="inStream"> /// input Stream. /// </param> /// <param name="outStream"> /// output Stream. /// </param> /// <param name="inSize"> /// input Size. -1 if unknown. /// </param> /// <param name="outSize"> /// output Size. -1 if unknown. /// </param> /// <param name="progress"> /// callback progress reference. /// </param> /// <exception cref="SevenZip.DataErrorException"> /// if input stream is not valid /// </exception> void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// <summary> /// Provides the fields that represent properties idenitifiers for compressing. /// </summary> public enum CoderPropID { /// <summary> /// Specifies size of dictionary. /// </summary> DictionarySize = 0x400, /// <summary> /// Specifies size of memory for PPM*. /// </summary> UsedMemorySize, /// <summary> /// Specifies order for PPM methods. /// </summary> Order, /// <summary> /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// </summary> PosStateBits = 0x440, /// <summary> /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// </summary> LitContextBits, /// <summary> /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// </summary> LitPosBits, /// <summary> /// Specifies number of fast bytes for LZ*. /// </summary> NumFastBytes = 0x450, /// <summary> /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// </summary> MatchFinder, /// <summary> /// Specifies number of passes. /// </summary> NumPasses = 0x460, /// <summary> /// Specifies number of algorithm. /// </summary> Algorithm = 0x470, /// <summary> /// Specifies multithread mode. /// </summary> MultiThread = 0x480, /// <summary> /// Specifies mode with end marker. /// </summary> EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZ/BinTree.java ================================================ // LZ.BinTree package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize = 0; int _matchMaxLen; int[] _son; int[] _hash; int _cutValue = 0xFF; int _hashMask; int _hashSizeSum = 0; boolean HASH_ARRAY = true; static final int kHash2Size = 1 << 10; static final int kHash3Size = 1 << 16; static final int kBT2HashSize = 1 << 16; static final int kStartMaxLen = 1; static final int kHash3Offset = kHash2Size; static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = (1 << 30) - 1; int kNumHashDirectBytes = 0; int kMinMatchCheck = 4; int kFixHashSize = kHash2Size + kHash3Size; public void SetType(int numHashBytes) { HASH_ARRAY = (numHashBytes > 2); if (HASH_ARRAY) { kNumHashDirectBytes = 0; kMinMatchCheck = 4; kFixHashSize = kHash2Size + kHash3Size; } else { kNumHashDirectBytes = 2; kMinMatchCheck = 2 + 1; kFixHashSize = 0; } } public void Init() throws IOException { super.Init(); for (int i = 0; i < _hashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { if (historySize > kMaxValForNormalize - 256) return false; _cutValue = 16 + (matchMaxLen >> 1); int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); _matchMaxLen = matchMaxLen; int cyclicBufferSize = historySize + 1; if (_cyclicBufferSize != cyclicBufferSize) _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2]; int hs = kBT2HashSize; if (HASH_ARRAY) { hs = historySize - 1; hs |= (hs >> 1); hs |= (hs >> 2); hs |= (hs >> 4); hs |= (hs >> 8); hs >>= 1; hs |= 0xFFFF; if (hs > (1 << 24)) hs >>= 1; _hashMask = hs; hs++; hs += kFixHashSize; } if (hs != _hashSizeSum) _hash = new int [_hashSizeSum = hs]; return true; } public int GetMatches(int[] distances) throws IOException { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); return 0; } } int offset = 0; int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int maxLen = kStartMaxLen; // to avoid items for len < hashSize; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; if (HASH_ARRAY) { int curMatch2 = _hash[hash2Value]; int curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[hash2Value] = _pos; _hash[kHash3Offset + hash3Value] = _pos; if (curMatch2 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { distances[offset++] = maxLen = 2; distances[offset++] = _pos - curMatch2 - 1; } if (curMatch3 > matchMinPos) if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { if (curMatch3 == curMatch2) offset -= 2; distances[offset++] = maxLen = 3; distances[offset++] = _pos - curMatch3 - 1; curMatch2 = curMatch3; } if (offset != 0 && curMatch2 == curMatch) { offset -= 2; maxLen = kStartMaxLen; } } _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; if (kNumHashDirectBytes != 0) { if (curMatch > matchMinPos) { if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != _bufferBase[cur + kNumHashDirectBytes]) { distances[offset++] = maxLen = kNumHashDirectBytes; distances[offset++] = _pos - curMatch - 1; } } } int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while(++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (maxLen < len) { distances[offset++] = maxLen = len; distances[offset++] = delta - 1; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); return offset; } public void Skip(int num) throws IOException { do { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kMinMatchCheck) { MovePos(); continue; } } int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; int cur = _bufferOffset + _pos; int hashValue; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); int hash2Value = temp & (kHash2Size - 1); _hash[hash2Value] = _pos; temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); int hash3Value = temp & (kHash3Size - 1); _hash[kHash3Offset + hash3Value] = _pos; hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask; } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)); int curMatch = _hash[kFixHashSize + hashValue]; _hash[kFixHashSize + hashValue] = _pos; int ptr0 = (_cyclicBufferPos << 1) + 1; int ptr1 = (_cyclicBufferPos << 1); int len0, len1; len0 = len1 = kNumHashDirectBytes; int count = _cutValue; while (true) { if (curMatch <= matchMinPos || count-- == 0) { _son[ptr0] = _son[ptr1] = kEmptyHashValue; break; } int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; int pby1 = _bufferOffset + curMatch; int len = Math.min(len0, len1); if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break; if (len == lenLimit) { _son[ptr1] = _son[cyclicPos]; _son[ptr0] = _son[cyclicPos + 1]; break; } } if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF)) { _son[ptr1] = curMatch; ptr1 = cyclicPos + 1; curMatch = _son[ptr1]; len1 = len; } else { _son[ptr0] = curMatch; ptr0 = cyclicPos; curMatch = _son[ptr0]; len0 = len; } } MovePos(); } while (--num != 0); } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindow package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; // we need one additional byte, since MovePos moves on 1 byte. if (offset > 0) offset--; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; // public static final int kDicLogSizeMax = 28; // public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1 << 11]; static { int kFastSlots = 22; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 11)) return g_FastPos[pos]; if (pos < (1 << 21)) return (g_FastPos[pos >> 10] + 20); return (g_FastPos[pos >> 20] + 40); } static int GetPosSlot2(int pos) { if (pos < (1 << 17)) return (g_FastPos[pos >> 6] + 12); if (pos < (1 << 27)) return (g_FastPos[pos >> 16] + 32); return (g_FastPos[pos >> 26] + 52); } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 22; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public void SetPrices(int posState, int numSymbols, int[] prices, int st) { int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); int i = 0; for (i = 0; i < Base.kNumLowLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); } for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) { if (i >= numSymbols) return; prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); } for (; i < numSymbols; i++) prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[posState * Base.kNumLenSymbols + symbol]; } void UpdateTable(int posState) { SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; public int BackPrev; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _numDistancePairs; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; int[] _alignPrices = new int[Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; if (_matchFinderType == EMatchFinderTypeBT2) numHashBytes = 2; bt.SetType(numHashBytes); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(boolean writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = 0; _numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (_numDistancePairs > 0) { lenRes = _matchDistances[_numDistancePairs - 2]; if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], Base.kMatchMaxLen - lenRes); } _additionalOffset++; return lenRes; } void MovePos(int num) throws java.io.IOException { if (num > 0) { _matchFinder.Skip(num); _additionalOffset += num; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetPureRepPrice(int repIndex, int state, int posState) { int price; if (repIndex == 0) { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); return price + GetPureRepPrice(repIndex, state, posState); } int GetPosLenPrice(int pos, int len, int posState) { int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; else price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int backRes; int GetOptimum(int position) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = _optimumEndIndex = 0; int lenMain, numDistancePairs; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } numDistancePairs = _numDistancePairs; int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; if (numAvailableBytes < 2) { backRes = -1; return 1; } if (numAvailableBytes > Base.kMatchMaxLen) numAvailableBytes = Base.kMatchMaxLen; int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) { backRes = -1; return 1; } _optimum[0].State = _state; int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); if (lenEnd < 2) { backRes = _optimum[1].BackPrev; return 1; } _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int len = lenEnd; do _optimum[len--].Price = kIfinityPrice; while (len >= 2); for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; if (repLen < 2) continue; int price = repMatchPrice + GetPureRepPrice(i, _state, posState); do { int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); Optimal optimum = _optimum[repLen]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } while (--repLen >= 2); } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); if (len <= lenMain) { int offs = 0; while (len > _matchDistances[offs]) offs += 2; for (; ; len++) { int distance = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); Optimal optimum = _optimum[len]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = distance + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (len == _matchDistances[offs]) { offs += 2; if (offs == numDistancePairs) break; } } } int cur = 0; while (true) { cur++; if (cur == lenEnd) return Backward(cur); int newLen = ReadMatchDistances(); numDistancePairs = _numDistancePairs; if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); nextIsChar = true; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (!nextIsChar && matchByte != currentByte) { // try Literal + rep0 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); { int offset = cur + 1 + lenTest2; while (lenEnd < offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } int startLen = 2; // speed optimization for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); if (lenTest < 2) continue; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while (--lenTest >= 2); lenTest = lenTestTemp; if (repIndex == 0) startLen = lenTest + 1; // if (_maxMode) if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } if (newLen > numAvailableBytes) { newLen = numAvailableBytes; for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; _matchDistances[numDistancePairs] = newLen; numDistancePairs += 2; } if (newLen >= startLen) { normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; int offs = 0; while (startLen > _matchDistances[offs]) offs += 2; for (int lenTest = startLen; ; lenTest++) { int curBack = _matchDistances[offs + 1]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (lenTest == _matchDistances[offs]) { if (lenTest < numAvailableBytesFull) { int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } offs += 2; if (offs == numDistancePairs) break; } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int len = GetOptimum((int)nowPos64); int pos = backRes; int posState = ((int)nowPos64) & _posStateMask; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); _alignPriceCount++; } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (_additionalOffset == 0) { // if (!_fastMode) if (_matchPriceCount >= (1 << 7)) FillDistancesPrices(); if (_alignPriceCount >= Base.kAlignTableSize) FillAlignPrices(); inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // if (!_fastMode) { FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } int[] tempPrices = new int[Base.kNumFullDistances]; int _matchPriceCount; void FillDistancesPrices() { for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; int st = (lenToPosState << Base.kNumPosSlotBits); for (posSlot = 0; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); int st2 = lenToPosState * Base.kNumFullDistances; int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + i]; for (; i < Base.kNumFullDistances; i++) _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; } _matchPriceCount = 0; } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = 0; } public boolean SetAlgorithm(int algorithm) { /* _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); */ return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = 29; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; _distTableSize = dicLogSize * 2; return true; } public boolean SetNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA <e|d> [<switches>...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "<Switches>\n" + // " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.61 2008-11-23\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; int Rep0; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } public void Generate() { RG.Init(); Rep0 = 1; while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int len; if (RG.GetRnd(3) == 0) len = 1 + GetLen1(); else { do Rep0 = GetOffset(); while (Rep0 >= Pos); Rep0++; len = 2 + GetLen2(); } for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - Rep0]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, long elapsedTime, long size) { long t = GetLogSize(dictionarySize) - (18 << kSubBits); long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 220 + outSize * 20; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, elapsedTime, size); PrintRating(rating); } static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 18)) { System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/Methods.txt ================================================ 7-Zip method IDs (4.65) ----------------------- Each compression or crypto method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). If you want to add some new ID, you have two ways: 1) Write request for allocating IDs to 7-zip developers. 2) Generate 8-bytes ID: 3F ZZ ZZ ZZ ZZ ZZ MM MM 3F - Prefix for random IDs (1 byte) ZZ ZZ ZZ ZZ ZZ - Developer ID (5 bytes). Use real random bytes. MM MM - Method ID (2 bytes) You can notify 7-Zip developers about your Developer ID / Method ID. Note: Use new ID only if old codec can not decode data encoded with new version. List of defined IDs ------------------- 00 - Copy 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - PPC (Big Endian) 03 - Alpha 01 - Alpha 04 - IA64 01 - IA64 05 - ARM 01 - ARM 06 - M68 05 - M68 (Big Endian) 07 - ARM Thumb 01 - ARMT 08 - SPARC 05 - SPARC 04 - PPMD 01 - Version 7F - 01 - experimental methods. 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 09 - NSIS 01 - DeflateNSIS 02 - BZip2NSIS 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 Cx - AES x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- 4.65 2009-02-03 ------------------------- - Some minor fixes 4.63 2008-12-31 ------------------------- - Some minor fixes 4.61 beta 2008-11-23 ------------------------- - The bug in ANSI-C LZMA Decoder was fixed: If encoded stream was corrupted, decoder could access memory outside of allocated range. - Some changes in ANSI-C 7z Decoder interfaces. - LZMA SDK is placed in the public domain. 4.60 beta 2008-08-19 ------------------------- - Some minor fixes. 4.59 beta 2008-08-13 ------------------------- - The bug was fixed: LZMA Encoder in fast compression mode could access memory outside of allocated range in some rare cases. 4.58 beta 2008-05-05 ------------------------- - ANSI-C LZMA Decoder was rewritten for speed optimizations. - ANSI-C LZMA Encoder was included to LZMA SDK. - C++ LZMA code now is just wrapper over ANSI-C code. 4.57 2007-12-12 ------------------------- - Speed optimizations in ++ LZMA Decoder. - Small changes for more compatibility with some C/C++ compilers. 4.49 beta 2007-07-05 ------------------------- - .7z ANSI-C Decoder: - now it supports BCJ and BCJ2 filters - now it supports files larger than 4 GB. - now it supports "Last Write Time" field for files. - C++ code for .7z archives compressing/decompressing from 7-zip was included to LZMA SDK. 4.43 2006-06-04 ------------------------- - Small changes for more compatibility with some C/C++ compilers. 4.42 2006-05-15 ------------------------- - Small changes in .h files in ANSI-C version. 4.39 beta 2006-04-14 ------------------------- - The bug in versions 4.33b:4.38b was fixed: C++ version of LZMA encoder could not correctly compress files larger than 2 GB with HC4 match finder (-mfhc4). 4.37 beta 2005-04-06 ------------------------- - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 4.35 beta 2005-03-02 ------------------------- - The bug was fixed in C++ version of LZMA Decoder: If encoded stream was corrupted, decoder could access memory outside of allocated range. 4.34 beta 2006-02-27 ------------------------- - Compressing speed and memory requirements for compressing were increased - LZMA now can use only these match finders: HC4, BT2, BT3, BT4 4.32 2005-12-09 ------------------------- - Java version of LZMA SDK was included 4.30 2005-11-20 ------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - The bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included 4.27 (Updated) 2005-09-21 ------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart 4.27 2005-08-07 ------------------------- - The bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. 4.26 2005-08-05 ------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 4.23 2005-06-29 ------------------------- - Small fixes in C++ code 4.22 2005-06-10 ------------------------- - Small fixes 4.21 2005-06-08 ------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB 4.17 2005-04-18 ------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe 4.16 2005-03-29 ------------------------- - The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included 4.06 2004-09-05 ------------------------- - The bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. 4.05 2004-08-25 ------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes 4.04 2004-07-28 ------------------------- - More compatibility with some C++ compilers 4.03 2004-06-18 ------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. 4.02 2004-06-10 ------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. 4.01 2004-02-15 ------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } 4.00 2004-02-13 ------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2008: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/others/squashfs-4.2/lzma-4.65/lzma.txt ================================================ LZMA SDK 4.65 ------------- LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is written and placed in the public domain by Igor Pavlov. LZMA SDK Contents ----------------- LZMA SDK includes: - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system UNIX/Linux version ------------------ To compile C++ version of file->file LZMA encoding, go to directory C++/7zip/Compress/LZMA_Alone and call make to recompile it: make -f makefile.gcc clean all In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, you can use LIB = -lm -static Files --------------------- lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description methods.txt - Compression method IDs for .7z lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C/ - C files 7zCrc*.* - CRC code Alloc.* - Memory allocation functions Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code LzFind.* - Match finder for LZ (LZMA) encoders LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding LzHash.h - Additional file for LZ match finder LzmaDec.* - LZMA decoding LzmaEnc.* - LZMA encoding LzmaLib.* - LZMA Library for DLL calling Types.h - Basic types for another .c files Threads.* - The code for multithreading. LzmaLib - LZMA Library (.DLL for Windows) LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). Archive - files related to archiving 7z - 7z ANSI-C Decoder CPP/ -- CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression Copy - Copy coder RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving Common - common files for archive handling 7z - 7z C++ Encoder/Decoder Bundles - Modules that are bundles of other modules Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. UI - User Interface files Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll Common - Common UI files Console - Code for console archiver CS/ - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java/ - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA features ------------- - Variable dictionary size (up to 1 GB) - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - Estimated decompressing speed: - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (16 KB + DictionarySize) - Small code size for decompressing: 5-8 KB LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect the speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations The speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA <e|d> inputFile outputFile [<switches>...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with Intel's Core 2 results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. Also you can change the number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. <Switches> -a{N}: set compression mode 0 = fast, 1 = normal default: 1 (normal) d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) The maximum value for dictionary size is 1 GB = 2^30 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase the compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Filters ------- You can increase the compression ratio for some data types, using special filters before compressing. For example, it's possible to increase the compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C source code of such filters in C/Bra*.* files You can check the compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=arm -m1=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties (lc,lp, pb in encoded form) 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. If you want to use old interfaces you can download previous version of LZMA SDK from sourceforge.net site. To use ANSI-C LZMA Decoder you need the following files: 1) LzmaDec.h + LzmaDec.c + Types.h LzmaUtil/LzmaUtil.c is example application that uses these files. Memory requirements for LZMA decoding ------------------------------------- Stack usage of LZMA decoding function for local variables is not larger than 200-400 bytes. LZMA Decoder uses dictionary buffer and internal state structure. Internal state structure consumes state_size = (4 + (1.5 << (lc + lp))) KB by default (lc=3, lp=0), state_size = 16 KB. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 2 interfaces: 1) Single-call Decompressing 2) Multi-call State Decompressing (zlib-like interface) You must use external allocator: Example: void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } void SzFree(void *p, void *address) { p = p; free(address); } ISzAlloc alloc = { SzAlloc, SzFree }; You can use p = p; operator to disable compiler warnings. Single-call Decompressing ------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures: state_size (16 KB for default settings) Interface: int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); In: dest - output data destLen - output data size src - input data srcLen - input data size propData - LZMA properties (5 bytes) propSize - size of propData buffer (5 bytes) finishMode - It has meaning only if the decoding reaches output limit (*destLen). LZMA_FINISH_ANY - Decode just destLen bytes. LZMA_FINISH_END - Stream must be finished after (*destLen). You can use LZMA_FINISH_END, when you know that current output buffer covers last bytes of stream. alloc - Memory allocator. Out: destLen - processed output size srcLen - processed input size Output: SZ_OK status: LZMA_STATUS_FINISHED_WITH_MARK LZMA_STATUS_NOT_FINISHED LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK SZ_ERROR_DATA - Data error SZ_ERROR_MEM - Memory allocation error SZ_ERROR_UNSUPPORTED - Unsupported properties SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). If LZMA decoder sees end_marker before reaching output limit, it returns OK result, and output value of destLen will be less than output buffer size limit. You can use multiple checks to test data integrity after full decompression: 1) Check Result and "status" variable. 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. You must use correct finish mode in that case. */ Multi-call State Decompressing (zlib-like interface) ---------------------------------------------------- When to use: file->file decompressing Compile files: LzmaDec.h + LzmaDec.c + Types.h Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures: state_size (16 KB for default settings) - LZMA dictionary (dictionary size is encoded in LZMA properties header) 1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: unsigned char header[LZMA_PROPS_SIZE + 8]; ReadFile(inFile, header, sizeof(header) 2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties CLzmaDec state; LzmaDec_Constr(&state); res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); if (res != SZ_OK) return res; 3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop LzmaDec_Init(&state); for (;;) { ... int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); ... } 4) Free all allocated structures LzmaDec_Free(&state, &g_Alloc); For full code example, look at C/LzmaUtil/LzmaUtil.c code. How To compress data -------------------- Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h Memory Requirements: - (dictSize * 11.5 + 6 MB) + state_size Lzma Encoder can use two memory allocators: 1) alloc - for small arrays. 2) allocBig - for big arrays. For example, you can use Large RAM Pages (2 MB) in allocBig allocator for better compression speed. Note that Windows has bad implementation for Large RAM Pages. It's OK to use same allocator for alloc and allocBig. Single-call Compression with callbacks -------------------------------------- Check C/LzmaUtil/LzmaUtil.c as example, When to use: file->file decompressing 1) you must implement callback structures for interfaces: ISeqInStream ISeqOutStream ICompressProgress ISzAlloc static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; CFileSeqInStream inStream; CFileSeqOutStream outStream; inStream.funcTable.Read = MyRead; inStream.file = inFile; outStream.funcTable.Write = MyWrite; outStream.file = outFile; 2) Create CLzmaEncHandle object; CLzmaEncHandle enc; enc = LzmaEnc_Create(&g_Alloc); if (enc == 0) return SZ_ERROR_MEM; 3) initialize CLzmaEncProps properties; LzmaEncProps_Init(&props); Then you can change some properties in that structure. 4) Send LZMA properties to LZMA Encoder res = LzmaEnc_SetProps(enc, &props); 5) Write encoded properties to header Byte header[LZMA_PROPS_SIZE + 8]; size_t headerSize = LZMA_PROPS_SIZE; UInt64 fileSize; int i; res = LzmaEnc_WriteProperties(enc, header, &headerSize); fileSize = MyGetFileLength(inFile); for (i = 0; i < 8; i++) header[headerSize++] = (Byte)(fileSize >> (8 * i)); MyWriteFileAndCheck(outFile, header, headerSize) 6) Call encoding function: res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, NULL, &g_Alloc, &g_Alloc); 7) Destroy LZMA Encoder Object LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); If callback function return some error code, LzmaEnc_Encode also returns that code. Single-call RAM->RAM Compression -------------------------------- Single-call RAM->RAM Compression is similar to Compression with callbacks, but you provide pointers to buffers instead of pointers to stream callbacks: HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); Return code: SZ_OK - OK SZ_ERROR_MEM - Memory allocation error SZ_ERROR_PARAM - Incorrect paramater SZ_ERROR_OUTPUT_EOF - output buffer overflow SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) LZMA Defines ------------ _LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. _LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for some structures will be doubled in that case. _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. C++ LZMA code is just wrapper over ANSI-C code. C++ Notes ~~~~~~~~~~~~~~~~~~~~~~~~ If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), you must check that you correctly work with "new" operator. 7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: operator new(size_t size) { void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } If you use MSCV that throws exception for "new" operator, you can compile without "NewHandler.cpp". So standard exception will be used. Actually some code of 7-Zip catches any exception in internal code and converts it to HRESULT code. So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. --- http://www.7-zip.org http://www.7-zip.org/sdk.html http://www.7-zip.org/support.html ================================================ FILE: src/others/squashfs-4.2/pseudo-file.example ================================================ # Pseudo file example # Mksquashfs supports pseudo files, these allow fake files, directories, # character and block devices to be specified and added to the Squashfs # filesystem being built, rather than requiring them to be present in the # source directories. # # This, for example, allows device nodes to be added to the filesystem without # requiring root access. # Mksquashfs 4.1 adds support for "dynamic pseudo files" and a modify operation. # Dynamic pseudo files allow files to be dynamically created when Mksquashfs # is run, their contents being the result of running a command or piece of # shell script. The modifiy operation allows the mode/uid/gid of an existing # file in the source filesystem to be modified. # Two Mksquashfs options are supported, -p allows one pseudo file to be # specified #on the command line, and -pf allows a pseudo file to be specified # containing a list of pseduo definitions, one per line. # Pseudo file examples # Run mkquashfs . /tmp/img -pf pseudo-file.examples # to see their effect # Creating dynamic file examples # Create a file "dmesg" containing the output from dmesg. dmesg f 444 root root dmesg # Create a file RELEASE containing the release name, date, build host, and # an incrementing version number. The incrementing version is a side-effect # of executing the shell script, and ensures every time Mksquashfs is run a # new version number is used without requiring any other shell scripting. RELEASE f 444 root root \ if [ ! -e /tmp/ver ]; then \ echo 0 > /tmp/ver; \ fi; \ ver=`cat /tmp/ver`; \ ver=$((ver +1)); \ echo $ver > /tmp/ver; \ echo -n "release x.x"; \ echo "-dev #"$ver `date` "Build host" `hostname` # Copy 10K from the device /dev/sda1 into the file input. Ordinarily # Mksquashfs given a device, fifo, or named socket will place that special file # within the Squashfs filesystem, this allows input from these special # files to be captured and placed in the Squashfs filesystem. input f 444 root root dd if=/dev/sda1 bs=1024 count=10 # Creating a block or character device examples # Create a character device "chr_dev" with major:minor 100:1 and # a block device "blk_dev" with major:minor 200:200, both with root # uid/gid and a mode of rw-rw-rw. chr_dev c 666 root root 100 1 blk_dev b 666 0 0 200 200 # Creating a directory example # create a directory "pseudo_dir" with root uid/gid and mode of r--r--r--. pseudo_dir d 444 root root # Modifying attributes of an existing file exmaple # Change the attributes of the file "INSTALL" in the filesystem to have # root uid/gid and a mode of rw-rw-rw, overriding the attributes obtained # from the source filesystem. INSTALL m 666 root root ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/Makefile ================================================ ############################################### # Compression build options # ############################################### # # ############# Building gzip support ########### # # Gzip support is by default enabled, and the compression type default # (COMP_DEFAULT) is gzip. # # If you don't want/need gzip support then comment out the GZIP SUPPORT line # below, and change COMP_DEFAULT to one of the compression types you have # selected. # # Obviously, you must select at least one of the available gzip, lzma, lzo # compression types. # GZIP_SUPPORT = 1 ########### Building XZ support ############# # # LZMA2 compression. # # XZ Utils liblzma (http://tukaani.org/xz/) is supported # # To build using XZ Utils liblzma - install the library and uncomment # the XZ_SUPPORT line below. # XZ_SUPPORT = 1 ############ Building LZO support ############## # # The LZO library (http://www.oberhumer.com/opensource/lzo/) is supported. # # To build using the LZO library - install the library and uncomment the # LZO_SUPPORT line below. If needed, uncomment and set LZO_DIR to the # installation prefix. # #LZO_SUPPORT = 1 #LZO_DIR = /usr/local ########### Building LZMA support ############# # # LZMA1 compression. # # LZMA1 compression is deprecated, and the newer and better XZ (LZMA2) # compression should be used in preference. # # Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK # (http://www.7-zip.org/sdk.html) are supported # # To build using XZ Utils liblzma - install the library and uncomment # the LZMA_XZ_SUPPORT line below. # # To build using the LZMA SDK (4.65 used in development, other versions may # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source, # and uncomment the LZMA_SUPPORT line below. # LZMA_XZ_SUPPORT = 1 #LZMA_SUPPORT = 1 LZMA_DIR = ../lzma-4.65 ######## Specifying default compression ######## # # The next line specifies which compression algorithm is used by default # in Mksquashfs. Obviously the compression algorithm must have been # selected to be built # COMP_DEFAULT = gzip ############################################### # Extended attribute (XATTRs) build options # ############################################### # # Building XATTR support for Mksquashfs and Unsquashfs # # If your C library or build/target environment doesn't support XATTRs then # comment out the next line to build Mksquashfs and Unsquashfs without XATTR # support XATTR_SUPPORT = 1 # Select whether you wish xattrs to be stored by Mksquashfs and extracted # by Unsquashfs by default. If selected users can disable xattr support by # using the -no-xattrs option # # If unselected, Mksquashfs/Unsquashfs won't store and extract xattrs by # default. Users can enable xattrs by using the -xattrs option. XATTR_DEFAULT = 1 ############################################### # End of BUILD options section # ############################################### INCLUDEDIR = -I. INSTALL_DIR = /usr/local/bin MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ unsquash-4.o swap.o compressor.o CFLAGS ?= -O2 CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \ -D_LARGEFILE_SOURCE -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" \ -Wall LIBS = -lpthread -lm ifeq ($(GZIP_SUPPORT),1) CFLAGS += -DGZIP_SUPPORT MKSQUASHFS_OBJS += gzip_wrapper.o UNSQUASHFS_OBJS += gzip_wrapper.o LIBS += -lz COMPRESSORS += gzip endif ifeq ($(LZMA_SUPPORT),1) LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o INCLUDEDIR += -I$(LZMA_DIR)/C CFLAGS += -DLZMA_SUPPORT MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) COMPRESSORS += lzma endif ifeq ($(LZMA_XZ_SUPPORT),1) CFLAGS += -DLZMA_SUPPORT MKSQUASHFS_OBJS += lzma_xz_wrapper.o UNSQUASHFS_OBJS += lzma_xz_wrapper.o COMPRESSORS += lzma endif ifeq ($(XZ_SUPPORT),1) CFLAGS += -DXZ_SUPPORT MKSQUASHFS_OBJS += xz_wrapper.o UNSQUASHFS_OBJS += xz_wrapper.o COMPRESSORS += xz endif ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),) MKSQUASHFS_OBJS += lzma_xz_options.o UNSQUASHFS_OBJS += lzma_xz_options.o ifneq ($(LZMA_LIB),) MKSQUASHFS_OBJS += $(LZMA_LIB) UNSQUASHFS_OBJS += $(LZMA_LIB) else LIBS += -llzma endif endif ifeq ($(LZO_SUPPORT),1) CFLAGS += -DLZO_SUPPORT ifdef LZO_DIR INCLUDEDIR += -I$(LZO_DIR)/include LZO_LIBDIR = -L$(LZO_DIR)/lib endif MKSQUASHFS_OBJS += lzo_wrapper.o UNSQUASHFS_OBJS += lzo_wrapper.o LIBS += $(LZO_LIBDIR) -llzo2 COMPRESSORS += lzo endif ifeq ($(XATTR_SUPPORT),1) ifeq ($(XATTR_DEFAULT),1) CFLAGS += -DXATTR_SUPPORT -DXATTR_DEFAULT else CFLAGS += -DXATTR_SUPPORT endif MKSQUASHFS_OBJS += xattr.o read_xattrs.o UNSQUASHFS_OBJS += read_xattrs.o unsquashfs_xattr.o endif # # If LZMA_SUPPORT is specified then LZMA_DIR must be specified too # ifeq ($(LZMA_SUPPORT),1) ifndef LZMA_DIR $(error "LZMA_SUPPORT requires LZMA_DIR to be also defined") endif endif # # Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified # ifeq ($(LZMA_XZ_SUPPORT),1) ifeq ($(LZMA_SUPPORT),1) $(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified") endif endif # # At least one compressor must have been selected # ifndef COMPRESSORS $(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!") endif # # COMP_DEFAULT must be a selected compressor # ifeq (, $(findstring $(COMP_DEFAULT), $(COMPRESSORS))) $(error "COMP_DEFAULT isn't selected to be built!") endif .PHONY: all all: mksquashfs unsquashfs mksquashfs: $(MKSQUASHFS_OBJS) $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(MKSQUASHFS_OBJS) $(LIBS) -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h sort.h squashfs_swap.h \ xattr.h pseudo.h compressor.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h squashfs_swap.h compressor.h \ xattr.h sort.o: sort.c squashfs_fs.h sort.h mksquashfs.h swap.o: swap.c pseudo.o: pseudo.c pseudo.h compressor.o: compressor.c compressor.h squashfs_fs.h xattr.o: xattr.c xattr.h squashfs_fs.h squashfs_swap.h mksquashfs.h read_xattrs.o: read_xattrs.c xattr.h squashfs_fs.h squashfs_swap.h read_fs.h gzip_wrapper.o: gzip_wrapper.c compressor.h squashfs_fs.h lzma_wrapper.o: lzma_wrapper.c compressor.h squashfs_fs.h lzma_xz_wrapper.o: lzma_xz_wrapper.c compressor.h squashfs_fs.h lzo_wrapper.o: lzo_wrapper.c compressor.h squashfs_fs.h xz_wrapper.o: xz_wrapper.c compressor.h squashfs_fs.h unsquashfs: $(UNSQUASHFS_OBJS) $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(UNSQUASHFS_OBJS) $(LIBS) -o $@ unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ squashfs_compat.h xattr.h read_fs.h compressor.h unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h unsquash-2.o: unsquashfs.h unsquash-2.c squashfs_fs.h squashfs_compat.h unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ read_fs.h unsquashfs_xattr.o: unsquashfs_xattr.c unsquashfs.h squashfs_fs.h xattr.h .PHONY: clean clean: -rm -f *.o mksquashfs unsquashfs .PHONY: install install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs $(INSTALL_DIR) cp unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/compressor.c ================================================ /* * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.c */ #include <stdio.h> #include <string.h> #include "compressor.h" #include "squashfs_fs.h" #ifndef GZIP_SUPPORT static struct compressor gzip_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 }; #else extern struct compressor gzip_comp_ops; #endif #ifndef LZMA_SUPPORT static struct compressor lzma_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }; #else extern struct compressor lzma_comp_ops; #endif #ifndef LZO_SUPPORT static struct compressor lzo_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 }; #else extern struct compressor lzo_comp_ops; #endif #ifndef XZ_SUPPORT static struct compressor xz_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 }; #else extern struct compressor xz_comp_ops; #endif static struct compressor unknown_comp_ops = { NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, 0, "unknown", 0 }; struct compressor *compressor[] = { &gzip_comp_ops, &lzma_comp_ops, &lzo_comp_ops, &xz_comp_ops, &unknown_comp_ops }; struct compressor *lookup_compressor(char *name) { int i; for(i = 0; compressor[i]->id; i++) if(strcmp(compressor[i]->name, name) == 0) break; return compressor[i]; } struct compressor *lookup_compressor_id(int id) { int i; for(i = 0; compressor[i]->id; i++) if(id == compressor[i]->id) break; return compressor[i]; } void display_compressors(char *indent, char *def_comp) { int i; for(i = 0; compressor[i]->id; i++) if(compressor[i]->supported) fprintf(stderr, "%s\t%s%s\n", indent, compressor[i]->name, strcmp(compressor[i]->name, def_comp) == 0 ? " (default)" : ""); } void display_compressor_usage(char *def_comp) { int i; for(i = 0; compressor[i]->id; i++) if(compressor[i]->supported) { char *str = strcmp(compressor[i]->name, def_comp) == 0 ? " (default)" : ""; if(compressor[i]->usage) { fprintf(stderr, "\t%s%s\n", compressor[i]->name, str); compressor[i]->usage(); } else fprintf(stderr, "\t%s (no options)%s\n", compressor[i]->name, str); } } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/compressor.h ================================================ /* * * Copyright (c) 2009, 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.h */ struct compressor { int (*init)(void **, int, int); int (*compress)(void *, void *, void *, int, int, int *); int (*uncompress)(void *, void *, int, int, int *); int (*options)(char **, int); int (*options_post)(int); void *(*dump_options)(int, int *); int (*extract_options)(int, void *, int); void (*usage)(); int id; char *name; int supported; }; extern struct compressor *lookup_compressor(char *); extern struct compressor *lookup_compressor_id(int); extern void display_compressors(char *, char *); extern void display_compressor_usage(char *); static inline int compressor_init(struct compressor *comp, void **stream, int block_size, int datablock) { if(comp->init == NULL) return 0; return comp->init(stream, block_size, datablock); } static inline int compressor_compress(struct compressor *comp, void *strm, void *dest, void *src, int size, int block_size, int *error) { return comp->compress(strm, dest, src, size, block_size, error); } static inline int compressor_uncompress(struct compressor *comp, void *dest, void *src, int size, int block_size, int *error) { return comp->uncompress(dest, src, size, block_size, error); } static inline int compressor_options(struct compressor *comp, char *argv[], int argc) { if(comp->options == NULL) return -1; return comp->options(argv, argc); } static inline int compressor_options_post(struct compressor *comp, int block_size) { if(comp->options_post == NULL) return 0; return comp->options_post(block_size); } static inline void *compressor_dump_options(struct compressor *comp, int block_size, int *size) { if(comp->dump_options == NULL) return NULL; return comp->dump_options(block_size, size); } static inline int compressor_extract_options(struct compressor *comp, int block_size, void *buffer, int size) { if(comp->extract_options == NULL) return size ? -1 : 0; return comp->extract_options(block_size, buffer, size); } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/gzip_wrapper.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * gzip_wrapper.c */ #include <stdlib.h> #include <zlib.h> #include "squashfs_fs.h" #include "compressor.h" static int gzip_init(void **strm, int block_size, int flags) { int res; z_stream *stream; stream = *strm = malloc(sizeof(z_stream)); if(stream == NULL) goto failed; stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; res = deflateInit(stream, 9); if(res != Z_OK) goto failed2; return 0; failed2: free(stream); failed: return -1; } static int gzip_compress(void *strm, void *d, void *s, int size, int block_size, int *error) { int res; z_stream *stream = strm; res = deflateReset(stream); if(res != Z_OK) goto failed; stream->next_in = s; stream->avail_in = size; stream->next_out = d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res == Z_STREAM_END) /* * Success, return the compressed size. */ return (int) stream->total_out; if(res == Z_OK) /* * Output buffer overflow. Return out of buffer space */ return 0; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error) { int res; unsigned long bytes = block_size; res = uncompress(d, &bytes, s, size); *error = res; return res == Z_OK ? (int) bytes : -1; } struct compressor gzip_comp_ops = { .init = gzip_init, .compress = gzip_compress, .uncompress = gzip_uncompress, .options = NULL, .usage = NULL, .id = ZLIB_COMPRESSION, .name = "gzip", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/lzma_wrapper.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_wrapper.c * * Support for LZMA1 compression using LZMA SDK (4.65 used in * development, other versions may work) http://www.7-zip.org/sdk.html */ #include <LzmaLib.h> #include "squashfs_fs.h" #include "compressor.h" #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) { unsigned char *d = dest; size_t props_size = LZMA_PROPS_SIZE, outlen = block_size - LZMA_HEADER_SIZE; int res; res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest, &props_size, 5, block_size, 3, 0, 2, 32, 1); if(res == SZ_ERROR_OUTPUT_EOF) { /* * Output buffer overflow. Return out of buffer space error */ return 0; } if(res != SZ_OK) { /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } /* * Fill in the 8 byte little endian uncompressed size field in the * LZMA header. 8 bytes is excessively large for squashfs but * this is the standard LZMA header and which is expected by the kernel * code */ d[LZMA_PROPS_SIZE] = size & 255; d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; d[LZMA_PROPS_SIZE + 4] = 0; d[LZMA_PROPS_SIZE + 5] = 0; d[LZMA_PROPS_SIZE + 6] = 0; d[LZMA_PROPS_SIZE + 7] = 0; /* * Success, return the compressed size. Outlen returned by the LZMA * compressor does not include the LZMA header space */ return outlen + LZMA_HEADER_SIZE; } static int lzma_uncompress(void *dest, void *src, int size, int block_size, int *error) { unsigned char *s = src; size_t outlen, inlen = size - LZMA_HEADER_SIZE; int res; outlen = s[LZMA_PROPS_SIZE] | (s[LZMA_PROPS_SIZE + 1] << 8) | (s[LZMA_PROPS_SIZE + 2] << 16) | (s[LZMA_PROPS_SIZE + 3] << 24); res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src, LZMA_PROPS_SIZE); *error = res; return res == SZ_OK ? outlen : -1; } struct compressor lzma_comp_ops = { .init = NULL, .compress = lzma_compress, .uncompress = lzma_uncompress, .options = NULL, .usage = NULL, .id = LZMA_COMPRESSION, .name = "lzma", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/lzma_xz_options.c ================================================ /* * Copyright (c) 2011 * Jonas Gorski <jonas.gorski@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_options.c * * Common options for LZMA1 and 2 compressors. Based on xz_wrapper.c */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <lzma.h> #include "lzma_xz_options.h" static const char const *lzmaver_str[] = { "", "lzma", "xz" }; static struct lzma_xz_options options = { .flags = 0, .preset = 6, .extreme = 0, .lc = LZMA_OPT_LC_DEFAULT, .lp = LZMA_OPT_LP_DEFAULT, .pb = LZMA_OPT_PB_DEFAULT, .fb = LZMA_OPT_FB_DEFAULT, .dict_size = 0, }; static float lzma_dict_percent = 0; struct lzma_xz_options *lzma_xz_get_options(void) { return &options; } int lzma_xz_options(char *argv[], int argc, int lzmaver) { const char *comp_name = lzmaver_str[lzmaver]; if(strcmp(argv[0], "-Xpreset") == 0) { int preset; if(argc < 2) { fprintf(stderr, "%s: -Xpreset missing preset\n", comp_name); goto failed; } preset = atoi(argv[1]); if (preset < 0 || preset > 9) { fprintf(stderr, "%s: -Xpreset invalid value\n", comp_name); goto failed; } options.preset = preset; return 1; } else if(strcmp(argv[0], "-Xe") == 0) { options.extreme = 1; return 0; } else if(strcmp(argv[0], "-Xlc") == 0) { int lc; if(argc < 2) { fprintf(stderr, "%s: -Xlc missing lc\n", comp_name); goto failed; } lc = atoi(argv[1]); if (lc < LZMA_OPT_LC_MIN || lc > LZMA_OPT_LC_MAX) { fprintf(stderr, "%s: -Xlc invalid value\n", comp_name); goto failed; } options.lc = lc; return 1; } else if(strcmp(argv[0], "-Xlp") == 0) { int lp; if(argc < 2) { fprintf(stderr, "%s: -Xlp missing lp\n", comp_name); goto failed; } lp = atoi(argv[1]); if (lp < LZMA_OPT_LP_MIN || lp > LZMA_OPT_LP_MAX) { fprintf(stderr, "%s: -Xlp invalid value\n", comp_name); goto failed; } options.lp = lp; return 1; } else if(strcmp(argv[0], "-Xpb") == 0) { int pb; if(argc < 2) { fprintf(stderr, "%s: -Xpb missing pb\n", comp_name); goto failed; } pb = atoi(argv[1]); if (pb < LZMA_OPT_PB_MIN || pb > LZMA_OPT_PB_MAX) { fprintf(stderr, "%s: -Xbp invalid value\n", comp_name); goto failed; } options.pb = pb; return 1; } else if(strcmp(argv[0], "-Xfb") == 0) { int fb; if(argc < 2) { fprintf(stderr, "%s: -Xfb missing fb\n", comp_name); goto failed; } fb = atoi(argv[1]); if (fb < LZMA_OPT_FB_MIN || fb > LZMA_OPT_FB_MAX) { fprintf(stderr, "%s: -Xfb invalid value\n", comp_name); goto failed; } options.fb = fb; return 1; } else if(strcmp(argv[0], "-Xdict-size") == 0) { char *b; float size; if(argc < 2) { fprintf(stderr, "%s: -Xdict-size missing dict-size\n", comp_name); goto failed; } size = strtof(argv[1], &b); if(*b == '%') { if(size <= 0 || size > 100) { fprintf(stderr, "%s: -Xdict-size percentage " "should be 0 < dict-size <= 100\n", comp_name); goto failed; } lzma_dict_percent = size; options.dict_size = 0; } else { if((float) ((int) size) != size) { fprintf(stderr, "%s: -Xdict-size can't be " "fractional unless a percentage of the" " block size\n", comp_name); goto failed; } lzma_dict_percent = 0; options.dict_size = (int) size; if(*b == 'k' || *b == 'K') options.dict_size *= 1024; else if(*b == 'm' || *b == 'M') options.dict_size *= 1024 * 1024; else if(*b != '\0') { fprintf(stderr, "%s: -Xdict-size invalid " "dict-size\n", comp_name); goto failed; } } return 1; } return -1; failed: return -2; } int lzma_xz_options_post(int block_size, int lzmaver) { const char *comp_name = lzmaver_str[lzmaver]; /* * if -Xdict-size has been specified use this to compute the datablock * dictionary size */ if(options.dict_size || lzma_dict_percent) { int dict_size_min = (lzmaver == 1 ? 4096 : 8192); int n; if(options.dict_size) { if(options.dict_size > block_size) { fprintf(stderr, "%s: -Xdict-size is larger than" " block_size\n", comp_name); goto failed; } } else options.dict_size = block_size * lzma_dict_percent / 100; if(options.dict_size < dict_size_min) { fprintf(stderr, "%s: -Xdict-size should be %i bytes " "or larger\n", comp_name, dict_size_min); goto failed; } /* * dictionary_size must be storable in xz header as either * 2^n or as 2^n+2^(n+1) */ n = ffs(options.dict_size) - 1; if(options.dict_size != (1 << n) && options.dict_size != ((1 << n) + (1 << (n + 1)))) { fprintf(stderr, "%s: -Xdict-size is an unsupported " "value, dict-size must be storable in %s " "header\n", comp_name, comp_name); fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). " "Example dict-sizes are 75%%, 50%%, 37.5%%, " "25%%,\n"); fprintf(stderr, "or 32K, 16K, 8K etc.\n"); goto failed; } } else /* No -Xdict-size specified, use defaults */ options.dict_size = block_size; return 0; failed: return -1; } static struct lzma_opts lzma_comp_opts; void *lzma_xz_dump_options(int block_size, int *size, int flags) { /* No need to store default options */ if (options.preset == 6 && options.extreme == 0 && options.lc == LZMA_OPT_LC_DEFAULT && options.lp == LZMA_OPT_LC_DEFAULT && options.pb == LZMA_OPT_PB_DEFAULT && options.fb == 0 && options.dict_size == block_size && flags == 0) return NULL; *size = sizeof(struct lzma_opts); lzma_comp_opts.flags |= flags; if (options.extreme) lzma_comp_opts.flags |= LZMA_OPT_EXTREME; lzma_comp_opts.flags |= ((options.preset << LZMA_OPT_PRE_OFF) & LZMA_OPT_PRE_MASK); lzma_comp_opts.bit_opts = ((options.lc << LZMA_OPT_LC_OFF) & LZMA_OPT_LC_MASK) | ((options.lp << LZMA_OPT_LP_OFF) & LZMA_OPT_LP_MASK) | ((options.pb << LZMA_OPT_PB_OFF) & LZMA_OPT_PB_MASK); lzma_comp_opts.fb = options.fb; lzma_comp_opts.dict_size = options.dict_size; SQUASHFS_INSWAP_LZMA_COMP_OPTS(&lzma_comp_opts); return &lzma_comp_opts; } int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver) { if (size == 0) { /* default options */ options.preset = 6; options.extreme = 0; options.lc = LZMA_OPT_LC_DEFAULT; options.lp = LZMA_OPT_LC_DEFAULT; options.pb = LZMA_OPT_PB_DEFAULT; options.fb = LZMA_OPT_FB_DEFAULT; options.dict_size = block_size; options.flags = 0; } else { struct lzma_opts *comp_opts = buffer; int n; if (size != sizeof(struct lzma_opts)) goto failed; SQUASHFS_INSWAP_LZMA_COMP_OPTS(comp_opts); options.flags = comp_opts->flags & LZMA_OPT_FLT_MASK; options.preset = (comp_opts->flags & LZMA_OPT_PRE_MASK) >> LZMA_OPT_PRE_OFF; options.extreme = !!(comp_opts->flags & LZMA_OPT_EXTREME); options.lc = (comp_opts->bit_opts & LZMA_OPT_LC_MASK) >> LZMA_OPT_LC_OFF; options.lp = (comp_opts->bit_opts & LZMA_OPT_LP_MASK) >> LZMA_OPT_LP_OFF; options.pb = (comp_opts->bit_opts & LZMA_OPT_PB_MASK) >> LZMA_OPT_PB_OFF; options.fb = comp_opts->fb; options.dict_size = comp_opts->dict_size; /* check that the LZMA bit options are in range */ if (options.lc < LZMA_OPT_LC_MIN || options.lc > LZMA_OPT_LC_MAX || options.lp < LZMA_OPT_LP_MIN || options.lp > LZMA_OPT_LP_MAX || options.pb < LZMA_OPT_PB_MIN || options.pb > LZMA_OPT_PB_MAX || options.fb < LZMA_OPT_FB_MIN || options.fb > LZMA_OPT_FB_MAX) goto failed; /* * check that the dictionary size seems correct - the dictionary * size should 2^n or 2^n+2^(n+1) */ n = ffs(options.dict_size) - 1; if(options.dict_size != (1 << n) && options.dict_size != ((1 << n) + (1 << (n + 1)))) goto failed; } return 0; failed: fprintf(stderr, "%s: error reading stored compressor options from " "filesystem!\n", lzmaver_str[lzmaver]); return -1; } void lzma_xz_usage(int lzmaver) { fprintf(stderr, "\t -Xpreset <preset>\n"); fprintf(stderr, "\t\tcompression preset (0-9, default 6)\n"); fprintf(stderr, "\t -Xe\n"); fprintf(stderr, "\t\tTry to improve compression ratio by using more "); fprintf(stderr, "CPU time.\n"); fprintf(stderr, "\t -Xlc <lc>\n"); fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n"); fprintf(stderr, "\t -Xlp <lp>\n"); fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n"); fprintf(stderr, "\t -Xpb <pb>\n"); fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n"); fprintf(stderr, "\t -Xnice <nice>\n"); fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n"); fprintf(stderr, "\t -Xdict-size <dict-size>\n"); fprintf(stderr, "\t\tUse <dict-size> as the %s dictionary size. The", lzmaver == LZMA_OPT_LZMA ? "LZMA" : "XZ"); fprintf(stderr, " dictionary size\n\t\tcan be specified as a"); fprintf(stderr, " percentage of the block size, or as an\n\t\t"); fprintf(stderr, "absolute value. The dictionary size must be less"); fprintf(stderr, " than or equal\n\t\tto the block size and %d bytes", lzmaver == LZMA_OPT_LZMA ? 4096 : 8192); fprintf(stderr, " or larger. It must also be\n\t\tstorable in the lzma"); fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t"); fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or"); fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n"); } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/lzma_xz_options.h ================================================ #ifndef LZMA_XZ_OPTIONS_H #define LZMA_XZ_OPTIONS_H /* * Copyright (c) 2011 * Jonas Gorski <jonas.gorski@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_options.h */ #include <stdint.h> #ifndef linux #ifdef __FreeBSD__ #include <machine/endian.h> #endif #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif struct lzma_opts { uint32_t flags; #define LZMA_OPT_FLT_MASK 0xffff #define LZMA_OPT_PRE_OFF 16 #define LZMA_OPT_PRE_MASK (0xf << LZMA_OPT_PRE_OFF) #define LZMA_OPT_EXTREME 20 uint16_t bit_opts; #define LZMA_OPT_LC_OFF 0 #define LZMA_OPT_LC_MASK (0x7 << LZMA_OPT_LC_OFF) #define LZMA_OPT_LP_OFF 3 #define LZMA_OPT_LP_MASK (0x7 << LZMA_OPT_LP_OFF) #define LZMA_OPT_PB_OFF 6 #define LZMA_OPT_PB_MASK (0x7 << LZMA_OPT_PB_OFF) uint16_t fb; uint32_t dict_size; }; #if __BYTE_ORDER == __BIG_ENDIAN extern unsigned int inswap_le32(unsigned int); #define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) { \ (s)->flags = inswap_le32((s)->flags); \ (s)->bit_opts = inswap_le16((s)->bit_opts); \ (s)->fb = inswap_le16((s)->fb); \ (s)->dict_size = inswap_le32((s)->dict_size); \ } #else #define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) #endif #define MEMLIMIT (32 * 1024 * 1024) #define LZMA_OPT_LC_MIN 0 #define LZMA_OPT_LC_MAX 4 #define LZMA_OPT_LC_DEFAULT 3 #define LZMA_OPT_LP_MIN 0 #define LZMA_OPT_LP_MAX 4 #define LZMA_OPT_LP_DEFAULT 0 #define LZMA_OPT_PB_MIN 0 #define LZMA_OPT_PB_MAX 4 #define LZMA_OPT_PB_DEFAULT 2 #define LZMA_OPT_FB_MIN 5 #define LZMA_OPT_FB_MAX 273 #define LZMA_OPT_FB_DEFAULT 64 enum { LZMA_OPT_LZMA = 1, LZMA_OPT_XZ }; struct lzma_xz_options { int preset; int extreme; int lc; int lp; int pb; int fb; int dict_size; int flags; }; struct lzma_xz_options *lzma_xz_get_options(void); int lzma_xz_options(char *argv[], int argc, int lzmaver); int lzma_xz_options_post(int block_size, int lzmaver); void *lzma_xz_dump_options(int block_size, int *size, int flags); int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver); void lzma_xz_usage(int lzmaver); #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/lzma_xz_wrapper.c ================================================ /* * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_xz_wrapper.c * * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/ */ #include <stdio.h> #include <string.h> #include <lzma.h> #include "squashfs_fs.h" #include "compressor.h" #include "lzma_xz_options.h" #define LZMA_PROPS_SIZE 5 #define LZMA_UNCOMP_SIZE 8 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE) #define LZMA_OPTIONS 5 #define MEMLIMIT (32 * 1024 * 1024) static int lzma_compress(void *dummy, void *dest, void *src, int size, int block_size, int *error) { uint32_t preset; unsigned char *d = (unsigned char *) dest; struct lzma_xz_options *opts = lzma_xz_get_options(); lzma_options_lzma opt; lzma_stream strm = LZMA_STREAM_INIT; int res; preset = opts->preset; if (opts->extreme) preset |= LZMA_PRESET_EXTREME; lzma_lzma_preset(&opt, opts->preset); opt.lc = opts->lc; opt.lp = opts->lp; opt.pb = opts->pb; if (opts->fb) opt.nice_len = opts->fb; opt.dict_size = opts->dict_size; res = lzma_alone_encoder(&strm, &opt); if(res != LZMA_OK) { lzma_end(&strm); goto failed; } strm.next_out = dest; strm.avail_out = block_size; strm.next_in = src; strm.avail_in = size; res = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if(res == LZMA_STREAM_END) { /* * Fill in the 8 byte little endian uncompressed size field in * the LZMA header. 8 bytes is excessively large for squashfs * but this is the standard LZMA header and which is expected by * the kernel code */ d[LZMA_PROPS_SIZE] = size & 255; d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; d[LZMA_PROPS_SIZE + 4] = 0; d[LZMA_PROPS_SIZE + 5] = 0; d[LZMA_PROPS_SIZE + 6] = 0; d[LZMA_PROPS_SIZE + 7] = 0; return (int) strm.total_out; } if(res == LZMA_OK) /* * Output buffer overflow. Return out of buffer space */ return 0; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int lzma_uncompress(void *dest, void *src, int size, int block_size, int *error) { lzma_stream strm = LZMA_STREAM_INIT; int uncompressed_size = 0, res; unsigned char lzma_header[LZMA_HEADER_SIZE]; res = lzma_alone_decoder(&strm, MEMLIMIT); if(res != LZMA_OK) { lzma_end(&strm); goto failed; } memcpy(lzma_header, src, LZMA_HEADER_SIZE); uncompressed_size = lzma_header[LZMA_PROPS_SIZE] | (lzma_header[LZMA_PROPS_SIZE + 1] << 8) | (lzma_header[LZMA_PROPS_SIZE + 2] << 16) | (lzma_header[LZMA_PROPS_SIZE + 3] << 24); memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE); strm.next_out = dest; strm.avail_out = block_size; strm.next_in = lzma_header; strm.avail_in = LZMA_HEADER_SIZE; res = lzma_code(&strm, LZMA_RUN); if(res != LZMA_OK || strm.avail_in != 0) { lzma_end(&strm); goto failed; } strm.next_in = src + LZMA_HEADER_SIZE; strm.avail_in = size - LZMA_HEADER_SIZE; res = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if(res == LZMA_STREAM_END || (res == LZMA_OK && strm.total_out >= uncompressed_size && strm.avail_in == 0)) return uncompressed_size; failed: *error = res; return -1; } static int lzma_options(char *argv[], int argc) { return lzma_xz_options(argv, argc, LZMA_OPT_LZMA); } static int lzma_options_post(int block_size) { return lzma_xz_options_post(block_size, LZMA_OPT_LZMA); } static void *lzma_dump_options(int block_size, int *size) { return lzma_xz_dump_options(block_size, size, 0); } static int lzma_extract_options(int block_size, void *buffer, int size) { return lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_LZMA); } void lzma_usage() { lzma_xz_usage(LZMA_OPT_LZMA); } struct compressor lzma_comp_ops = { .init = NULL, .compress = lzma_compress, .uncompress = lzma_uncompress, .options = lzma_options, .options_post = lzma_options_post, .dump_options = lzma_dump_options, .extract_options = lzma_extract_options, .usage = lzma_usage, .id = LZMA_COMPRESSION, .name = "lzma", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/lzo_wrapper.c ================================================ /* * Copyright (c) 2010 LG Electronics * Chan Jeong <chan.jeong@lge.com> * * All modifications Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzo_wrapper.c */ #include <stdlib.h> #include <string.h> #include <lzo/lzoconf.h> #include <lzo/lzo1x.h> #include "squashfs_fs.h" #include "compressor.h" /* worst-case expansion calculation during compression, see LZO FAQ for more information */ #define LZO_OUTPUT_BUFFER_SIZE(size) (size + (size/16) + 64 + 3) struct lzo_stream { lzo_voidp wrkmem; lzo_bytep out; }; static int squashfs_lzo_init(void **strm, int block_size, int flags) { struct lzo_stream *stream; if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL) goto failed; /* work memory for compression */ if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL) goto failed2; /* temporal output buffer */ if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL) goto failed3; return 0; failed3: free(stream->wrkmem); failed2: free(stream); failed: return -1; } static int lzo_compress(void *strm, void *d, void *s, int size, int block_size, int *error) { int res; lzo_uint outlen; struct lzo_stream *stream = strm; res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem); if(res != LZO_E_OK) goto failed; if(outlen >= size) /* * Output buffer overflow. Return out of buffer space */ return 0; /* * Success, return the compressed size. */ memcpy(d, stream->out, outlen); return outlen; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error) { int res; lzo_uint bytes = block_size; res = lzo1x_decompress_safe(s, size, d, &bytes, NULL); *error = res; return res == LZO_E_OK ? bytes : -1; } struct compressor lzo_comp_ops = { .init = squashfs_lzo_init, .compress = lzo_compress, .uncompress = lzo_uncompress, .options = NULL, .usage = NULL, .id = LZO_COMPRESSION, .name = "lzo", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <stddef.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #include <sys/wait.h> #ifndef linux #ifndef __CYGWIN__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #endif /* __CYGWIN__ */ #else #include <endian.h> #include <sys/sysinfo.h> #endif #ifdef __CYGWIN__ #include <sys/termios.h> #define FNM_EXTMATCH (1 << 5) #endif #ifndef FNM_EXTMATCH #define FNM_EXTMATCH 0 #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) \ do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) \ do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() \ do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) \ do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "sort.h" #include "pseudo.h" #include "compressor.h" #include "xattr.h" int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int comp_opts = FALSE; int no_xattrs = XATTR_DEF, noX = 0; int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0; int silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; int first_freelist = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned int id_count = 0; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { struct squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) struct squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char *name; struct inode_info inode; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* flag if we're restoring existing filesystem */ int restoring = 0; /* restore orignal filesystem state if appending to existing filesystem is * cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* in memory uid tables */ #define ID_ENTRIES 256 #define ID_HASH(id) (id & (ID_ENTRIES - 1)) #define ISA_UID 1 #define ISA_GID 2 struct id { unsigned int id; int index; char flags; struct id *next; }; struct id *id_hash_table[ID_ENTRIES]; struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS]; unsigned int uid_count = 0, guid_count = 0; unsigned int sid_count = 0, suid_count = 0, sguid_count = 0; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; struct pseudo *pseudo = NULL; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; /* compression operations */ static struct compressor *comp; int compressor_opts_parsed = 0; void *stream = NULL; /* xattr stats */ unsigned int xattr_bytes = 0, total_xattr_bytes = 0; char *read_from_disk(long long start, unsigned int avail_bytes); void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern struct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source); extern long long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), struct squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo); void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern int generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); long long generic_write_table(int, void *, int, void *, int); void restorefs(); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) goto failed; queue->data = malloc(sizeof(void *) * (size + 1)); if(queue->data == NULL) { free(queue); goto failed; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; failed: BAD_ERROR("Out of memory in queue_init\n"); } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) BAD_ERROR("Out of memory in cache_init\n"); cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ if(first_freelist && cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else if(!first_freelist && cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); BAD_ERROR("Out of memory in cache_get\n"); } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found * getting a new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \ + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; if(restoring++) /* * Recursive failure when trying to restore filesystem! * Nothing to do except to exit, otherwise we'll just appear * to hang. The user should be able to restore from the * recovery file (which is why it was added, in case of * catastrophic failure in Mksquashfs) */ exit(1); ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes); directory_cache_bytes = sdirectory_cache_bytes; inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; id_count = sid_count; restore_xattrs(); longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { #ifndef __CYGWIN__ struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; #else columns = 80; #endif } void sigalrm_handler() { rotate = (rotate + 1) % 4; } int mangle2(void *strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { int error, c_byte = 0; if(!uncompressed) { c_byte = compressor_compress(comp, strm, d, s, size, block_size, &error); if(c_byte == -1) BAD_ERROR("mangle2:: %s compress failed with error " "code %d\n", comp->name, error); } if(c_byte == 0 || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return c_byte; } int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { return mangle2(stream, d, s, size, block_size, uncompressed, data_block); } void *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { void *it = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(it == NULL) { goto failed; } inode_table = it; inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; void *dc = realloc(data_cache, cache_size + realloc_size); if(dc == NULL) { goto failed; } cache_size += realloc_size; data_cache = dc; } cache_bytes += req_size; return data_cache + cache_bytes - req_size; failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } int read_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) goto bytes_read; else if(errno != EINTR) { ERROR("Read failed because %s\n", strerror(errno)); return -1; } else res = 0; } } bytes_read: return count; } int read_fs_bytes(int fd, long long byte, int bytes, void *buff) { off_t off = byte; TRACE("read_fs_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); goto failed; } if(read_bytes(fd, buff, bytes) < bytes) { ERROR("Read on destination failed\n"); goto failed; } pthread_mutex_unlock(&pos_mutex); return 1; failed: pthread_mutex_unlock(&pos_mutex); return 0; } int write_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write failed because %s\n", strerror(errno)); return -1; } res = 0; } } return 0; } void write_destination(int fd, long long byte, int bytes, void *buff) { off_t off = byte; if(!restoring) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write_bytes(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed\n"); if(!restoring) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *it = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(it == NULL) { BAD_ERROR("Out of memory in inode table " "reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; inode_table = it; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += avail_bytes + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } write_destination(fd, bytes, inode_bytes, inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *dt = realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(dt == NULL) { BAD_ERROR("Out of memory in directory table " "reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; directory_table = dt; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += avail_bytes + BLOCK_OFFSET; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_destination(fd, bytes, directory_bytes, directory_table); bytes += directory_bytes; return start_bytes; } long long write_id_table() { unsigned int id_bytes = SQUASHFS_ID_BYTES(id_count); unsigned int p[id_count]; int i; TRACE("write_id_table: ids %d, id_bytes %d\n", id_count, id_bytes); for(i = 0; i < id_count; i++) { TRACE("write_id_table: id index %d, id %d", i, id_table[i]->id); SQUASHFS_SWAP_INTS(&id_table[i]->id, p + i, 1); } return generic_write_table(id_bytes, p, 0, NULL, noI); } struct id *get_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = id_hash_table[hash]; for(; entry; entry = entry->next) if(entry->id == id) break; return entry; } struct id *create_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = malloc(sizeof(struct id)); if(entry == NULL) BAD_ERROR("Out of memory in create_id\n"); entry->id = id; entry->index = id_count ++; entry->flags = 0; entry->next = id_hash_table[hash]; id_hash_table[hash] = entry; id_table[entry->index] = entry; return entry; } unsigned int get_uid(unsigned int uid) { struct id *entry = get_id(uid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of uids!\n"); entry = create_id(uid); } if((entry->flags & ISA_UID) == 0) { entry->flags |= ISA_UID; uid_count ++; } return entry->index; } unsigned int get_guid(unsigned int guid) { struct id *entry = get_id(guid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of gids!\n"); entry = create_id(guid); } if((entry->flags & ISA_GID) == 0) { entry->flags |= ISA_GID; guid_count ++; } return entry->index; } int create_inode(squashfs_inode *i_no, struct dir_info *dir_info, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in, long long sparse) { struct stat *buf = &dir_ent->inode->buf; union squashfs_inode_header inode_header; struct squashfs_base_inode_header *base = &inode_header.base; void *inode; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = type == SQUASHFS_DIR_TYPE ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; int xattr = read_xattrs(dir_ent); switch(type) { case SQUASHFS_FILE_TYPE: if(dir_ent->inode->nlink > 1 || byte_size >= (1LL << 32) || start_block >= (1LL << 32) || sparse || IS_XATTR(xattr)) type = SQUASHFS_LREG_TYPE; break; case SQUASHFS_DIR_TYPE: if(dir_info->dir_is_ldir || IS_XATTR(xattr)) type = SQUASHFS_LDIR_TYPE; break; case SQUASHFS_SYMLINK_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LSYMLINK_TYPE; break; case SQUASHFS_BLKDEV_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LBLKDEV_TYPE; break; case SQUASHFS_CHRDEV_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LCHRDEV_TYPE; break; case SQUASHFS_FIFO_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LFIFO_TYPE; break; case SQUASHFS_SOCKET_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LSOCKET_TYPE; break; } base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((unsigned int) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((unsigned int) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; struct squashfs_reg_inode_header *reg = &inode_header.reg; size_t off = offsetof(struct squashfs_reg_inode_header, block_list); inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; SQUASHFS_SWAP_REG_INODE_HEADER(reg, inode); SQUASHFS_SWAP_INTS(block_list, inode + off, offset); TRACE("File inode, file_size %lld, start_block 0x%llx, blocks " "%d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; struct squashfs_lreg_inode_header *reg = &inode_header.lreg; size_t off = offsetof(struct squashfs_lreg_inode_header, block_list); inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(sparse && sparse >= byte_size) sparse = byte_size - 1; reg->sparse = sparse; reg->xattr = xattr; SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inode); SQUASHFS_SWAP_INTS(block_list, inode + off, offset); TRACE("Long file inode, file_size %lld, start_block 0x%llx, " "blocks %d, fragment %d, offset %d, size %d, nlink %d" "\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; struct squashfs_ldir_inode_header *dir = &inode_header.ldir; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; dir->xattr = xattr; SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = inode + offsetof(struct squashfs_ldir_inode_header, index); for(i = 0; i < i_count; i++) { SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); p += offsetof(struct squashfs_dir_index, name); memcpy(p, index[i].name, index[i].index.size + 1); p += index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block " "0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { struct squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, " "offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { struct squashfs_dev_inode_header *dev = &inode_header.dev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_LCHRDEV_TYPE || type == SQUASHFS_LBLKDEV_TYPE) { struct squashfs_ldev_inode_header *dev = &inode_header.ldev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); dev->xattr = xattr; SQUASHFS_SWAP_LDEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { struct squashfs_symlink_inode_header *symlink = &inode_header.symlink; int byte; char buff[65536]; size_t off = offsetof(struct squashfs_symlink_inode_header, symlink); byte = readlink(filename, buff, 65536); if(byte == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inode + off, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_LSYMLINK_TYPE) { struct squashfs_symlink_inode_header *symlink = &inode_header.symlink; int byte; char buff[65536]; size_t off = offsetof(struct squashfs_symlink_inode_header, symlink); byte = readlink(filename, buff, 65536); if(byte == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte + sizeof(unsigned int)); symlink->nlink = nlink; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inode + off, buff, byte); SQUASHFS_SWAP_INTS(&xattr, inode + off + byte, 1); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { struct squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else if(type == SQUASHFS_LFIFO_TYPE || type == SQUASHFS_LSOCKET_TYPE) { struct squashfs_lipc_inode_header *ipc = &inode_header.lipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; ipc->xattr = xattr; SQUASHFS_SWAP_LIPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan3_init_dir(struct directory *dir) { dir->buff = malloc(SQUASHFS_METADATA_SIZE); if(dir->buff == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; struct squashfs_dir_entry idir; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size = strlen(name); size_t name_off = offsetof(struct squashfs_dir_entry, name); if(size > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ..." "\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(struct squashfs_dir_entry) + size + sizeof(struct squashfs_dir_header) >= dir->buff + dir->size) { buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE); if(buff == NULL) { BAD_ERROR("Out of memory reallocating directory buffer" "\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(struct squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < -32768) { if(dir->entry_count_p) { struct squashfs_dir_header dir_header; if((dir->p + sizeof(struct squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) { dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index)); if(dir->index == NULL) BAD_ERROR("Out of memory in " "directory index table " "reallocation!\n"); } dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(struct squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(struct squashfs_dir_header); } idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); SQUASHFS_SWAP_DIR_ENTRY(&idir, dir->p); strncpy((char *) dir->p + name_off, name, size); dir->p += sizeof(struct squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = directory_cache_size - directory_cache_bytes; unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; void *dc = realloc(directory_data_cache, directory_cache_size + realloc_size); if(dc == NULL) { goto failed; } directory_cache_size += realloc_size; directory_data_cache = dc; } if(dir_size) { struct squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *dt = realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(dt == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; directory_table = dt; } c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memmove(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } create_inode(inode, dir_info, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0); #ifdef SQUASHFS_TRACE { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; struct squashfs_dir_entry idir, *idirp; struct squashfs_dir_header dirh; SQUASHFS_SWAP_DIR_HEADER((struct squashfs_dir_header *) dirp, &dirh); count = dirh.count + 1; dirp += sizeof(struct squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh.start_block, count); while(count--) { idirp = (struct squashfs_dir_entry *) dirp; SQUASHFS_SWAP_DIR_ENTRY(idirp, &idir); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type " "%d\n", buffer, idir.offset, idir.type); dirp += sizeof(struct squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { struct squashfs_fragment_entry *disk_fragment; int res, size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int error; char *data; if(compressed_buffer) data = compressed_buffer->data; else data = read_from_disk(start_block, size); res = compressor_uncompress(comp, buffer->data, data, size, block_size, &error); if(res == -1) BAD_ERROR("%s uncompress failed with error code %d\n", comp->name, error); } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else { res = read_fs_bytes(fd, start_block, size, buffer->data); if(res == 0) EXIT_MKSQUASHFS(); } cache_block_put(compressed_buffer); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, entry->buffer); TRACE("fragment_locked writing fragment %d, compressed size %d" "\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } void add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) BAD_ERROR("Out of memory in add_pending fragment\n"); entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { void *ft = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(struct squashfs_fragment_entry)); if(ft == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } fragment_table = ft; } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); ffrg = malloc(sizeof(struct fragment)); if(ffrg == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, void *buffer, int length2, void *buffer2, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; #ifdef SQUASHFS_TRACE long long obytes = bytes; int olength = length; #endif for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); SQUASHFS_SWAP_SHORTS(&c_byte, cbuffer, 1); list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_destination(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; total_bytes += avail_bytes; length -= avail_bytes; } start_bytes = bytes; if(length2) { write_destination(fd, bytes, length2, buffer2); bytes += length2; total_bytes += length2; } SQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks); write_destination(fd, bytes, sizeof(list), list); bytes += sizeof(list); total_bytes += sizeof(list); TRACE("generic_write_table: total uncompressed %d compressed %lld\n", olength, bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); struct squashfs_fragment_entry p[fragments]; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, " "size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p + i); } return generic_write_table(frag_bytes, p, 0, NULL, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { int res; res = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer); if(res == 0) EXIT_MKSQUASHFS(); return read_from_file_buffer; } char read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk2(long long start, unsigned int avail_bytes) { int res; res = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer2); if(res == 0) EXIT_MKSQUASHFS(); return read_from_file_buffer2; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } frg = malloc(sizeof(struct fragment)); if(frg == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = malloc(sizeof(struct file_info)); if(dupl_ptr == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long target_start, dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; target_start = *start; for(block = 0; block < blocks; block ++) { int size = SQUASHFS_COMPRESSED_SIZE_BLOCK ((*block_list)[block]); struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(size == 0) continue; target_buffer = cache_lookup(writer_buffer, target_start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(target_start, size); dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else dup_data = read_from_disk2(dup_start, size); res = memcmp(target_data, dup_data, size); cache_block_put(target_buffer); cache_block_put(dup_buffer); if(res != 0) break; target_start += size; dup_start += size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start " "0x%llx, size %lld, checksum " "0x%x, fragment %d, size %d, " "offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } static int seq = 0; void reader_read_process(struct dir_ent *dir_ent) { struct file_buffer *prev_buffer = NULL, *file_buffer; int status, res, byte, count = 0; int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; long long bytes = 0; while(1) { file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; byte = read_bytes(file, file_buffer->data, block_size); if(byte == -1) goto read_err; file_buffer->size = byte; file_buffer->file_size = -1; file_buffer->block = count ++; file_buffer->error = FALSE; file_buffer->fragment = FALSE; bytes += byte; if(byte == 0) break; /* * Update estimated_uncompressed block count. This is done * on every block rather than waiting for all blocks to be * read incase write_file_process() is running in parallel * with this. Otherwise cur uncompressed block count may * get ahead of the total uncompressed block count. */ estimated_uncompressed ++; if(prev_buffer) queue_put(from_reader, prev_buffer); prev_buffer = file_buffer; } /* * Update inode file size now that the size of the dynamic pseudo file * is known. This is needed for the -info option. */ dir_ent->inode->buf.st_size = bytes; res = waitpid(child, &status, 0); if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) goto read_err; if(prev_buffer == NULL) prev_buffer = file_buffer; else { cache_block_put(file_buffer); seq --; } prev_buffer->file_size = bytes; prev_buffer->fragment = !no_fragments && (count == 2 || always_use_fragments) && (byte < block_size); queue_put(from_reader, prev_buffer); return; read_err: if(prev_buffer) { cache_block_put(file_buffer); seq --; file_buffer = prev_buffer; } file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; file = open(dir_ent->pathname, O_RDONLY); if(file == -1) { file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; goto read_err; } do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; /* * Always try to read block_size bytes from the file rather * than expected bytes (which will be less than the block_size * at the file tail) to check that the file hasn't grown * since being stated. If it is longer (or shorter) than * expected, then restat, and try again. Note the special * case where the file is an exact multiple of the block_size * is dealt with later. */ byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte == -1) goto read_err; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; file_buffer->fragment = (file_buffer->block == frag_block); bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { /* * Special case where we've not tried to read past the end of * the file. We expect to get EOF, i.e. the file isn't larger * than we expect. */ char buffer; int res; res = read_bytes(file, &buffer, 1); if(res == -1) goto read_err; if(res != 0) goto restat; } queue_put(from_reader, file_buffer); close(file); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } read_err: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; if(IS_PSEUDO_PROCESS(dir_ent->inode)) { reader_read_process(dir_ent); continue; } switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write_bytes(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { void *stream = NULL; int res, oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); res = compressor_init(comp, &stream, block_size, 1); if(res) BAD_ERROR("deflator:: compressor_init failed\n"); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer; if(sparse_files && all_zero(file_buffer)) { file_buffer->c_byte = 0; queue_put(from_deflate, file_buffer); } else if(file_buffer->fragment) { file_buffer->c_byte = file_buffer->size; queue_put(from_deflate, file_buffer); } else { write_buffer = cache_get(writer_buffer, 0, 0); write_buffer->c_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK (write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } } void *frag_deflator(void *arg) { void *stream = NULL; int res, oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); res = compressor_init(comp, &stream, block_size, 1); if(res) BAD_ERROR("frag_deflator:: compressor_init failed\n"); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, write_buffer); pthread_mutex_unlock(&fragment_mutex); TRACE("Writing fragment %lld, uncompressed size %d, " "compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits, used, hashes, spaces; static int tty = -1; if(max == 0) return; max_digits = floor(log10(max)) + 1; used = max_digits * 2 + 11; hashes = (current * (columns - used)) / max; spaces = columns - used - hashes; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); return; } int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *duplicate_file) { long long read_size, file_bytes, start; struct fragment *fragment; unsigned int *block_list = NULL; int block = 0, status; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; lock_fragments(); file_bytes = 0; start = bytes; while (1) { read_size = read_buffer->file_size; if(read_buffer->fragment && read_buffer->c_byte) fragment_buffer = read_buffer; else { block_list = realloc(block_list, (block + 1) * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list" "\n"); block_list[block ++] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(read_size != -1) break; read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, block, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { long long file_bytes, start; struct fragment *fragment; unsigned int *block_list; int block, status; int blocks = (read_size + block_size - 1) >> block_log; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { int block, thresh; long long file_bytes, dup_start, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer **buffer_list; int status, num_locked_fragments; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; buffer_list = malloc(blocks * sizeof(struct file_buffer *)); if(buffer_list == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = dup_start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); if(block < thresh) { buffer_list[block] = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block] = read_buffer; } else { buffer_list[block] = NULL; sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block]) queue_put(to_writer, buffer_list[block]); fragment = get_and_fill_fragment(fragment_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block]); bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because" " %s\n", strerror(errno)); } } unlock_fragments(); cache_block_put(fragment_buffer); free(buffer_list); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks]); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == -1) status = write_file_process(inode, dir_ent, read_buffer, duplicate_file); else if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(read_buffer->fragment && read_buffer->c_byte) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, " "attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } #define BUFF_SIZE 8192 char b_buffer[BUFF_SIZE]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getcwd(b_buffer, BUFF_SIZE); if(result == NULL) return NULL; strcat(strcat(b_buffer, "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } inode = malloc(sizeof(struct inode_info)); if(inode == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation" "\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->root_entry = FALSE; inode->pseudo_file = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) { dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *)); if(dir->list == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); } dir->list[dir->count] = malloc(sizeof(struct dir_ent)); if(dir->list[dir->count] == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count++]->our_dir = dir; dir->byte_count += strlen(name) + sizeof(struct squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; dir = malloc(sizeof(struct dir_info)); if(dir == NULL) BAD_ERROR("Out of memory in scan1_opendir\n"); if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { static int index = 0; if(dir->count < old_root_entries) { int i; for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } } while(index < source) { char *basename = getbase(source_path[index]); int n, pass = 1; if(basename == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i; if(dir->count < old_root_entries) { for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } } if((d_name = readdir(dir->linuxdir)) != NULL) { int pass = 1; strcpy(dir_name, d_name->d_name); for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name = readdir(dir->linuxdir); if(d_name != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) continue; else return dir_info->list[current_count]; return NULL; } struct dir_ent *scan2_lookup(struct dir_info *dir, char *name) { int i; for(i = 0; i < dir->count; i++) if(strcmp(dir->list[i]->name, name) == 0) return dir->list[i]; return NULL; } struct dir_ent *scan3_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) add_dir(dir_info->list[current_count]->inode->inode, dir_info->list[current_count]->inode->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->inode->type, dir); else return dir_info->list[current_count]; return NULL; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); free(dir->pathname); dir->pathname = NULL; } void scan2_freedir(struct dir_info *dir) { dir->current_count = 0; if(dir->pathname) { free(dir->pathname); dir->pathname = NULL; } } void scan3_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; dir_scan2(dir_info, pseudo); dir_ent = malloc(sizeof(struct dir_ent)); if(dir_ent == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* * dummy top level directory, if multiple sources specified on * command line */ memset(&buf, 0, sizeof(buf)); buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; dir_ent->inode = lookup_inode(&buf); dir_ent->inode->pseudo_file = PSEUDO_FILE_OTHER; } else { if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); } if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_info->dir_ent = dir_ent; if(sorted) { int res = generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); if(res == FALSE) BAD_ERROR("generate_file_priorities failed\n"); } queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan3(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { char filename[8192], dir_name[8192]; struct dir_info *dir = scan1_opendir(pathname); if(dir == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { struct dir_info *sub_dir; struct stat buf; struct pathnames *new; if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring" "\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { sub_dir = dir_scan1(filename, new, scan1_readdir); if(sub_dir == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), dir); } scan1_freedir(dir); error: return dir; } struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo) { struct dir_info *sub_dir; struct dir_ent *dir_ent; struct pseudo_entry *pseudo_ent; struct stat buf; static int pseudo_ino = 1; if(dir == NULL && (dir = scan1_opendir("")) == NULL) return NULL; while((dir_ent = scan2_readdir(dir)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *name = dir_ent->name; if((buf->st_mode & S_IFMT) == S_IFDIR) dir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo)); } while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { dir_ent = scan2_lookup(dir, pseudo_ent->name); if(pseudo_ent->dev->type == 'm') { struct stat *buf; if(dir_ent == NULL) { ERROR("Pseudo modify file \"%s\" does not exist " "in source filesystem. Ignoring.\n", pseudo_ent->pathname); continue; } if(dir_ent->inode->root_entry) { ERROR("Pseudo modify file \"%s\" is a pre-existing" " file in the filesystem being appended" " to. It cannot be modified. " "Ignoring.\n", pseudo_ent->pathname); continue; } buf = &dir_ent->inode->buf; buf->st_mode = (buf->st_mode & S_IFMT) | pseudo_ent->dev->mode; buf->st_uid = pseudo_ent->dev->uid; buf->st_gid = pseudo_ent->dev->gid; continue; } if(dir_ent) { if(dir_ent->inode->root_entry) ERROR("Pseudo file \"%s\" is a pre-existing" " file in the filesystem being appended" " to. Ignoring.\n", pseudo_ent->pathname); else ERROR("Pseudo file \"%s\" exists in source " "filesystem \"%s\".\nIgnoring, " "exclude it (-e/-ef) to override.\n", pseudo_ent->pathname, dir_ent->pathname); continue; } if(pseudo_ent->dev->type == 'd') { sub_dir = dir_scan2(NULL, pseudo_ent->pseudo); if(sub_dir == NULL) { ERROR("Could not create pseudo directory \"%s\"" ", skipping...\n", pseudo_ent->pathname); continue; } dir->directory_count ++; } else sub_dir = NULL; memset(&buf, 0, sizeof(buf)); buf.st_mode = pseudo_ent->dev->mode; buf.st_uid = pseudo_ent->dev->uid; buf.st_gid = pseudo_ent->dev->gid; buf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor); buf.st_mtime = time(NULL); buf.st_ino = pseudo_ino ++; if(pseudo_ent->dev->type == 'f') { #ifdef USE_TMP_FILE struct stat buf2; int res = stat(pseudo_ent->dev->filename, &buf2); struct inode_info *inode; if(res == -1) { ERROR("Stat on pseudo file \"%s\" failed, " "skipping...", pseudo_ent->pathname); continue; } buf.st_size = buf2.st_size; inode = lookup_inode(&buf); inode->pseudo_file = PSEUDO_FILE_OTHER; add_dir_entry(pseudo_ent->name, pseudo_ent->dev->filename, sub_dir, inode, dir); #else struct inode_info *inode = lookup_inode(&buf); inode->pseudo_id = pseudo_ent->dev->pseudo_id; inode->pseudo_file = PSEUDO_FILE_PROCESS; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, inode, dir); #endif } else { struct inode_info *inode = lookup_inode(&buf); inode->pseudo_file = PSEUDO_FILE_OTHER; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, inode, dir); } } scan2_freedir(dir); sort_directory(dir); return dir; } void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->dir_ent->pathname; struct directory dir; struct dir_ent *dir_ent; scan3_init_dir(&dir); while((dir_ent = scan3_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld " "bytes %s\n", filename, (long long) buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan3(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("character device %s inode 0x%llx" "\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("fifo %s inode 0x%llx\n",dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("unix domain socket %s inode " "0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, " "mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed " "size %lld bytes LINK" "\n", filename, (long long) buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode " "0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan3_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) { \ exclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \ * sizeof(struct exclude_info)); \ if(exclude_paths == NULL) \ BAD_ERROR("Out of memory in exclude dir/file table\n"); \ } \ exclude_paths[exclude].st_dev = buf.st_dev; \ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, " "ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because " "%s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { old_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1)); if(old_root_entry == NULL) BAD_ERROR("Out of memory in old root directory entries " "reallocation\n"); old_root_entry[old_root_entries].name = strdup(name); old_root_entry[old_root_entries].inode.inode = inode; old_root_entry[old_root_entries].inode.inode_number = inode_number; old_root_entry[old_root_entries].inode.type = type; old_root_entry[old_root_entries++].inode.root_entry = TRUE; } void initialise_threads(int readb_mbytes, int writeb_mbytes, int fragmentb_mbytes) { int i; sigset_t sigmask, old_mask; int reader_buffer_size = readb_mbytes << (20 - block_log); int fragment_buffer_size = fragmentb_mbytes << (20 - block_log); /* * writer_buffer_size is global because it is needed in * write_file_blocks_dup() */ writer_buffer_size = writeb_mbytes << (20 - block_log); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); #ifdef __CYGWIN__ processors = atoi(getenv("NUMBER_OF_PROCESSORS")); #else if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = sysconf(_SC_NPROCESSORS_ONLN); #endif } #endif /* __CYGWIN__ */ thread = malloc((2 + processors * 2) * sizeof(pthread_t)); if(thread == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); void *it; if(inode_count == sinode_count) goto skip_inode_hash_table; it = realloc(inode_lookup_table, lookup_bytes); if(it == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); inode_lookup_table = it; for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; SQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, inode_lookup_table, 0, NULL, noI); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { paths = malloc(sizeof(struct pathname)); if(paths == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); if(paths->name == NULL) BAD_ERROR("Out of memory in add path\n"); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(paths->name[i].preg == NULL) BAD_ERROR("Out of memory in add_path\n"); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing exclude which subsumes * the exclude currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist * from more specific excludes, delete as they're * subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with " "-wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); if(new == NULL) BAD_ERROR("Out of memory in init_subdir\n"); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) { paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); if(paths == NULL) BAD_ERROR("Out of memory in add_subdir\n"); } paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories * in the filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(struct squashfs_super_block *sBlk) { int res, recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } metadata = malloc(bytes); if(metadata == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "write_recovery_data\n"); res = read_fs_bytes(fd, sBlk->inode_table_start, bytes, metadata); if(res == 0) EXIT_MKSQUASHFS(); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(recoverfd == -1) BAD_ERROR("Failed to create recovery file, because %s. " "Aborting\n", strerror(errno)); if(write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, sBlk, sizeof(struct squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; struct squashfs_super_block orig_sBlk, sBlk; char *metadata; int res; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; recoverfd = open(recovery_file, O_RDONLY); if(recoverfd == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); fd = open(destination_file, O_RDWR); if(fd == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < RECOVER_ID_SIZE) BAD_ERROR("Recovery file appears to be truncated\n"); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); res = read_bytes(recoverfd, &sBlk, sizeof(struct squashfs_super_block)); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < sizeof(struct squashfs_super_block)) BAD_ERROR("Recovery file appears to be truncated\n"); res = read_fs_bytes(fd, 0, sizeof(struct squashfs_super_block), &orig_sBlk); if(res == 0) EXIT_MKSQUASHFS(); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(struct squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to " "match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; metadata = malloc(bytes); if(metadata == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "read_recovery_data\n"); res = read_bytes(recoverfd, metadata, bytes); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_destination(fd, 0, sizeof(struct squashfs_super_block), &sBlk); write_destination(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 4.2 (2011/02/28)\n");\ printf("copyright (C) 2011 Phillip Lougher "\ "<phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or"\ "\n");\ printf("modify it under the terms of the GNU General Public License"\ "\n");\ printf("as published by the Free Software Foundation; either version "\ "2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be "\ "useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty "\ "of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int res, i; struct squashfs_super_block sBlk; char *b, *root_name = NULL; int nopad = FALSE, keep_as_directory = FALSE; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; /* * lookup default compressor. Note the Makefile ensures the default * compressor has been built, and so we don't need to to check * for failure here */ comp = lookup_compressor(COMP_DEFAULT); for(; i < argc; i++) { if(strcmp(argv[i], "-comp") == 0) { if(compressor_opts_parsed) { ERROR("%s: -comp must appear before -X options" "\n", argv[0]); exit(1); } if(++i == argc) { ERROR("%s: -comp missing compression type\n", argv[0]); exit(1); } comp = lookup_compressor(argv[i]); if(!comp->supported) { ERROR("%s: Compressor \"%s\" is not supported!" "\n", argv[0], argv[i]); ERROR("%s: Compressors available:\n", argv[0]); display_compressors("", COMP_DEFAULT); exit(1); } } else if(strncmp(argv[i], "-X", 2) == 0) { int args = compressor_options(comp, argv + i, argc - i); if(args < 0) { if(args == -1) { ERROR("%s: Unrecognised compressor" " option %s\n", argv[0], argv[i]); ERROR("%s: Did you forget to specify" " -comp, or specify it after" " the compressor specific" " option?\n", argv[0]); } exit(1); } i += args; compressor_opts_parsed = 1; } else if(strcmp(argv[i], "-pf") == 0) { if(++i == argc) { ERROR("%s: -pf missing filename\n", argv[0]); exit(1); } if(read_pseudo_file(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-p") == 0) { if(++i == argc) { ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } if(read_pseudo_def(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte " "or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 " "megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or " "not between 4096 and 1Mbyte\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range" "\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or " "unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range" "\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or " "unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-noX") == 0 || strcmp(argv[i], "-noXattrCompression") == 0) noX = TRUE; else if(strcmp(argv[i], "-no-xattrs") == 0) no_xattrs = TRUE; else if(strcmp(argv[i], "-xattrs") == 0) no_xattrs = FALSE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] " "[-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nFilesystem build options:\n"); ERROR("-comp <comp>\t\tselect <comp> compression\n"); ERROR("\t\t\tCompressors available:\n"); display_compressors("\t\t\t", COMP_DEFAULT); ERROR("-b <block_size>\t\tset data block to " "<block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-no-exports\t\tdon't make the filesystem " "exportable via NFS\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-no-xattrs\t\tdon't store extended attributes" NOXOPT_STR "\n"); ERROR("-xattrs\t\t\tstore extended attributes" XOPT_STR "\n"); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-noX\t\t\tdo not compress extended " "attributes\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for " "files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate " "checking\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " "of 4K\n"); ERROR("-keep-as-directory\tif one source directory is " "specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, " "rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("\nFilesystem filter options:\n"); ERROR("-p <pseudo-definition>\tAdd pseudo file " "definition\n"); ERROR("-pf <pseudo-file>\tAdd list of pseudo file " "definitions\n"); ERROR("-sort <sort_file>\tsort files according to " "priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. " "Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files." " One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards " "(globbing) to be used in\n\t\t\texclude " "dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to " "be used in exclude\n\t\t\tdirs/files\n"); ERROR("\nFilesystem append options:\n"); ERROR("-noappend\t\tdo not append to existing " "filesystem\n"); ERROR("-root-becomes <name>\twhen appending source " "files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in " "the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new " "source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("\nMksquashfs runtime options:\n"); ERROR("-version\t\tprint version, licence and " "copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data " "using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery " "file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-progress\t\tdon't display the progress " "bar\n"); ERROR("-processors <number>\tUse <number> processors." " By default will use number of\n"); ERROR("\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> " "Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> " "Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fragment queue to " "<size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\nMiscellaneous options:\n"); ERROR("-root-owned\t\talternative name for -all-root" "\n"); ERROR("-noInodeCompression\talternative name for -noI" "\n"); ERROR("-noDataCompression\talternative name for -noD" "\n"); ERROR("-noFragmentCompression\talternative name for " "-noF\n"); ERROR("-noXattrCompression\talternative name for " "-noX\n"); ERROR("\nCompressors available and compressor specific " "options:\n"); display_compressor_usage(COMP_DEFAULT); exit(1); } } /* * Some compressors may need the options to be checked for validity * once all the options have been processed */ res = compressor_options_post(comp, block_size); if(res) EXIT_MKSQUASHFS(); for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" " "because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(fd == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as " "destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR); if(fd == -1) { perror("Could not open regular file for " "writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* * process the exclude files - must be done afer destination file has * been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { int res = read_sort_file(argv[++i], source, source_path); if(res == FALSE) BAD_ERROR("Failed to read sort file\n"); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { comp = read_super(fd, &sBlk, argv[source + 1]); if(comp == NULL) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); noX = SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags); comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags); } initialise_threads(readb_mbytes, writeb_mbytes, fragmentb_mbytes); res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0); if(res) BAD_ERROR("compressor_init failed\n"); if(delete) { int size; void *comp_data = compressor_dump_options(comp, block_size, &size); printf("Creating %d.%d filesystem on %s, block size %d.\n", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); /* * store any compressor specific options after the superblock, * and set the COMP_OPT flag to show that the filesystem has * compressor specfic options */ if(comp_data) { unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT; SQUASHFS_INSWAP_SHORTS(&c_byte, 1); write_destination(fd, sizeof(struct squashfs_super_block), sizeof(c_byte), &c_byte); write_destination(fd, sizeof(struct squashfs_super_block) + sizeof(c_byte), size, comp_data); bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte) + size; comp_opts = TRUE; } else bytes = sizeof(struct squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) { fragment_table = realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(struct squashfs_fragment_entry)); if(fragment_table == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); } printf("Appending to existing %d.%d filesystem on %s, block " "size %d\n", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -b, -noI, -noD, -noF, -noX, no-duplicates, no-fragments, " "-always-use-fragments,\n-exportable and -comp options " "ignored\n"); printf("\nIf appending is not wanted, please re-run with " "-noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = malloc(scache_bytes); if(sdata_cache == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); sdirectory_data_cache = malloc(sdirectory_cache_bytes); if(sdirectory_data_cache == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; sid_count = id_count; write_recovery_data(&sBlk); if(save_xattrs() == FALSE) BAD_ERROR("Failed to save xattrs from existing " "filesystem\n"); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_destination(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* * set the filesystem state up to be able to append to the * original filesystem. The filesystem state differs depending * on whether we're appending to the original root directory, or * if the original root directory becomes a sub-directory * (root-becomes specified on command line, here root_name != * NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); if(sdirectory_compressed == NULL) BAD_ERROR("Out of memory in save filesystem " "state\n"); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; /* * The default use freelist before growing cache policy behaves * poorly with appending - with many deplicates the caches * do not grow due to the fact that large queues of outstanding * fragments/writer blocks do not occur, leading to small caches * and un-uncessary performance loss to frequent cache * replacement in the small caches. Therefore with appending * change the policy to grow the caches before reusing blocks * from the freelist */ first_freelist = FALSE; } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, no_fragments, always_use_fragments, duplicate_checking, exportable, no_xattrs, comp_opts); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(!restoring) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.no_ids = id_count; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; sBlk.id_table_start = write_id_table(); sBlk.xattr_id_table_start = write_xattrs(); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.bytes_used = bytes; sBlk.compression = comp->id; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk); write_destination(fd, SQUASHFS_START, sizeof(sBlk), &sBlk); if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_destination(fd, bytes, 4096 - i, temp); } close(fd); delete_pseudo_files(); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + sizeof(struct squashfs_super_block) + total_xattr_bytes; printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, comp->name, block_size); printf("\t%s data, %s metadata, %s fragments, %s xattrs\n", noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", no_xattrs ? "no" : noX ? "uncompressed" : "compressed"); printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(total_xattr_bytes) { printf("Xattr table size %d bytes (%.2f Kbytes)\n", xattr_bytes, xattr_bytes / 1024.0); printf("\t%.2f%% of uncompressed xattr table size (%d bytes)\n", ((float) xattr_bytes / total_xattr_bytes) * 100.0, total_xattr_bytes); } if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of ids (unique uids + gids) %d\n", id_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_UID) { struct passwd *user = getpwuid(id_table[i]->id); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, id_table[i]->id); } } printf("Number of gids %d\n", guid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_GID) { struct group *group = getgrgid(id_table[i]->id); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, id_table[i]->id); } } return 0; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/mksquashfs.h ================================================ #ifndef MKSQUASHFS_H #define MKSQUASHFS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(s, d, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(s, d, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) swap_le64_num(s, d, n) #define SWAP_LE16(s, d) swap_le16(s, d) #define SWAP_LE32(s, d) swap_le32(s, d) #define SWAP_LE64(s, d) swap_le64(s, d) #else #define SQUASHFS_MEMCPY(s, d, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(s, d, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(s, d, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \ memcpy(d, s, n * sizeof(long long)) #endif struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; }; struct inode_info { struct stat buf; struct inode_info *next; squashfs_inode inode; unsigned int inode_number; unsigned int nlink; int pseudo_id; char type; char read; char root_entry; char pseudo_file; }; #endif #define PSEUDO_FILE_OTHER 1 #define PSEUDO_FILE_PROCESS 2 #define IS_PSEUDO(a) ((a)->pseudo_file) #define IS_PSEUDO_PROCESS(a) ((a)->pseudo_file & PSEUDO_FILE_PROCESS) #define IS_PSEUDO_OTHER(a) ((a)->pseudo_file & PSEUDO_FILE_OTHER) /* offset of data in compressed metadata blocks (allowing room for * compressed size */ #define BLOCK_OFFSET 2 ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/pseudo.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.c */ #include <pwd.h> #include <grp.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include "pseudo.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() \ do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) \ do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); #define TRUE 1 #define FALSE 0 struct pseudo_dev **pseudo_file = NULL; int pseudo_count = 0; static void dump_pseudo(struct pseudo *pseudo, char *string) { int i; char path[1024]; for(i = 0; i < pseudo->names; i++) { struct pseudo_entry *entry = &pseudo->name[i]; if(string) strcat(strcat(strcpy(path, string), "/"), entry->name); else strcpy(path, entry->name); if(entry->pseudo == NULL) ERROR("%s %c %o %d %d %d %d\n", path, entry->dev->type, entry->dev->mode, entry->dev->uid, entry->dev->gid, entry->dev->major, entry->dev->minor); else dump_pseudo(entry->pseudo, path); } } static char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } /* * Add pseudo device target to the set of pseudo devices. Pseudo_dev * describes the pseudo device attributes. */ struct pseudo *add_pseudo(struct pseudo *pseudo, struct pseudo_dev *pseudo_dev, char *target, char *alltarget) { char targname[1024]; int i; target = get_component(target, targname); if(pseudo == NULL) { if((pseudo = malloc(sizeof(struct pseudo))) == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->names = 0; pseudo->count = 0; pseudo->name = NULL; } for(i = 0; i < pseudo->names; i++) if(strcmp(pseudo->name[i].name, targname) == 0) break; if(i == pseudo->names) { /* allocate new name entry */ pseudo->names ++; pseudo->name = realloc(pseudo->name, (i + 1) * sizeof(struct pseudo_entry)); if(pseudo->name == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->name[i].name = strdup(targname); if(target[0] == '\0') { /* at leaf pathname component */ pseudo->name[i].pseudo = NULL; pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else { /* recurse adding child components */ pseudo->name[i].dev = NULL; pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); } } else { /* existing matching entry */ if(pseudo->name[i].pseudo == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing pseudo file. */ if(target[0] != '\0') { /* entry must exist as a 'd' type pseudo file */ if(pseudo->name[i].dev->type == 'd') /* recurse adding child components */ pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); else ERROR("%s already exists as a non " "directory. Ignoring %s!\n", targname, alltarget); } else if(memcmp(pseudo_dev, pseudo->name[i].dev, sizeof(struct pseudo_dev)) != 0) ERROR("%s already exists as a different pseudo " "definition. Ignoring!\n", alltarget); else ERROR("%s already exists as an identical " "pseudo definition!\n", alltarget); } else { /* sub-directory exists which means this can only be a * 'd' type pseudo file */ if(target[0] == '\0') { if(pseudo->name[i].dev == NULL && pseudo_dev->type == 'd') { pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else ERROR("%s already exists as a " "directory. Ignoring %s!\n", targname, alltarget); } else /* recurse adding child components */ add_pseudo(pseudo->name[i].pseudo, pseudo_dev, target, alltarget); } } return pseudo; } /* * Find subdirectory in pseudo directory referenced by pseudo, matching * filename. If filename doesn't exist or if filename is a leaf file * return NULL */ struct pseudo *pseudo_subdir(char *filename, struct pseudo *pseudo) { int i; if(pseudo == NULL) return NULL; for(i = 0; i < pseudo->names; i++) if(strcmp(filename, pseudo->name[i].name) == 0) return pseudo->name[i].pseudo; return NULL; } struct pseudo_entry *pseudo_readdir(struct pseudo *pseudo) { if(pseudo == NULL) return NULL; while(pseudo->count < pseudo->names) { if(pseudo->name[pseudo->count].dev != NULL) return &pseudo->name[pseudo->count++]; else pseudo->count++; } return NULL; } int exec_file(char *command, struct pseudo_dev *dev) { int child, res; static pid_t pid = -1; int pipefd[2]; #ifdef USE_TMP_FILE char filename[1024]; int status; static int number = 0; #endif if(pid == -1) pid = getpid(); #ifdef USE_TMP_FILE sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(pipefd[1] == -1) { printf("open failed\n"); return -1; } #else res = pipe(pipefd); if(res == -1) { printf("pipe failed\n"); return -1; } #endif child = fork(); if(child == -1) { printf("fork failed\n"); goto failed; } if(child == 0) { close(STDOUT_FILENO); res = dup(pipefd[1]); if(res == -1) { printf("dup failed\n"); exit(EXIT_FAILURE); } execl("/bin/sh", "sh", "-c", command, (char *) NULL); printf("execl failed\n"); exit(EXIT_FAILURE); } #ifdef USE_TMP_FILE res = waitpid(child, &status, 0); close(pipefd[1]); if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { dev->filename = strdup(filename); return 0; } failed: unlink(filename); return -1; #else close(pipefd[1]); dev->fd = pipefd[0]; dev->child = child; return 0; failed: return -1; #endif } void add_pseudo_file(struct pseudo_dev *dev) { pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * sizeof(struct pseudo_dev *)); if(pseudo_file == NULL) BAD_ERROR("Failed to realloc pseudo_file\n"); dev->pseudo_id = pseudo_count; pseudo_file[pseudo_count ++] = dev; } void delete_pseudo_files() { #ifdef USE_TMP_FILE int i; for(i = 0; i < pseudo_count; i++) unlink(pseudo_file[i]->filename); #endif } struct pseudo_dev *get_pseudo_file(int pseudo_id) { return pseudo_file[pseudo_id]; } int read_pseudo_def(struct pseudo **pseudo, char *def) { int n, bytes; unsigned int major = 0, minor = 0, mode; char filename[2048], type, suid[100], sgid[100], *ptr; long long uid, gid; struct pseudo_dev *dev; n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, sgid, &bytes); if(n < 5) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } switch(type) { case 'b': case 'c': n = sscanf(def + bytes, "%u %u", &major, &minor); if(n < 2) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } if(major > 0xfff) { ERROR("Major %d out of range\n", major); goto error; } if(minor > 0xfffff) { ERROR("Minor %d out of range\n", minor); goto error; } case 'f': if(def[bytes] == '\0') { ERROR("Not enough arguments in pseudo file " "definition\n"); goto error; } break; case 'd': case 'm': break; default: ERROR("Unsupported type %c\n", type); goto error; } if(mode > 07777) { ERROR("Mode %o out of range\n", mode); goto error; } uid = strtoll(suid, &ptr, 10); if(*ptr == '\0') { if(uid < 0 || uid > ((1LL << 32) - 1)) { ERROR("Uid %s out of range\n", suid); goto error; } } else { struct passwd *pwuid = getpwnam(suid); if(pwuid) uid = pwuid->pw_uid; else { ERROR("Uid %s invalid uid or unknown user\n", suid); goto error; } } gid = strtoll(sgid, &ptr, 10); if(*ptr == '\0') { if(gid < 0 || gid > ((1LL << 32) - 1)) { ERROR("Gid %s out of range\n", sgid); goto error; } } else { struct group *grgid = getgrnam(sgid); if(grgid) gid = grgid->gr_gid; else { ERROR("Gid %s invalid uid or unknown user\n", sgid); goto error; } } switch(type) { case 'b': mode |= S_IFBLK; break; case 'c': mode |= S_IFCHR; break; case 'd': mode |= S_IFDIR; break; case 'f': mode |= S_IFREG; break; } dev = malloc(sizeof(struct pseudo_dev)); if(dev == NULL) BAD_ERROR("Failed to create pseudo_dev\n"); dev->type = type; dev->mode = mode; dev->uid = uid; dev->gid = gid; dev->major = major; dev->minor = minor; if(type == 'f') { int res; printf("Executing dynamic pseudo file\n"); printf("\t\"%s\"\n", def); res = exec_file(def + bytes, dev); if(res == -1) { ERROR("Failed to execute dynamic pseudo file definition" " \"%s\"\n", def); return FALSE; } add_pseudo_file(dev); } *pseudo = add_pseudo(*pseudo, dev, filename, filename); return TRUE; error: ERROR("Bad pseudo file definition \"%s\"\n", def); return FALSE; } #define MAX_LINE 2048 int read_pseudo_file(struct pseudo **pseudo, char *filename) { FILE *fd; char *line = NULL; int size = 0; int res = TRUE; fd = fopen(filename, "r"); if(fd == NULL) { ERROR("Could not open pseudo device file \"%s\" because %s\n", filename, strerror(errno)); return FALSE; } while(1) { int total = 0; while(1) { int n, err; if(total + MAX_LINE > size) { line = realloc(line, size += MAX_LINE); if(line == NULL) { ERROR("No space in read_pseudo_file\n"); return FALSE; } } err = fscanf(fd, "%2047[^\n]%n\n", line + total, &n); if(err <= 0) goto done; if(line[total] == '#') continue; if(line[total + n - 1] != '\\') break; total += n - 1; } res = read_pseudo_def(pseudo, line); if(res == FALSE) break; } done: fclose(fd); free(line); return res; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/pseudo.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.h */ struct pseudo_dev { char type; unsigned int mode; unsigned int uid; unsigned int gid; unsigned int major; unsigned int minor; int pseudo_id; int fd; int child; #ifdef USE_TMP_FILE char *filename; #endif }; struct pseudo_entry { char *name; char *pathname; struct pseudo *pseudo; struct pseudo_dev *dev; }; struct pseudo { int names; int count; struct pseudo_entry *name; }; extern int read_pseudo_def(struct pseudo **, char *); extern int read_pseudo_file(struct pseudo **, char *); extern struct pseudo *pseudo_subdir(char *, struct pseudo *); extern struct pseudo_entry *pseudo_readdir(struct pseudo *); extern struct pseudo_dev *get_pseudo_file(int); extern void delete_pseudo_files(); ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #ifndef linux #ifndef __CYGWIN__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #else #include <endian.h> #endif #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "compressor.h" #include "xattr.h" extern int read_fs_bytes(int, long long, int, void *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); extern void *create_id(unsigned int); extern unsigned int get_uid(unsigned int); extern unsigned int get_guid(unsigned int); static struct compressor *comp; int read_block(int fd, long long start, long long *next, void *block) { unsigned short c_byte; int res; res = read_fs_bytes(fd, start, 2, &c_byte); if(res == 0) return 0; SQUASHFS_INSWAP_SHORTS(&c_byte, 1); if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); res = read_fs_bytes(fd, start + 2, c_byte, buffer); if(res == 0) return 0; res = compressor_uncompress(comp, block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); return 0; } if(next) *next = start + 2 + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); res = read_fs_bytes(fd, start + 2, c_byte, block); if(res == 0) return 0; if(next) *next = start + 2 + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, struct squashfs_super_block *sBlk, union squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, unsigned int *id_table) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; struct squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start " "0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx " "containing root inode\n", start); *root_inode_block = bytes; } if(size - bytes < SQUASHFS_METADATA_SIZE) { *inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE); if(*inode_table == NULL) return FALSE; } TRACE("scan_inode_table: reading block 0x%llx\n", start); byte = read_block(fd, start, &start, *inode_table + bytes); if(byte == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain * the last directory start block index. This is used when calculating * the total uncompressed directory size. The directory bytes in the * last * block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, *inode_table + bytes); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, *inode_table + bytes); directory_start_block = dir_inode->dir.start_block; } else { SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, *inode_table + bytes); directory_start_block = dir_inode->ldir.start_block; } get_uid(id_table[dir_inode->base.uid]); get_guid(id_table[dir_inode->base.guid]); for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { SQUASHFS_SWAP_REG_INODE_HEADER(&inode, cur_ptr); TRACE("scan_inode_table: processing inode @ byte position " "0x%x, type 0x%x\n", (unsigned int) (cur_ptr - *inode_table), inode.inode_type); get_uid(id_table[inode.uid]); get_guid(id_table[inode.guid]); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, " "file_size %d, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { struct squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, cur_ptr); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular " "file, file_size %lld, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { struct squashfs_symlink_inode_header inodep; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, cur_ptr); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; if (inode.inode_type == SQUASHFS_LSYMLINK_TYPE) cur_ptr += sizeof(unsigned int); break; } case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header dir_inode; SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(struct squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header dir_inode; int i; SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(struct squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { struct squashfs_dir_index index; SQUASHFS_SWAP_DIR_INDEX(&index, cur_ptr); cur_ptr += sizeof(struct squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(struct squashfs_dev_inode_header); break; case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(struct squashfs_ldev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(struct squashfs_ipc_inode_header); break; case SQUASHFS_LFIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(struct squashfs_lipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(struct squashfs_ipc_inode_header); break; case SQUASHFS_LSOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(struct squashfs_lipc_inode_header); break; default: ERROR("Unknown inode type %d in " "scan_inode_table!\n", inode.inode_type); goto failed; } } printf("Read existing filesystem, %d inodes scanned\n", files); return TRUE; failed: free(*inode_table); return FALSE; } struct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source) { int res, bytes = 0; char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned)); res = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), sBlk); if(res == 0) goto failed_mount; SQUASHFS_INSWAP_SUPER_BLOCK(sBlk); if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) ERROR("Pre 4.0 big-endian filesystem on %s, appending" " to this is unsupported\n", source); else ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 4) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem." " Appending\nto SQUASHFS %d.%d filesystems is " "not supported. Please convert it to a " "SQUASHFS 4 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later " "filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } /* Check the compression type */ comp = lookup_compressor_id(sBlk->compression); if(!comp->supported) { ERROR("Filesystem on %s uses %s compression, this is" "unsupported by this version\n", source, comp->name); ERROR("Compressors available:\n"); display_compressors("", ""); goto failed_mount; } /* * Read extended superblock information from disk. * * Read compressor specific options from disk if present, and pass * to compressor to set compressor options. * * Note, if there's no compressor options present, the compressor * is still called to set the default options (the defaults may have * been changed by the user specifying options on the command * line which need to be over-ridden). */ if(SQUASHFS_COMP_OPTS(sBlk->flags)) { bytes = read_block(fd, sizeof(*sBlk), NULL, buffer); if(bytes == 0) goto failed_mount; } res = compressor_extract_options(comp, sBlk->block_size, buffer, bytes); if(res == -1) { ERROR("Compressor failed to set compressor options\n"); goto failed_mount; } printf("Found a valid %sSQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); printf("\tCompression used %s\n", comp->name); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tXattrs are %scompressed\n", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? "un" : ""); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tXattrs are %sstored\n", SQUASHFS_NO_XATTRS(sBlk->flags) ? "not " : ""); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of ids %d\n", sBlk->no_ids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); TRACE("sBlk->xattr_id_table_start %llx\n", sBlk->xattr_id_table_start); printf("\n"); return comp; failed_mount: return NULL; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, struct squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { struct squashfs_dir_header dirh; char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1] __attribute__ ((aligned)); struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1)); if(directory_table == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so " "far %d\n", start, bytes); last_start_block = start; byte = read_block(fd, start, &start, directory_table + bytes); if(byte == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, directory_table + bytes); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position " "0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, directory_table + bytes); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, " "inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } unsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk) { int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids); long long index[indexes]; int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids); unsigned int *id_table; int res, i; id_table = malloc(bytes); if(id_table == NULL) { ERROR("Failed to allocate id table\n"); return NULL; } res = read_fs_bytes(fd, sBlk->id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index); if(res == 0) { free(id_table); return NULL; } SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) id_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read id table block %d, from 0x%llx, length %d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read id table block %d, from 0x%llx, " "length %d\n", i, index[i], length); free(id_table); return NULL; } } SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); for(i = 0; i < sBlk->no_ids; i++) { TRACE("Adding id %d to id tables\n", id_table[i]); create_id(id_table[i]); } return id_table; } int read_fragment_table(int fd, struct squashfs_super_block *sBlk, struct squashfs_fragment_entry **fragment_table) { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; *fragment_table = malloc(sBlk->fragments * sizeof(struct squashfs_fragment_entry)); if(*fragment_table == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } res = read_fs_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), fragment_table_index); if(res == 0) { free(*fragment_table); return 0; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == 0) { ERROR("Failed to read fragment table block %d, from " "0x%llx, length %d\n", i, fragment_table_index[i], length); free(*fragment_table); return 0; } } for(i = 0; i < sBlk->fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]); return 1; } int read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int res, i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; *inode_lookup_table = malloc(lookup_bytes); if(*inode_lookup_table == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } res = read_fs_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index); if(res == 0) { free(*inode_lookup_table); return 0; } SQUASHFS_INSWAP_LONG_LONGS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read inode lookup table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read inode lookup table block %d, " "from 0x%llx, length %d\n", i, index[i], length); free(*inode_lookup_table); return 0; } } SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); return 1; } long long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), struct squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start; long long end = sBlk->directory_table_start; long long root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode); unsigned int root_inode_block; union squashfs_inode_header inode; unsigned int *id_table; int res; printf("Scanning existing filesystem...\n"); if(get_xattrs(fd, sBlk) == 0) goto error; if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; id_table = read_id_table(fd, sBlk); if(id_table == NULL) goto error; res = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count, id_table); if(res == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry); if(directory_table == NULL) { ERROR("read_filesystem: Could not read root directory" "\n"); goto error; } root_inode_start -= start; *cinode_table = malloc(root_inode_start); if(*cinode_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem inode table\n"); goto error; } res = read_fs_bytes(fd, start, root_inode_start, *cinode_table); if(res == 0) goto error; *cdirectory_table = malloc(*last_directory_block); if(*cdirectory_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem directory table\n"); goto error; } res = read_fs_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if(res == 0) goto error; *data_cache = malloc(root_inode_offset + *root_inode_size); if(*data_cache == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); *directory_data_cache = malloc(*inode_dir_offset + *inode_dir_file_size); if(*directory_data_cache == NULL) { ERROR("read_filesystem: failed to alloc directory " "cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/read_fs.h ================================================ #ifndef READ_FS_H #define READ_FS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(d, s, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(d, s, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) swap_le64_num(s, d, n) #define SWAP_LE16(d, s) swap_le16(s, d) #define SWAP_LE32(d, s) swap_le32(s, d) #define SWAP_LE64(d, s) swap_le64(s, d) #else #define SQUASHFS_MEMCPY(d, s, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(d, s, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(d, s, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) \ memcpy(d, s, n * sizeof(long long)) #endif #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/read_xattrs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_xattrs.c */ /* * Common xattr read code shared between mksquashfs and unsquashfs */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <string.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "xattr.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("read_xattrs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) extern int read_fs_bytes(int, long long, int, void *); extern int read_block(int, long long, long long *, void *); static struct hash_entry { long long start; unsigned int offset; struct hash_entry *next; } *hash_table[65536]; static struct squashfs_xattr_id *xattr_ids; static void *xattrs = NULL; static long long xattr_table_start; /* * Prefix lookup table, storing mapping to/from prefix string and prefix id */ struct prefix prefix_table[] = { { "user.", SQUASHFS_XATTR_USER }, { "trusted.", SQUASHFS_XATTR_TRUSTED }, { "security.", SQUASHFS_XATTR_SECURITY }, { "", -1 } }; /* * store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ static int save_xattr_block(long long start, int offset) { struct hash_entry *hash_entry = malloc(sizeof(*hash_entry)); int hash = start & 0xffff; TRACE("save_xattr_block: start %lld, offset %d\n", start, offset); if(hash_entry == NULL) { ERROR("Failed to allocate hash entry\n"); return -1; } hash_entry->start = start; hash_entry->offset = offset; hash_entry->next = hash_table[hash]; hash_table[hash] = hash_entry; return 1; } /* * map from location of compressed block in fs -> * location of uncompressed block in memory */ static int get_xattr_block(long long start) { int hash = start & 0xffff; struct hash_entry *hash_entry = hash_table[hash]; for(; hash_entry; hash_entry = hash_entry->next) if(hash_entry->start == start) break; TRACE("get_xattr_block: start %lld, offset %d\n", start, hash_entry ? hash_entry->offset : -1); return hash_entry ? hash_entry->offset : -1; } /* * construct the xattr_list entry from the fs xattr, including * mapping name and prefix into a full name */ static int read_xattr_entry(struct xattr_list *xattr, struct squashfs_xattr_entry *entry, void *name) { int i, len, type = entry->type & XATTR_PREFIX_MASK; for(i = 0; prefix_table[i].type != -1; i++) if(prefix_table[i].type == type) break; if(prefix_table[i].type == -1) { ERROR("Unrecognised type in read_xattr_entry\n"); return 0; } len = strlen(prefix_table[i].prefix); xattr->full_name = malloc(len + entry->size + 1); if(xattr->full_name == NULL) { ERROR("Out of memory in read_xattr_entry\n"); return -1; } memcpy(xattr->full_name, prefix_table[i].prefix, len); memcpy(xattr->full_name + len, name, entry->size); xattr->full_name[len + entry->size] = '\0'; xattr->name = xattr->full_name + len; xattr->size = entry->size; xattr->type = type; return 1; } /* * Read and decompress the xattr id table and the xattr metadata. * This is cached in memory for later use by get_xattr() */ int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { int res, bytes, i, indexes, index_bytes, ids; long long *index, start, end; struct squashfs_xattr_table id_table; TRACE("read_xattrs_from_disk\n"); if(sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK) return SQUASHFS_INVALID_BLK; /* * Read xattr id table, containing start of xattr metadata and the * number of xattrs in the file system */ res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table); if(res == 0) return 0; SQUASHFS_INSWAP_XATTR_TABLE(&id_table); /* * Allocate and read the index to the xattr id table metadata * blocks */ ids = id_table.xattr_ids; xattr_table_start = id_table.xattr_table_start; index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids); indexes = SQUASHFS_XATTR_BLOCKS(ids); index = malloc(index_bytes); if(index == NULL) { ERROR("Failed to allocate index array\n"); return 0; } res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index); if(res ==0) goto failed1; SQUASHFS_INSWAP_LONG_LONGS(index, indexes); /* * Allocate enough space for the uncompressed xattr id table, and * read and decompress it */ bytes = SQUASHFS_XATTR_BYTES(ids); xattr_ids = malloc(bytes); if(xattr_ids == NULL) { ERROR("Failed to allocate xattr id table\n"); goto failed1; } for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) xattr_ids) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr id table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read xattr id table block %d, " "from 0x%llx, length %d\n", i, index[i], length); goto failed2; } } /* * Read and decompress the xattr metadata * * Note the first xattr id table metadata block is immediately after * the last xattr metadata block, so we can use index[0] to work out * the end of the xattr metadata */ start = xattr_table_start; end = index[0]; for(i = 0; start < end; i++) { int length; void *x = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE); if(x == NULL) { ERROR("Failed to realloc xattr data\n"); goto failed3; } xattrs = x; /* store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ res = save_xattr_block(start, i * SQUASHFS_METADATA_SIZE); if(res == -1) goto failed3; length = read_block(fd, start, &start, ((unsigned char *) xattrs) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr block %d, length %d\n", i, length); if(length == 0) { ERROR("Failed to read xattr block %d\n", i); goto failed3; } } /* swap if necessary the xattr id entries */ for(i = 0; i < ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]); free(index); return ids; failed3: free(xattrs); failed2: free(xattr_ids); failed1: free(index); return 0; } /* * Construct and return the list of xattr name:value pairs for the passed xattr * id */ struct xattr_list *get_xattr(int i, unsigned int *count) { long long start; struct xattr_list *xattr_list = NULL; unsigned int offset; void *xptr; int j; TRACE("get_xattr\n"); *count = xattr_ids[i].count; start = SQUASHFS_XATTR_BLK(xattr_ids[i].xattr) + xattr_table_start; offset = SQUASHFS_XATTR_OFFSET(xattr_ids[i].xattr); xptr = xattrs + get_xattr_block(start) + offset; TRACE("get_xattr: xattr_id %d, count %d, start %lld, offset %d\n", i, *count, start, offset); for(j = 0; j < *count; j++) { struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; int res; xattr_list = realloc(xattr_list, (j + 1) * sizeof(struct xattr_list)); if(xattr_list == NULL) { ERROR("Out of memory in get_xattrs\n"); goto failed; } SQUASHFS_SWAP_XATTR_ENTRY(&entry, xptr); xptr += sizeof(entry); res = read_xattr_entry(&xattr_list[j], &entry, xptr); if(res != 1) goto failed; xptr += entry.size; TRACE("get_xattr: xattr %d, type %d, size %d, name %s\n", j, entry.type, entry.size, xattr_list[j].full_name); if(entry.type & SQUASHFS_XATTR_VALUE_OOL) { long long xattr; void *ool_xptr; xptr += sizeof(val); SQUASHFS_SWAP_LONG_LONGS(&xattr, xptr, 1); xptr += sizeof(xattr); start = SQUASHFS_XATTR_BLK(xattr) + xattr_table_start; offset = SQUASHFS_XATTR_OFFSET(xattr); ool_xptr = xattrs + get_xattr_block(start) + offset; SQUASHFS_SWAP_XATTR_VAL(&val, ool_xptr); xattr_list[j].value = ool_xptr + sizeof(val); } else { SQUASHFS_SWAP_XATTR_VAL(&val, xptr); xattr_list[j].value = xptr + sizeof(val); xptr += sizeof(val) + val.vsize; } TRACE("get_xattr: xattr %d, vsize %d\n", j, val.vsize); xattr_list[j].vsize = val.vsize; } return xattr_list; failed: free(xattr_list); return NULL; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include "squashfs_fs.h" #include "mksquashfs.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) \ do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %d, st_ino " "%lld\n", path, priority, (int) buf.st_dev, (long long) buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is " "supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry"); ERROR(" should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to " "$PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source " "directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory " "test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) { ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more " "than one source entry! Please use an absolute path." "\n", path); return FALSE; } error: ERROR("Cannot stat sortlist entry \"%s\"\n", path); ERROR("This is probably because you're using the wrong file\n"); ERROR("path relative to the source directories\n"); /* * Historical note * Failure to stat a sortlist entry is deliberately ignored, even * though it is an error. Squashfs release 2.2 changed the behaviour * to treat it as a fatal error, but it was changed back to * the original behaviour to ignore it in release 2.2-r2 following * feedback from users at the time. */ return TRUE; } int generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { int res; priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: res = add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); if(res == FALSE) return FALSE; break; case S_IFDIR: res = generate_file_priorities(dir_ent->dir, priority, buf); if(res == FALSE) return FALSE; break; } } dir->current_count = 0; return TRUE; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int res, priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) { res = add_sort_list(sort_filename, priority, source, source_path); if(res == FALSE) return FALSE; } else ERROR("Sort file %s, priority %d outside range of " "-32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s" "\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes " "LINK\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/squashfs_compat.h ================================================ #ifndef SQUASHFS_COMPAT #define SQUASHFS_COMPAT /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_compat.h */ /* * definitions for structures on disk - layout 3.x */ #define SQUASHFS_CHECK 2 #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 struct squashfs_super_block_3 { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index_3 { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER_3 \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; } __attribute__ ((packed)); struct squashfs_ipc_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; squashfs_block start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; squashfs_block start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index_3 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_3 { struct squashfs_base_inode_header_3 base; struct squashfs_dev_inode_header_3 dev; struct squashfs_symlink_inode_header_3 symlink; struct squashfs_reg_inode_header_3 reg; struct squashfs_lreg_inode_header_3 lreg; struct squashfs_dir_inode_header_3 dir; struct squashfs_ldir_inode_header_3 ldir; struct squashfs_ipc_inode_header_3 ipc; }; struct squashfs_dir_entry_3 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header_3 { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry_3 { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); typedef struct squashfs_super_block_3 squashfs_super_block_3; typedef struct squashfs_dir_index_3 squashfs_dir_index_3; typedef struct squashfs_base_inode_header_3 squashfs_base_inode_header_3; typedef struct squashfs_ipc_inode_header_3 squashfs_ipc_inode_header_3; typedef struct squashfs_dev_inode_header_3 squashfs_dev_inode_header_3; typedef struct squashfs_symlink_inode_header_3 squashfs_symlink_inode_header_3; typedef struct squashfs_reg_inode_header_3 squashfs_reg_inode_header_3; typedef struct squashfs_lreg_inode_header_3 squashfs_lreg_inode_header_3; typedef struct squashfs_dir_inode_header_3 squashfs_dir_inode_header_3; typedef struct squashfs_ldir_inode_header_3 squashfs_ldir_inode_header_3; typedef struct squashfs_dir_entry_3 squashfs_dir_entry_3; typedef struct squashfs_dir_header_3 squashfs_dir_header_3; typedef struct squashfs_fragment_entry_3 squashfs_fragment_entry_3; /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block_3));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER_3(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ipc_inode_header_3))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dev_inode_header_3)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_symlink_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_reg_inode_header_3));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_lreg_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ldir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_3));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_3));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_3));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_INODE_T_3(s, d) SQUASHFS_SWAP_LONG_LONGS_3(s, d, 1) #define SQUASHFS_SWAP_SHORTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_FRAGMENT_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_3));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_3(A) ((A) * sizeof(struct squashfs_fragment_entry_3)) #define SQUASHFS_FRAGMENT_INDEX_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_3(A) ((SQUASHFS_FRAGMENT_BYTES_3(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_3(A) (SQUASHFS_FRAGMENT_INDEXES_3(A) *\ sizeof(long long)) /* * definitions for structures on disk - layout 1.x */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } /* * definitions for structures on disk - layout 2.x */ struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS_3(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) ((A) * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 4 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* * Squashfs + LZMA */ #define SQUASHFS_MAGIC_LZMA 0x71736873 #define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_IDS 65536 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_XATTR ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_NOX 8 #define SQUASHFS_NO_XATTR 9 #define SQUASHFS_COMP_OPT 10 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_UNCOMPRESSED_XATTRS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOX) #define SQUASHFS_NO_XATTRS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_XATTR) #define SQUASHFS_COMP_OPTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_COMP_OPT) #define SQUASHFS_MKFLAGS(noi, nod, nof, nox, no_frag, always_frag, \ duplicate_checking, exportable, no_xattr, comp_opt) (noi | \ (nod << 1) | (nof << 3) | (no_frag << 4) | \ (always_frag << 5) | (duplicate_checking << 6) | \ (exportable << 7) | (nox << 8) | (no_xattr << 9) | \ (comp_opt << 10)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 #define SQUASHFS_LSYMLINK_TYPE 10 #define SQUASHFS_LBLKDEV_TYPE 11 #define SQUASHFS_LCHRDEV_TYPE 12 #define SQUASHFS_LFIFO_TYPE 13 #define SQUASHFS_LSOCKET_TYPE 14 /* Xattr types */ #define SQUASHFS_XATTR_USER 0 #define SQUASHFS_XATTR_TRUSTED 1 #define SQUASHFS_XATTR_SECURITY 2 #define SQUASHFS_XATTR_VALUE_OOL 256 #define SQUASHFS_XATTR_PREFIX_MASK 0xff /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* uid lookup table defines */ #define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int)) #define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ sizeof(long long)) /* xattr id lookup table defines */ #define SQUASHFS_XATTR_BYTES(A) ((A) * sizeof(struct squashfs_xattr_id)) #define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCK_OFFSET(A) (SQUASHFS_XATTR_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCKS(A) ((SQUASHFS_XATTR_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCK_BYTES(A) (SQUASHFS_XATTR_BLOCKS(A) *\ sizeof(long long)) #define SQUASHFS_XATTR_BLK(A) ((unsigned int) ((A) >> 16)) #define SQUASHFS_XATTR_OFFSET(A) ((unsigned int) ((A) & 0xffff)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block; typedef long long squashfs_inode; #define ZLIB_COMPRESSION 1 #define LZMA_COMPRESSION 2 #define LZO_COMPRESSION 3 #define XZ_COMPRESSION 4 struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time /* time of filesystem creation */; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode root_inode; long long bytes_used; long long id_table_start; long long xattr_id_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; }; struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned int size; unsigned char name[0]; }; struct squashfs_base_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; }; struct squashfs_ipc_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; }; struct squashfs_lipc_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int xattr; }; struct squashfs_dev_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int rdev; }; struct squashfs_ldev_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int rdev; unsigned int xattr; }; struct squashfs_symlink_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int symlink_size; char symlink[0]; }; struct squashfs_reg_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned int block_list[0]; }; struct squashfs_lreg_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; squashfs_block start_block; long long file_size; long long sparse; unsigned int nlink; unsigned int fragment; unsigned int offset; unsigned int xattr; unsigned int block_list[0]; }; struct squashfs_dir_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int start_block; unsigned int nlink; unsigned short file_size; unsigned short offset; unsigned int parent_inode; }; struct squashfs_ldir_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int file_size; unsigned int start_block; unsigned int parent_inode; unsigned short i_count; unsigned short offset; unsigned int xattr; struct squashfs_dir_index index[0]; }; union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_ldev_inode_header ldev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; struct squashfs_lipc_inode_header lipc; }; struct squashfs_dir_entry { unsigned short offset; short inode_number; unsigned short type; unsigned short size; char name[0]; }; struct squashfs_dir_header { unsigned int count; unsigned int start_block; unsigned int inode_number; }; struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; }; struct squashfs_xattr_entry { unsigned short type; unsigned short size; char data[0]; }; struct squashfs_xattr_val { unsigned int vsize; char value[0]; }; struct squashfs_xattr_id { long long xattr; unsigned int count; unsigned int size; }; struct squashfs_xattr_table { long long xattr_table_start; unsigned int xattr_ids; unsigned int unused; }; #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/squashfs_swap.h ================================================ #ifndef SQUASHFS_SWAP_H #define SQUASHFS_SWAP_H /* * Squashfs * * Copyright (c) 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_swap.h */ /* * macros to convert each stucture from big endian to little endian */ #if __BYTE_ORDER == __BIG_ENDIAN #include <stddef.h> extern void swap_le16(void *, void *); extern void swap_le32(void *, void *); extern void swap_le64(void *, void *); extern void swap_le16_num(void *, void *, int); extern void swap_le32_num(void *, void *, int); extern void swap_le64_num(void *, void *, int); extern unsigned short inswap_le16(unsigned short); extern unsigned int inswap_le32(unsigned int); extern long long inswap_le64(long long); extern void inswap_le16_num(unsigned short *, int); extern void inswap_le32_num(unsigned int *, int); extern void inswap_le64_num(long long *, int); #define _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, s_magic, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, inodes, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, mkfs_time, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, block_size, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, fragments, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, compression, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, block_log, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, flags, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, no_ids, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, s_major, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, s_minor, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, root_inode, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, bytes_used, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, id_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, xattr_id_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, inode_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, directory_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, fragment_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, lookup_table_start, struct squashfs_super_block);\ } #define _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, index, struct squashfs_dir_index);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_index);\ SWAP_FUNC(32, s, d, size, struct squashfs_dir_index);\ } #define _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_base_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_base_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_base_inode_header);\ } #define _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ipc_inode_header);\ } #define _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_lipc_inode_header);\ } #define _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, rdev, struct squashfs_dev_inode_header);\ } #define _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, rdev, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_ldev_inode_header);\ } #define _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, symlink_size, struct squashfs_symlink_inode_header);\ } #define _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, fragment, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, offset, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, file_size, struct squashfs_reg_inode_header);\ } #define _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, start_block, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, file_size, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, sparse, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, fragment, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, offset, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_lreg_inode_header);\ } #define _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, file_size, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, offset, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, parent_inode, struct squashfs_dir_inode_header);\ } #define _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, file_size, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, parent_inode, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, i_count, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, offset, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_ldir_inode_header);\ } #define _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, offset, struct squashfs_dir_entry);\ SWAP_FUNC##S(16, s, d, inode_number, struct squashfs_dir_entry);\ SWAP_FUNC(16, s, d, type, struct squashfs_dir_entry);\ SWAP_FUNC(16, s, d, size, struct squashfs_dir_entry);\ } #define _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, count, struct squashfs_dir_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_header);\ } #define _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, start_block, struct squashfs_fragment_entry);\ SWAP_FUNC(32, s, d, size, struct squashfs_fragment_entry);\ } #define _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, type, struct squashfs_xattr_entry);\ SWAP_FUNC(16, s, d, size, struct squashfs_xattr_entry);\ } #define _SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, vsize, struct squashfs_xattr_val);\ } #define _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, xattr, struct squashfs_xattr_id);\ SWAP_FUNC(32, s, d, count, struct squashfs_xattr_id);\ SWAP_FUNC(32, s, d, size, struct squashfs_xattr_id);\ } #define _SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, xattr_table_start, struct squashfs_xattr_table);\ SWAP_FUNC(32, s, d, xattr_ids, struct squashfs_xattr_table);\ } /* big endian architecture copy and swap macros */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_LE) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \ _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_VAL(s, d) \ _SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_ID(s, d) \ _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_TABLE(s, d) \ _SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_LE) #define SWAP_LE(bits, s, d, field, type) \ SWAP_LE##bits(((void *)(s)) + offsetof(type, field), \ ((void *)(d)) + offsetof(type, field)) #define SWAP_LES(bits, s, d, field, type) \ SWAP_LE(bits, s, d, field, type) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \ SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) /* big endian architecture swap in-place macros */ #define SQUASHFS_INSWAP_SUPER_BLOCK(s) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INDEX(s) \ _SQUASHFS_SWAP_DIR_INDEX(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_ENTRY(s) \ _SQUASHFS_SWAP_DIR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_HEADER(s) \ _SQUASHFS_SWAP_DIR_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_ENTRY(s) \ _SQUASHFS_SWAP_XATTR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_VAL(s) \ _SQUASHFS_SWAP_XATTR_VAL(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_ID(s) \ _SQUASHFS_SWAP_XATTR_ID(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_TABLE(s) \ _SQUASHFS_SWAP_XATTR_TABLE(s, s, INSWAP_LE) #define INSWAP_LE(bits, s, d, field, type) \ (s)->field = inswap_le##bits((s)->field) #define INSWAP_LES(bits, s, d, field, type) \ (s)->field = (short) inswap_le##bits((unsigned short) \ (s)->field) #define SQUASHFS_INSWAP_INODE_T(s) s = inswap_le64(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) inswap_le16_num(s, n) #define SQUASHFS_INSWAP_INTS(s, n) inswap_le32_num(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) inswap_le64_num(s, n) #else /* little endian architecture, just copy */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_VAL(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_ID(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_TABLE(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \ SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) /* little endian architecture, data already in place so do nothing */ #define SQUASHFS_INSWAP_SUPER_BLOCK(s) #define SQUASHFS_INSWAP_DIR_INDEX(s) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_ENTRY(s) #define SQUASHFS_INSWAP_DIR_HEADER(s) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) #define SQUASHFS_INSWAP_XATTR_ENTRY(s) #define SQUASHFS_INSWAP_XATTR_VAL(s) #define SQUASHFS_INSWAP_XATTR_ID(s) #define SQUASHFS_INSWAP_XATTR_TABLE(s) #define SQUASHFS_INSWAP_INODE_T(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) #define SQUASHFS_INSWAP_INTS(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) #endif #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/swap.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * swap.c */ #ifndef linux #ifndef __CYGWIN__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #else #include <endian.h> #endif #if __BYTE_ORDER == __BIG_ENDIAN void swap_le16(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[1]; d[1] = s[0]; } void swap_le32(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } void swap_le64(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; d[3] = s[4]; d[4] = s[3]; d[5] = s[2]; d[6] = s[1]; d[7] = s[0]; } unsigned short inswap_le16(unsigned short num) { return (num >> 8) | ((num & 0xff) << 8); } unsigned int inswap_le32(unsigned int num) { return (num >> 24) | ((num & 0xff0000) >> 8) | ((num & 0xff00) << 8) | ((num & 0xff) << 24); } long long inswap_le64(long long n) { unsigned long long num = n; return (num >> 56) | ((num & 0xff000000000000LL) >> 40) | ((num & 0xff0000000000LL) >> 24) | ((num & 0xff00000000LL) >> 8) | ((num & 0xff000000) << 8) | ((num & 0xff0000) << 24) | ((num & 0xff00) << 40) | ((num & 0xff) << 56); } #define SWAP_LE_NUM(BITS) \ void swap_le##BITS##_num(void *s, void *d, int n) \ {\ int i;\ for(i = 0; i < n; i++, s += BITS / 8, d += BITS / 8)\ swap_le##BITS(s, d);\ } SWAP_LE_NUM(16) SWAP_LE_NUM(32) SWAP_LE_NUM(64) #define INSWAP_LE_NUM(BITS, TYPE) \ void inswap_le##BITS##_num(TYPE *s, int n) \ {\ int i;\ for(i = 0; i < n; i++)\ s[i] = inswap_le##BITS(s[i]);\ } INSWAP_LE_NUM(16, unsigned short) INSWAP_LE_NUM(32, unsigned int) INSWAP_LE_NUM(64, long long) #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquash-1.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-1.c */ #include "unsquashfs.h" #include "squashfs_compat.h" void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; TRACE("read_block_list: blocks %d\n", blocks); for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS_3((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } int read_fragment_table_1() { TRACE("read_fragment_table\n"); return TRUE; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_1 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.xattr = SQUASHFS_INVALID_XATTR; i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.s.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; i.sparse = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: EXIT_UNSQUASH("Unknown inode type %d in " " read_inode_header_1!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_1(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_1() { int res; TRACE("read_uids_guids: no_uids %d, no_guids %d\n", sBlk.no_uids, sBlk.no_guids); uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int)); if(uid_table == NULL) { ERROR("read_uids_guids: failed to allocate uid/gid table\n"); return FALSE; } guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), suid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } SQUASHFS_SWAP_INTS_3(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else { res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), uid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } } return TRUE; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquash-2.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-2.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_2 *fragment_table; void read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) { TRACE("read_block_list: blocks %d\n", blocks); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } int read_fragment_table_2() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.s.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(squashfs_fragment_entry_2)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else { res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.s.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } return TRUE; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_2 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.xattr = SQUASHFS_INVALID_XATTR; i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.s.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: EXIT_UNSQUASH("Unknown inode type %d in " "read_inode_header_2!\n", header.base.inode_type); } return &i; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquash-3.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-3.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_3 *fragment_table; int read_fragment_table_3() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.s.fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(squashfs_fragment_entry_3)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { long long sfragment_table_index[indexes]; res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index, sfragment_table_index, indexes); } else { res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_3 sfragment; for(i = 0; i < sBlk.s.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_3)); } } return TRUE; } void read_fragment_3(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_3 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_3(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_3 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_3(&header.base, &sinode, sizeof(squashfs_base_inode_header_3)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.xattr = SQUASHFS_INVALID_XATTR; i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_3 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_3(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_3 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_3(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_3 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header_3 *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.s.block_size - 1) >> sBlk.s.block_log : inode->file_size >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_3 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_3), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_3 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: EXIT_UNSQUASH("Unknown inode type %d in read_inode!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_3(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_3 dirh; char buffer[sizeof(squashfs_dir_entry_3) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); squashfs_dir_entry_3 *dire = (squashfs_dir_entry_3 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes - 3; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_3 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_3(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_3 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_3(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquash-4.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-4.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "read_fs.h" static struct squashfs_fragment_entry *fragment_table; static unsigned int *id_table; int read_fragment_table_4() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.s.fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(struct squashfs_fragment_entry)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment table " "index\n"); return FALSE; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < sBlk.s.fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]); return TRUE; } void read_fragment_4(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); struct squashfs_fragment_entry *fragment_entry; fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_4(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, block_ptr); i.uid = (uid_t) id_table[header.base.uid]; i.gid = (uid_t) id_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header *inode = &header.dir; SQUASHFS_SWAP_DIR_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header *inode = &header.ldir; SQUASHFS_SWAP_LDIR_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.xattr = inode->xattr; break; } case SQUASHFS_FILE_TYPE: { struct squashfs_reg_inode_header *inode = &header.reg; SQUASHFS_SWAP_REG_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LREG_TYPE: { struct squashfs_lreg_inode_header *inode = &header.lreg; SQUASHFS_SWAP_LREG_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.s.block_size - 1) >> sBlk.s.block_log : inode->file_size >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = inode->sparse != 0; i.block_ptr = block_ptr + sizeof(*inode); i.xattr = inode->xattr; break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { struct squashfs_symlink_inode_header *inode = &header.symlink; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inode, block_ptr); i.symlink = malloc(inode->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(struct squashfs_symlink_inode_header), inode->symlink_size); i.symlink[inode->symlink_size] = '\0'; i.data = inode->symlink_size; if(header.base.inode_type == SQUASHFS_LSYMLINK_TYPE) SQUASHFS_SWAP_INTS(&i.xattr, block_ptr + sizeof(struct squashfs_symlink_inode_header) + inode->symlink_size, 1); else i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { struct squashfs_dev_inode_header *inode = &header.dev; SQUASHFS_SWAP_DEV_INODE_HEADER(inode, block_ptr); i.data = inode->rdev; i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { struct squashfs_ldev_inode_header *inode = &header.ldev; SQUASHFS_SWAP_LDEV_INODE_HEADER(inode, block_ptr); i.data = inode->rdev; i.xattr = inode->xattr; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; i.xattr = SQUASHFS_INVALID_XATTR; break; case SQUASHFS_LFIFO_TYPE: case SQUASHFS_LSOCKET_TYPE: { struct squashfs_lipc_inode_header *inode = &header.lipc; SQUASHFS_SWAP_LIPC_INODE_HEADER(inode, block_ptr); i.data = 0; i.xattr = inode->xattr; break; } default: EXIT_UNSQUASH("Unknown inode type %d in read_inode!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_4(unsigned int block_start, unsigned int offset, struct inode **i) { struct squashfs_dir_header dirh; char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes - 3; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, directory_table + bytes); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, directory_table + bytes); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_4() { int res, i, indexes = SQUASHFS_ID_BLOCKS(sBlk.s.no_ids); long long id_index_table[indexes]; TRACE("read_uids_guids: no_ids %d\n", sBlk.s.no_ids); id_table = malloc(SQUASHFS_ID_BYTES(sBlk.s.no_ids)); if(id_table == NULL) { ERROR("read_uids_guids: failed to allocate id table\n"); return FALSE; } res = read_fs_bytes(fd, sBlk.s.id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk.s.no_ids), id_index_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read id index table\n"); return FALSE; } SQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes); for(i = 0; i < indexes; i++) { res = read_block(fd, id_index_table[i], NULL, ((char *) id_table) + i * SQUASHFS_METADATA_SIZE); if(res == FALSE) { ERROR("read_uids_guids: failed to read id table block" "\n"); return FALSE; } } SQUASHFS_INSWAP_INTS(id_table, sBlk.s.no_ids); return TRUE; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "squashfs_compat.h" #include "read_fs.h" #include "compressor.h" #include "xattr.h" #include <sys/types.h> struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; struct super_block sBlk; squashfs_operations s_ops; struct compressor *comp; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; int use_regex = FALSE; char **created_inode; int root_process; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int inode_number = 1; int no_xattrs = XATTR_DEF; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { #ifndef __CYGWIN__ struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; #else columns = 80; #endif } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) EXIT_UNSQUASH("Out of memory in queue_init\n"); queue->data = malloc(sizeof(void *) * (size + 1)); if(queue->data == NULL) EXIT_UNSQUASH("Out of memory in queue_init\n"); queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) EXIT_UNSQUASH("Out of memory in cache_init\n"); cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* * Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for * reading off disk and decompression. The cache grows until max_blocks * is reached, once this occurs existing discarded blocks on the free * list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* * found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* * not in the cache * * first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) EXIT_UNSQUASH("Out of memory in cache_get\n"); entry->data = malloc(cache->buffer_size); if(entry->data == NULL) EXIT_UNSQUASH("Out of memory in cache_get\n"); entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* * try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* * initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* * queue to read thread to read and ultimately (via the * decompress threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; } void cache_block_ready(struct cache_entry *entry, int error) { /* * mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* * if the wait_pending flag is set, one or more threads may be waiting * on this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* * wait for this cache entry to become ready, when reading and (if * necessary) decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* * finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains * accessible via the hash table it can be found getting a new lease of * life before it is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* * if the wait_free flag is set, one or more threads may be * waiting on this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } user = getpwuid(inode->uid); if(user == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; group = getgrgid(inode->gid); if(group == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } void add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; hash_table_entry = malloc(sizeof(struct hash_table_entry)); if(hash_table_entry == NULL) EXIT_UNSQUASH("Out of memory in add_entry\n"); hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; } int lookup_entry(struct hash_table_entry *hash_table[], long long start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_fs_bytes(int fd, long long byte, int bytes, void *buff) { off_t off = byte; int res, count; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) { ERROR("Read on filesystem failed because " "EOF\n"); return FALSE; } else if(errno != EINTR) { ERROR("Read on filesystem failed because %s\n", strerror(errno)); return FALSE; } else res = 0; } } return TRUE; } int read_block(int fd, long long start, long long *next, void *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) goto failed; c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); } else if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_fs_bytes(fd, start + offset, c_byte, buffer) == FALSE) goto failed; res = compressor_uncompress(comp, block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } if(next) *next = start + offset + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_fs_bytes(fd, start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: ERROR("read_block: failed to read block @0x%llx\n", start); return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int error, res; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_fs_bytes(fd, start, c_byte, data) == FALSE) goto failed; res = compressor_uncompress(comp, block, data, c_byte, block_size, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } return res; } else { if(read_fs_bytes(fd, start, c_byte, block) == FALSE) goto failed; return c_byte; } failed: ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, c_byte); return FALSE; } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE) { inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE); if(inode_table == NULL) EXIT_UNSQUASH("Out of memory in " "uncompress_inode_table"); } TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); res = read_block(fd, start, &start, inode_table + bytes); if(res == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read " "block \n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int xattr, unsigned int set_mode) { struct utimbuf times = { time, time }; write_xattr(pathname, xattr); if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids " "on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } int write_bytes(int fd, char *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write on output file failed because " "%s\n", strerror(errno)); return -1; } res = 0; } } return 0; } int lseek_broken = FALSE; char *zero_data = NULL; int write_block(int file_fd, char *buffer, int size, long long hole, int sparse) { off_t off = hole; if(hole) { if(sparse && lseek_broken == FALSE) { int error = lseek(file_fd, off, SEEK_CUR); if(error == -1) /* failed to seek beyond end of file */ lseek_broken = TRUE; } if((sparse == FALSE || lseek_broken) && zero_data == NULL) { if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc " "zero data block\n"); memset(zero_data, 0, block_size); } if(sparse == FALSE || lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write_bytes(file_fd, zero_data, avail_bytes) == -1) goto failure; } } } if(write_bytes(file_fd, buffer, size) == -1) goto failure; return TRUE; failure: return FALSE; } int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); if(file_fd == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } block_list = malloc(inode->blocks * sizeof(unsigned int)); if(block_list == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); file = malloc(sizeof(struct squashfs_file)); if(file == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* * the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are * queued separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); file->sparse = inode->sparse; file->xattr = inode->xattr; queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, " "because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, " "blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink " "%s, because %s\n", pathname, strerror(errno)); break; } write_xattr(pathname, i->xattr); if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change " "uid and gids on %s, because " "%s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create " "%s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s " "device %s, because you're not " "superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_LFIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, " "because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: case SQUASHFS_LSOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE) { directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE); if(directory_table == NULL) EXIT_UNSQUASH("Out of memory in " "uncompress_directory_table\n"); } TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); res = read_block(fd, start, &start, directory_table + bytes); if(res == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to " "read block\n"); bytes += res; } } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; TRACE("add_path: adding \"%s\" extract file\n", target); target = get_component(target, targname); if(paths == NULL) { paths = malloc(sizeof(struct pathname)); if(paths == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* * allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); if(paths->name == NULL) EXIT_UNSQUASH("Out of memory in add_path\n"); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(paths->name[i].preg == NULL) EXIT_UNSQUASH("Out of memory in add_path\n"); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* * at leaf pathname component */ paths->name[i].paths = NULL; else /* * recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* * existing matching entry */ if(paths->name[i].paths == NULL) { /* * No sub-directory which means this is the leaf * component of a pre-existing extract which subsumes * the extract currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* * at leaf pathname component and child components exist * from more specific extracts, delete as they're * subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* * recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); if(new == NULL) EXIT_UNSQUASH("Out of memory in init_subdir\n"); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) { paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); if(paths == NULL) EXIT_UNSQUASH("Out of memory in add_subdir\n"); } paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* * match on a leaf component, any subdirectories * will implicitly match, therefore return an * empty new search set */ goto empty_set; if(match) /* * match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* * no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* * one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* * found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } void pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { i = s_ops.read_inode(start_block, offset); if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); } void dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to make directory %s, because %s\n", parent_name, strerror(errno)); squashfs_closedir(dir); return; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { i = s_ops.read_inode(start_block, offset); if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } if(i->type == SQUASHFS_SYMLINK_TYPE || i->type == SQUASHFS_LSYMLINK_TYPE) free(i->symlink); } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, dir->xattr, force); squashfs_closedir(dir); dir_count ++; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.s.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s.s_major == 4 ? "" : swap ? "little endian " : "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); #else printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s.s_major == 4 ? "" : swap ? "big endian " : "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / (1024.0 * 1024.0)); if(sBlk.s.s_major == 4) printf("Compression %s\n", comp->name); printf("Block size %d\n", sBlk.s.block_size); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); if(sBlk.s.s_major > 1) { if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) printf("Fragments are not stored\n"); else { printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? "un" : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : "not "); } } if(sBlk.s.s_major == 4) { if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) printf("Xattrs are not stored\n"); else printf("Xattrs are %scompressed\n", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? "un" : ""); } if(sBlk.s.s_major < 4) printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : "not "); if(sBlk.s.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); else printf("Duplicates are removed\n"); if(sBlk.s.s_major > 1) printf("Number of fragments %d\n", sBlk.s.fragments); printf("Number of inodes %d\n", sBlk.s.inodes); if(sBlk.s.s_major == 4) printf("Number of ids %d\n", sBlk.s.no_ids); else { printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); } TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); TRACE("sBlk.s.directory_table_start 0x%llx\n", sBlk.s.directory_table_start); if(sBlk.s.s_major == 4) { TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", sBlk.s.xattr_id_table_start); } else { TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); } if(sBlk.s.s_major > 1) TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", sBlk.s.fragment_table_start); } int read_super(char *source) { squashfs_super_block_3 sBlk_3; struct squashfs_super_block sBlk_4; /* * Try to read a Squashfs 4 superblock */ read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), &sBlk_4); swap = (sBlk_4.s_magic != SQUASHFS_MAGIC && sBlk_4.s_magic != SQUASHFS_MAGIC_LZMA); SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); if((sBlk_4.s_magic == SQUASHFS_MAGIC || sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA) && sBlk_4.s_major == 4 && sBlk_4.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir_4; s_ops.read_fragment = read_fragment_4; s_ops.read_fragment_table = read_fragment_table_4; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_4; s_ops.read_uids_guids = read_uids_guids_4; memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); /* * Check the compression type */ if (sBlk_4.s_magic == SQUASHFS_MAGIC_LZMA) comp = lookup_compressor("lzma"); else comp = lookup_compressor_id(sBlk.s.compression); return TRUE; } /* * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock * (compatible with 1 and 2 filesystems) */ read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), &sBlk_3); /* * Check it is a SQUASHFS superblock */ swap = 0; if(sBlk_3.s_magic != SQUASHFS_MAGIC && sBlk_3.s_magic != SQUASHFS_MAGIC_LZMA) { if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP || sBlk_3.s_magic == SQUASHFS_MAGIC_LZMA_SWAP) { squashfs_super_block_3 sblk; ERROR("Reading a different endian SQUASHFS filesystem " "on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } sBlk.s.s_magic = sBlk_3.s_magic; sBlk.s.inodes = sBlk_3.inodes; sBlk.s.mkfs_time = sBlk_3.mkfs_time; sBlk.s.block_size = sBlk_3.block_size; sBlk.s.fragments = sBlk_3.fragments; sBlk.s.block_log = sBlk_3.block_log; sBlk.s.flags = sBlk_3.flags; sBlk.s.s_major = sBlk_3.s_major; sBlk.s.s_minor = sBlk_3.s_minor; sBlk.s.root_inode = sBlk_3.root_inode; sBlk.s.bytes_used = sBlk_3.bytes_used; sBlk.s.inode_table_start = sBlk_3.inode_table_start; sBlk.s.directory_table_start = sBlk_3.directory_table_start; sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; sBlk.no_uids = sBlk_3.no_uids; sBlk.no_guids = sBlk_3.no_guids; sBlk.uid_start = sBlk_3.uid_start; sBlk.guid_start = sBlk_3.guid_start; sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; /* Check the MAJOR & MINOR versions */ if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { sBlk.s.bytes_used = sBlk_3.bytes_used_2; sBlk.uid_start = sBlk_3.uid_start_2; sBlk.guid_start = sBlk_3.guid_start_2; sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; if(sBlk.s.s_major == 1) { sBlk.s.block_size = sBlk_3.block_size_1; sBlk.s.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; s_ops.read_uids_guids = read_uids_guids_1; } else { sBlk.s.fragment_table_start = sBlk_3.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_2; s_ops.read_uids_guids = read_uids_guids_1; } } else if(sBlk.s.s_major == 3) { s_ops.squashfs_opendir = squashfs_opendir_3; s_ops.read_fragment = read_fragment_3; s_ops.read_fragment_table = read_fragment_table_3; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_3; s_ops.read_uids_guids = read_uids_guids_1; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, sBlk.s.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } /* * 1.x, 2.x and 3.x filesystems use gzip compression. */ if (sBlk.s.s_magic == SQUASHFS_MAGIC_LZMA) comp = lookup_compressor("lzma"); else comp = lookup_compressor("gzip"); return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; fd = fopen(filename, "r"); if(fd == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* * reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_fs_bytes(fd, entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* * queue successfully read block to the deflate * thread(s) for further processing */ queue_put(to_deflate, entry); else /* * block has either been successfully read and is * uncompressed, or an error has occurred, clear pending * flag, set error appropriately, and wake up any * threads waiting on this buffer */ cache_block_ready(entry, !res); } } /* * writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; long long hole = 0; int failed = FALSE; int error; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed) continue; error = write_block(file_fd, block->buffer->data + block->offset, block->size, hole, file->sparse); if(error == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* * corner case for hole extending to end of file */ if(file->sparse == FALSE || lseek(file_fd, hole, SEEK_CUR) == -1) { /* * for files which we don't want to write * sparsely, or for broken lseeks which cannot * seek beyond end of file, write_block will do * the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole, file->sparse) == FALSE) { ERROR("writer: failed to write sparse " "data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data " "block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, file->xattr, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* * decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; while(1) { struct cache_entry *entry = queue_get(to_deflate); int error, res; res = compressor_uncompress(comp, tmp, entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, &error); if(res == -1) ERROR("%s uncompress failed with error code %d\n", comp->name, error); else memcpy(entry->data, tmp, res); /* * block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res == -1); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); #ifdef __CYGWIN__ processors = atoi(getenv("NUMBER_OF_PROCESSORS")); #else if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = sysconf(_SC_NPROCESSORS_ONLN); #endif } #endif /* __CYGWIN__ */ thread = malloc((3 + processors) * sizeof(pthread_t)); if(thread == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits, used, hashes, spaces; static int tty = -1; if(max == 0) return; max_digits = floor(log10(max)) + 1; used = max_digits * 2 + 11; hashes = (current * (columns - used)) / max; spaces = columns - used - hashes; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* * Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 4.2 (2011/02/28)\n");\ printf("copyright (C) 2011 Phillip Lougher "\ "<phillip@lougher.demon.co.uk>\n\n");\ printf("This program is free software; you can redistribute it and/or"\ "\n");\ printf("modify it under the terms of the GNU General Public License"\ "\n");\ printf("as published by the Free Software Foundation; either version "\ "2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be "\ "useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ "\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-xattrs") == 0 || strcmp(argv[i], "-no") == 0) no_xattrs = TRUE; else if(strcmp(argv[i], "-xattrs") == 0 || strcmp(argv[i], "-x") == 0) no_xattrs = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(lsonly || info) progress = FALSE; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or " "files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and " "copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " "default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress " "bar\n"); ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" NOXOPT_STR"\n"); ERROR("\t-x[attrs]\t\textract xattrs in file system" XOPT_STR "\n"); ERROR("\t-p[rocessors] <number>\tuse <number> " "processors. By default will use\n"); ERROR("\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are " "unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are " "unsquashed with file\n"); ERROR("\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" "\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file " "attributes (like\n"); ERROR("\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then " "overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " "information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or " "files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to " "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX " "regular expressions\n"); ERROR("\t\t\t\trather than use the default shell " "wildcard\n\t\t\t\texpansion (globbing)\n"); ERROR("\nDecompressors available:\n"); display_compressors("", ""); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } if(!comp->supported) { ERROR("Filesystem uses %s compression, this is " "unsupported by this version\n", comp->name); ERROR("Decompressors available:\n"); display_compressors("", ""); exit(1); } block_size = sBlk.s.block_size; block_log = sBlk.s.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); fragment_data = malloc(block_size); if(fragment_data == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); file_data = malloc(block_size); if(file_data == NULL) EXIT_UNSQUASH("failed to allocate file_data"); data = malloc(block_size); if(data == NULL) EXIT_UNSQUASH("failed to allocate data\n"); created_inode = malloc(sBlk.s.inodes * sizeof(char *)); if(created_inode == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); if(s_ops.read_uids_guids() == FALSE) EXIT_UNSQUASH("failed to uid/gid table\n"); if(s_ops.read_fragment_table() == FALSE) EXIT_UNSQUASH("failed to read fragment table\n"); uncompress_inode_table(sBlk.s.inode_table_start, sBlk.s.directory_table_start); uncompress_directory_table(sBlk.s.directory_table_start, sBlk.s.fragment_table_start); if(no_xattrs) sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; if(read_xattrs_from_disk(fd, &sBlk.s) == 0) EXIT_UNSQUASH("failed to read the xattr table\n"); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); inode_number = 1; printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquashfs.h ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.h */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #ifndef linux #ifndef __CYGWIN__ #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #endif #else #include <endian.h> #include <sys/sysinfo.h> #endif #ifdef __CYGWIN__ #include <sys/termios.h> #define FNM_EXTMATCH (1 << 5) #endif #ifndef FNM_EXTMATCH #define FNM_EXTMATCH 0 #endif #include "squashfs_fs.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) /* * Unified superblock containing fields for all superblocks */ struct super_block { struct squashfs_super_block s; /* fields only used by squashfs 3 and earlier layouts */ unsigned int no_uids; unsigned int no_guids; long long uid_start; long long guid_start; }; struct hash_table_entry { long long start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char *symlink; time_t time; int type; uid_t uid; char sparse; unsigned int xattr; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); int (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); int (*read_uids_guids)(); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; unsigned int xattr; struct dir_ent *dirs; }; struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; char sparse; unsigned int xattr; }; struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 /* globals */ extern struct super_block sBlk; extern squashfs_operations s_ops; extern int swap; extern char *inode_table, *directory_table; extern struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; extern unsigned int *uid_table, *guid_table; extern pthread_mutex_t screen_mutex; extern int progress_enabled; extern int inode_number; extern int lookup_type[]; extern int fd; /* unsquashfs.c */ extern int lookup_entry(struct hash_table_entry **, long long); extern int read_fs_bytes(int fd, long long, int, void *); extern int read_block(int, long long, long long *, void *); /* unsquash-1.c */ extern void read_block_list_1(unsigned int *, char *, int); extern int read_fragment_table_1(); extern struct inode *read_inode_1(unsigned int, unsigned int); extern struct dir *squashfs_opendir_1(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_1(); /* unsquash-2.c */ extern void read_block_list_2(unsigned int *, char *, int); extern int read_fragment_table_2(); extern void read_fragment_2(unsigned int, long long *, int *); extern struct inode *read_inode_2(unsigned int, unsigned int); /* unsquash-3.c */ extern int read_fragment_table_3(); extern void read_fragment_3(unsigned int, long long *, int *); extern struct inode *read_inode_3(unsigned int, unsigned int); extern struct dir *squashfs_opendir_3(unsigned int, unsigned int, struct inode **); /* unsquash-4.c */ extern int read_fragment_table_4(); extern void read_fragment_4(unsigned int, long long *, int *); extern struct inode *read_inode_4(unsigned int, unsigned int); extern struct dir *squashfs_opendir_4(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_4(); ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/unsquashfs_xattr.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs_xattr.c */ #include "unsquashfs.h" #include "xattr.h" #include <sys/xattr.h> extern int root_process; void write_xattr(char *pathname, unsigned int xattr) { unsigned int count; struct xattr_list *xattr_list; int i; if(xattr == SQUASHFS_INVALID_XATTR || sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK) return; xattr_list = get_xattr(xattr, &count); if(xattr_list == NULL) { ERROR("Failed to read xattrs for file %s\n", pathname); return; } for(i = 0; i < count; i++) { int prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK; if(root_process || prefix == SQUASHFS_XATTR_USER) { int res = lsetxattr(pathname, xattr_list[i].full_name, xattr_list[i].value, xattr_list[i].vsize, 0); if(res == -1) ERROR("write_xattr: failed to write xattr %s" " for file %s because %s\n", xattr_list[i].full_name, pathname, errno == ENOSPC || errno == EDQUOT ? "no extended attribute space remaining " "on destination filesystem" : errno == ENOTSUP ? "extended attributes are not supported " "by the destination filesystem" : "a weird error occurred"); } else ERROR("write_xattr: could not write xattr %s " "for file %s because you're not " "superuser!\n", xattr_list[i].full_name, pathname); } } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/xattr.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xattr.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <sys/xattr.h> #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "xattr.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) /* compressed xattr table */ static char *xattr_table = NULL; static unsigned int xattr_size = 0; /* cached uncompressed xattr data */ static char *data_cache = NULL; static int cache_bytes = 0, cache_size = 0; /* cached uncompressed xattr id table */ static struct squashfs_xattr_id *xattr_id_table = NULL; static int xattr_ids = 0; /* saved compressed xattr table */ unsigned int sxattr_bytes = 0, stotal_xattr_bytes = 0; /* saved cached uncompressed xattr data */ static char *sdata_cache = NULL; static int scache_bytes = 0; /* saved cached uncompressed xattr id table */ static int sxattr_ids = 0; /* xattr hash table for value duplicate detection */ static struct xattr_list *dupl[65536]; /* xattr hash table for id duplicate detection */ static struct dupl_id *dupl_id[65536]; /* file system globals from mksquashfs.c */ extern int no_xattrs, noX; extern long long bytes; extern int fd; extern unsigned int xattr_bytes, total_xattr_bytes; /* helper functions from mksquashfs.c */ extern unsigned short get_checksum(char *, int, unsigned short); extern void write_destination(int, long long, int, void *); extern long long generic_write_table(int, void *, int, void *, int); extern int mangle(char *, char *, int, int, int, int); /* helper functions and definitions from read_xattrs.c */ extern int read_xattrs_from_disk(int, struct squashfs_super_block *); extern struct xattr_list *get_xattr(int, unsigned int *); extern struct prefix prefix_table[]; static int get_prefix(struct xattr_list *xattr, char *name) { int i; xattr->full_name = strdup(name); for(i = 0; prefix_table[i].type != -1; i++) { struct prefix *p = &prefix_table[i]; if(strncmp(xattr->full_name, p->prefix, strlen(p->prefix)) == 0) break; } if(prefix_table[i].type != -1) { xattr->name = xattr->full_name + strlen(prefix_table[i].prefix); xattr->size = strlen(xattr->name); } return prefix_table[i].type; } static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) { ssize_t size, vsize; char *xattr_names, *p; int i; struct xattr_list *xattr_list = NULL; while(1) { size = llistxattr(filename, NULL, 0); if(size <= 0) { if(size < 0 && errno != ENOTSUP) ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } xattr_names = malloc(size); if(xattr_names == NULL) { ERROR("Out of memory in read_attrs\n"); return 0; } size = llistxattr(filename, xattr_names, size); if(size < 0) { free(xattr_names); if(errno == ERANGE) /* xattr list grew? Try again */ continue; else { ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } } break; } for(i = 0, p = xattr_names; p < xattr_names + size; i++) { struct xattr_list *x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list)); if(x == NULL) { ERROR("Out of memory in read_attrs\n"); goto failed; } else xattr_list = x; xattr_list[i].type = get_prefix(&xattr_list[i], p); p += strlen(p) + 1; if(xattr_list[i].type == -1) { ERROR("Unrecognised xattr prefix %s\n", xattr_list[i].full_name); free(xattr_list[i].full_name); i--; continue; } while(1) { vsize = lgetxattr(filename, xattr_list[i].full_name, NULL, 0); if(vsize < 0) { ERROR("lgetxattr failed for %s in read_attrs," " because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } xattr_list[i].value = malloc(vsize); if(xattr_list[i].value == NULL) { ERROR("Out of memory in read_attrs\n"); free(xattr_list[i].full_name); goto failed; } vsize = lgetxattr(filename, xattr_list[i].full_name, xattr_list[i].value, vsize); if(vsize < 0) { free(xattr_list[i].value); if(errno == ERANGE) /* xattr grew? Try again */ continue; else { ERROR("lgetxattr failed for %s in " "read_attrs, because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } } break; } xattr_list[i].vsize = vsize; TRACE("read_xattrs_from_system: filename %s, xattr name %s," " vsize %d\n", filename, xattr_list[i].full_name, xattr_list[i].vsize); } free(xattr_names); *xattrs = xattr_list; return i; failed: while(--i >= 0) { free(xattr_list[i].full_name); free(xattr_list[i].value); } free(xattr_list); free(xattr_names); return 0; } static int get_xattr_size(struct xattr_list *xattr) { int size = sizeof(struct squashfs_xattr_entry) + sizeof(struct squashfs_xattr_val) + xattr->size; if(xattr->type & XATTR_VALUE_OOL) size += XATTR_VALUE_OOL_SIZE; else size += xattr->vsize; return size; } static void *get_xattr_space(unsigned int req_size, long long *disk) { int data_space; unsigned short c_byte; /* * Move and compress cached uncompressed data into xattr table. */ while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { xattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(xattr_table == NULL) { goto failed; } xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noX, 0); TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; memmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } /* * Ensure there's enough space in the uncompressed data cache */ data_space = cache_size - cache_bytes; if(data_space < req_size) { int realloc_size = req_size - data_space; data_cache = realloc(data_cache, cache_size + realloc_size); if(data_cache == NULL) { goto failed; } cache_size += realloc_size; } if(disk) *disk = ((long long) xattr_bytes << 16) | cache_bytes; cache_bytes += req_size; return data_cache + cache_bytes - req_size; failed: ERROR("Out of memory in inode table reallocation!\n"); return NULL; } static struct dupl_id *check_id_dupl(struct xattr_list *xattr_list, int xattrs) { struct dupl_id *entry; int i; unsigned short checksum = 0; /* compute checksum over all xattrs */ for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; checksum = get_checksum(xattr->full_name, strlen(xattr->full_name), checksum); checksum = get_checksum(xattr->value, xattr->vsize, checksum); } for(entry = dupl_id[checksum]; entry; entry = entry->next) { if (entry->xattrs != xattrs) continue; for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; struct xattr_list *dup_xattr = &entry->xattr_list[i]; if(strcmp(xattr->full_name, dup_xattr->full_name)) break; if(memcmp(xattr->value, dup_xattr->value, xattr->vsize)) break; } if(i == xattrs) break; } if(entry == NULL) { /* no duplicate exists */ entry = malloc(sizeof(*entry)); if(entry == NULL) { ERROR("malloc failed in check_ip_dupl\n"); return NULL; } entry->xattrs = xattrs; entry->xattr_list = xattr_list; entry->xattr_id = SQUASHFS_INVALID_XATTR; entry->next = dupl_id[checksum]; dupl_id[checksum] = entry; } return entry; } static void check_value_dupl(struct xattr_list *xattr) { struct xattr_list *entry; if(xattr->vsize < XATTR_VALUE_OOL_SIZE) return; /* Check if this is a duplicate of an existing value */ xattr->vchecksum = get_checksum(xattr->value, xattr->vsize, 0); for(entry = dupl[xattr->vchecksum]; entry; entry = entry->vnext) { if(entry->vsize != xattr->vsize) continue; if(memcmp(entry->value, xattr->value, xattr->vsize) == 0) break; } if(entry == NULL) { /* * No duplicate exists, add to hash table, and mark as * requiring writing */ xattr->vnext = dupl[xattr->vchecksum]; dupl[xattr->vchecksum] = xattr; xattr->ool_value = SQUASHFS_INVALID_BLK; } else { /* * Duplicate exists, make type XATTR_VALUE_OOL, and * remember where the duplicate is */ xattr->type |= XATTR_VALUE_OOL; xattr->ool_value = entry->ool_value; /* on appending don't free duplicate values because the * duplicate value already points to the non-duplicate value */ if(xattr->value != entry->value) { free(xattr->value); xattr->value = entry->value; } } } static int get_xattr_id(int xattrs, struct xattr_list *xattr_list, long long xattr_disk, struct dupl_id *xattr_dupl) { int i, size = 0; struct squashfs_xattr_id *xattr_id; xattr_id_table = realloc(xattr_id_table, (xattr_ids + 1) * sizeof(struct squashfs_xattr_id)); if(xattr_id_table == NULL) { ERROR("Out of memory in xattr_id_table reallocation!\n"); return -1; } /* get total uncompressed size of xattr data, needed for stat */ for(i = 0; i < xattrs; i++) size += strlen(xattr_list[i].full_name) + 1 + xattr_list[i].vsize; xattr_id = &xattr_id_table[xattr_ids]; xattr_id->xattr = xattr_disk; xattr_id->count = xattrs; xattr_id->size = size; /* * keep track of total uncompressed xattr data, needed for mksquashfs * file system summary */ total_xattr_bytes += size; xattr_dupl->xattr_id = xattr_ids ++; return xattr_dupl->xattr_id; } long long write_xattrs() { unsigned short c_byte; int i, avail_bytes; char *datap = data_cache; long long start_bytes = bytes; struct squashfs_xattr_table header; if(xattr_ids == 0) return SQUASHFS_INVALID_BLK; /* * Move and compress cached uncompressed data into xattr table. */ while(cache_bytes) { if((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { xattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(xattr_table == NULL) { goto failed; } xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noX, 0); TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } /* * Write compressed xattr table to file system */ write_destination(fd, bytes, xattr_bytes, xattr_table); bytes += xattr_bytes; /* * Swap if necessary the xattr id table */ for(i = 0; i < xattr_ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_id_table[i]); header.xattr_ids = xattr_ids; header.xattr_table_start = start_bytes; SQUASHFS_INSWAP_XATTR_TABLE(&header); return generic_write_table(xattr_ids * sizeof(struct squashfs_xattr_id), xattr_id_table, sizeof(header), &header, noX); failed: ERROR("Out of memory in xattr_table reallocation!\n"); return -1; } int generate_xattrs(int xattrs, struct xattr_list *xattr_list) { int total_size, i; int xattr_value_max; void *xp; long long xattr_disk; struct dupl_id *xattr_dupl; /* * check if the file xattrs are a complete duplicate of a pre-existing * id */ xattr_dupl = check_id_dupl(xattr_list, xattrs); if (xattr_dupl == NULL) return SQUASHFS_INVALID_XATTR; if(xattr_dupl->xattr_id != SQUASHFS_INVALID_XATTR) return xattr_dupl->xattr_id; /* * Scan the xattr_list deciding which type to assign to each * xattr. The choice is fairly straightforward, and depends on the * size of each xattr name/value and the overall size of the * resultant xattr list stored in the xattr metadata table. * * Choices are whether to store data inline or out of line. * * The overall goal is to optimise xattr scanning and lookup, and * to enable the file system layout to scale from a couple of * small xattr name/values to a large number of large xattr * names/values without affecting performance. While hopefully * enabling the common case of a couple of small xattr name/values * to be stored efficiently * * Code repeatedly scans, doing the following * move xattr data out of line if it exceeds * xattr_value_max. Where xattr_value_max is * initially XATTR_INLINE_MAX. If the final uncompressed * xattr list is larger than XATTR_TARGET_MAX then more * aggressively move xattr data out of line by repeatedly * setting inline threshold to 1/2, then 1/4, 1/8 of * XATTR_INLINE_MAX until target achieved or there's * nothing left to move out of line */ xattr_value_max = XATTR_INLINE_MAX; while(1) { for(total_size = 0, i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; xattr->type &= XATTR_PREFIX_MASK; /* all inline */ if (xattr->vsize > xattr_value_max) xattr->type |= XATTR_VALUE_OOL; total_size += get_xattr_size(xattr); } /* * If the total size of the uncompressed xattr list is <= * XATTR_TARGET_MAX we're done */ if(total_size <= XATTR_TARGET_MAX) break; if(xattr_value_max == XATTR_VALUE_OOL_SIZE) break; /* * Inline target not yet at minimum and so reduce it, and * try again */ xattr_value_max /= 2; if(xattr_value_max < XATTR_VALUE_OOL_SIZE) xattr_value_max = XATTR_VALUE_OOL_SIZE; } /* * Check xattr values for duplicates */ for(i = 0; i < xattrs; i++) { check_value_dupl(&xattr_list[i]); } /* * Add each out of line value to the file system xattr table * if it doesn't already exist as a duplicate */ for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; if((xattr->type & XATTR_VALUE_OOL) && (xattr->ool_value == SQUASHFS_INVALID_BLK)) { struct squashfs_xattr_val val; int size = sizeof(val) + xattr->vsize; xp = get_xattr_space(size, &xattr->ool_value); val.vsize = xattr->vsize; SQUASHFS_SWAP_XATTR_VAL(&val, xp); memcpy(xp + sizeof(val), xattr->value, xattr->vsize); } } /* * Create xattr list and add to file system xattr table */ get_xattr_space(0, &xattr_disk); for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; xp = get_xattr_space(sizeof(entry) + xattr->size, NULL); entry.type = xattr->type; entry.size = xattr->size; SQUASHFS_SWAP_XATTR_ENTRY(&entry, xp); memcpy(xp + sizeof(entry), xattr->name, xattr->size); if(xattr->type & XATTR_VALUE_OOL) { int size = sizeof(val) + XATTR_VALUE_OOL_SIZE; xp = get_xattr_space(size, NULL); val.vsize = XATTR_VALUE_OOL_SIZE; SQUASHFS_SWAP_XATTR_VAL(&val, xp); SQUASHFS_SWAP_LONG_LONGS(&xattr->ool_value, xp + sizeof(val), 1); } else { int size = sizeof(val) + xattr->vsize; xp = get_xattr_space(size, &xattr->ool_value); val.vsize = xattr->vsize; SQUASHFS_SWAP_XATTR_VAL(&val, xp); memcpy(xp + sizeof(val), xattr->value, xattr->vsize); } } /* * Add to xattr id lookup table */ return get_xattr_id(xattrs, xattr_list, xattr_disk, xattr_dupl); } int read_xattrs(void *d) { struct dir_ent *dir_ent = d; struct inode_info *inode = dir_ent->inode; char *filename = dir_ent->pathname; struct xattr_list *xattr_list; int xattrs; if(no_xattrs || IS_PSEUDO(inode) || inode->root_entry) return SQUASHFS_INVALID_XATTR; xattrs = read_xattrs_from_system(filename, &xattr_list); if(xattrs == 0) return SQUASHFS_INVALID_XATTR; return generate_xattrs(xattrs, xattr_list); } /* * Add the existing xattr ids and xattr metadata in the file system being * appended to, to the in-memory xattr cache. This allows duplicate checking to * take place against the xattrs already in the file system being appended to, * and ensures the pre-existing xattrs are written out along with any new xattrs */ int get_xattrs(int fd, struct squashfs_super_block *sBlk) { int ids, res, i, id; unsigned int count; TRACE("get_xattrs\n"); res = read_xattrs_from_disk(fd, sBlk); if(res == SQUASHFS_INVALID_BLK || res == 0) goto done; ids = res; /* * for each xattr id read and construct its list of xattr * name:value pairs, and add them to the in-memory xattr cache */ for(i = 0; i < ids; i++) { struct xattr_list *xattr_list = get_xattr(i, &count); if(xattr_list == NULL) { res = 0; goto done; } id = generate_xattrs(count, xattr_list); /* * Sanity check, the new xattr id should be the same as the * xattr id in the original file system */ if(id != i) { ERROR("BUG, different xattr_id in get_xattrs\n"); res = 0; goto done; } } done: return res; } /* * Save current state of xattrs, needed for restoring state in the event of an * abort in appending */ int save_xattrs() { /* save the current state of the compressed xattr data */ sxattr_bytes = xattr_bytes; stotal_xattr_bytes = total_xattr_bytes; /* * save the current state of the cached uncompressed xattr data. * Note we have to save the contents of the data cache because future * operations will delete the current contents */ sdata_cache = malloc(cache_bytes); if(sdata_cache == NULL) goto failed; memcpy(sdata_cache, data_cache, cache_bytes); scache_bytes = cache_bytes; /* save the current state of the xattr id table */ sxattr_ids = xattr_ids; return TRUE; failed: ERROR("Out of memory in save_xattrs\n"); return FALSE; } /* * Restore xattrs in the event of an abort in appending */ void restore_xattrs() { /* restore the state of the compressed xattr data */ xattr_bytes = sxattr_bytes; total_xattr_bytes = stotal_xattr_bytes; /* restore the state of the uncomoressed xattr data */ memcpy(data_cache, sdata_cache, scache_bytes); cache_bytes = scache_bytes; /* restore the state of the xattr id table */ xattr_ids = sxattr_ids; } ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/xattr.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xattr.h */ #define XATTR_VALUE_OOL SQUASHFS_XATTR_VALUE_OOL #define XATTR_PREFIX_MASK SQUASHFS_XATTR_PREFIX_MASK #define XATTR_VALUE_OOL_SIZE sizeof(long long) /* maximum size of xattr value data that will be inlined */ #define XATTR_INLINE_MAX 128 /* the target size of an inode's xattr name:value list. If it * exceeds this, then xattr value data will be successively out of lined * until it meets the target */ #define XATTR_TARGET_MAX 65536 #define IS_XATTR(a) (a != SQUASHFS_INVALID_XATTR) struct xattr_list { char *name; char *full_name; int size; int vsize; void *value; int type; long long ool_value; unsigned short vchecksum; struct xattr_list *vnext; }; struct dupl_id { struct xattr_list *xattr_list; int xattrs; int xattr_id; struct dupl_id *next; }; struct prefix { char *prefix; int type; }; extern int generate_xattrs(int, struct xattr_list *); #ifdef XATTR_SUPPORT extern int get_xattrs(int, struct squashfs_super_block *); extern int read_xattrs(void *); extern long long write_xattrs(); extern int save_xattrs(); extern void restore_xattrs(); extern unsigned int xattr_bytes, total_xattr_bytes; extern void write_xattr(char *, unsigned int); extern int read_xattrs_from_disk(int, struct squashfs_super_block *); extern struct xattr_list *get_xattr(int, unsigned int *); #else static inline int get_xattrs(int fd, struct squashfs_super_block *sBlk) { if(sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) { fprintf(stderr, "Xattrs in filesystem! These are not " "supported on this version of Squashfs\n"); return 0; } else return SQUASHFS_INVALID_BLK; } static inline int read_xattrs(void *dir_ent) { return SQUASHFS_INVALID_XATTR; } static inline long long write_xattrs() { return SQUASHFS_INVALID_BLK; } static inline int save_xattrs() { return 1; } static inline void restore_xattrs() { } static inline void write_xattr(char *pathname, unsigned int xattr) { } static inline int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { if(sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) { fprintf(stderr, "Xattrs in filesystem! These are not " "supported on this version of Squashfs\n"); return 0; } else return SQUASHFS_INVALID_BLK; } static inline struct xattr_list *get_xattr(int i, unsigned int *count) { return NULL; } #endif #ifdef XATTR_SUPPORT #ifdef XATTR_DEFAULT #define NOXOPT_STR #define XOPT_STR " (default)" #define XATTR_DEF 0 #else #define NOXOPT_STR " (default)" #define XOPT_STR #define XATTR_DEF 1 #endif #else #define NOXOPT_STR " (default)" #define XOPT_STR " (unsupported)" #define XATTR_DEF 1 #endif ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/xz_wrapper.c ================================================ /* * Copyright (c) 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xz_wrapper.c * * Support for XZ (LZMA2) compression using XZ Utils liblzma * http://tukaani.org/xz/ */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <lzma.h> #include "squashfs_fs.h" #include "xz_wrapper.h" #include "compressor.h" #include "lzma_xz_options.h" static struct bcj bcj[] = { { "x86", LZMA_FILTER_X86, 0 }, { "powerpc", LZMA_FILTER_POWERPC, 0 }, { "ia64", LZMA_FILTER_IA64, 0 }, { "arm", LZMA_FILTER_ARM, 0 }, { "armthumb", LZMA_FILTER_ARMTHUMB, 0 }, { "sparc", LZMA_FILTER_SPARC, 0 }, { NULL, LZMA_VLI_UNKNOWN, 0 } }; static int filter_count = 1; static int xz_options(char *argv[], int argc) { if(strcmp(argv[0], "-Xbcj") == 0) { int i; char *name; if(argc < 2) { fprintf(stderr, "xz: -Xbcj missing filter\n"); return -2; } name = argv[1]; while(name[0] != '\0') { for(i = 0; bcj[i].name; i++) { int n = strlen(bcj[i].name); if((strncmp(name, bcj[i].name, n) == 0) && (name[n] == '\0' || name[n] == ',')) { if(bcj[i].selected == 0) { bcj[i].selected = 1; filter_count++; } name += name[n] == ',' ? n + 1 : n; break; } } if(bcj[i].name == NULL) { fprintf(stderr, "xz: -Xbcj unrecognised " "filter\n"); return -2; } } return 1; } else { return lzma_xz_options(argv, argc, LZMA_OPT_XZ); } } static int xz_options_post(int block_size) { return lzma_xz_options_post(block_size, LZMA_OPT_XZ); } static void *xz_dump_options(int block_size, int *size) { int i, flags = 0; for(i = 0; bcj[i].name; i++) flags |= bcj[i].selected << i; return lzma_xz_dump_options(block_size, size, flags); } static int xz_extract_options(int block_size, void *buffer, int size) { int ret = lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_XZ); if (!ret) { int i; struct lzma_xz_options *opts = lzma_xz_get_options(); for(i = 0; bcj[i].name; i++) { if((opts->flags >> i) & 1) { bcj[i].selected = 1; filter_count ++; } else bcj[i].selected = 0; } } return ret; } static int xz_init(void **strm, int block_size, int datablock) { int i, j, filters = datablock ? filter_count : 1; struct filter *filter = malloc(filters * sizeof(struct filter)); struct xz_stream *stream; struct lzma_xz_options *opts = lzma_xz_get_options(); if(filter == NULL) goto failed; stream = *strm = malloc(sizeof(struct xz_stream)); if(stream == NULL) goto failed2; stream->filter = filter; stream->filters = filters; memset(filter, 0, filters * sizeof(struct filter)); stream->dictionary_size = datablock ? opts->dict_size : SQUASHFS_METADATA_SIZE; filter[0].filter[0].id = LZMA_FILTER_LZMA2; filter[0].filter[0].options = &stream->opt; filter[0].filter[1].id = LZMA_VLI_UNKNOWN; for(i = 0, j = 1; datablock && bcj[i].name; i++) { if(bcj[i].selected) { filter[j].buffer = malloc(block_size); if(filter[j].buffer == NULL) goto failed3; filter[j].filter[0].id = bcj[i].id; filter[j].filter[1].id = LZMA_FILTER_LZMA2; filter[j].filter[1].options = &stream->opt; filter[j].filter[2].id = LZMA_VLI_UNKNOWN; j++; } } return 0; failed3: for(i = 1; i < filters; i++) free(filter[i].buffer); free(stream); failed2: free(filter); failed: return -1; } static int xz_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) { int i; lzma_ret res = 0; struct xz_stream *stream = strm; struct filter *selected = NULL; struct lzma_xz_options *opts = lzma_xz_get_options(); stream->filter[0].buffer = dest; for(i = 0; i < stream->filters; i++) { uint32_t preset = opts->preset; struct filter *filter = &stream->filter[i]; if (opts->extreme) preset |= LZMA_PRESET_EXTREME; if(lzma_lzma_preset(&stream->opt, preset)) goto failed; stream->opt.lc = opts->lc; stream->opt.lp = opts->lp; stream->opt.pb = opts->pb; if (opts->fb) stream->opt.nice_len = opts->fb; stream->opt.dict_size = stream->dictionary_size; filter->length = 0; res = lzma_stream_buffer_encode(filter->filter, LZMA_CHECK_CRC32, NULL, src, size, filter->buffer, &filter->length, block_size); if(res == LZMA_OK) { if(!selected || selected->length > filter->length) selected = filter; } else if(res != LZMA_BUF_ERROR) goto failed; } if(!selected) /* * Output buffer overflow. Return out of buffer space */ return 0; if(selected->buffer != dest) memcpy(dest, selected->buffer, selected->length); return (int) selected->length; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int xz_uncompress(void *dest, void *src, int size, int block_size, int *error) { size_t src_pos = 0; size_t dest_pos = 0; uint64_t memlimit = MEMLIMIT; lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL, src, &src_pos, size, dest, &dest_pos, block_size); *error = res; return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1; } void xz_usage() { lzma_xz_usage(LZMA_OPT_XZ); fprintf(stderr, "\t -Xbcj filter1,filter2,...,filterN\n"); fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in"); fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose"); fprintf(stderr, " the best compression.\n"); fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,"); fprintf(stderr, " powerpc, sparc, ia64\n"); } struct compressor xz_comp_ops = { .init = xz_init, .compress = xz_compress, .uncompress = xz_uncompress, .options = xz_options, .options_post = xz_options_post, .dump_options = xz_dump_options, .extract_options = xz_extract_options, .usage = xz_usage, .id = XZ_COMPRESSION, .name = "xz", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2/squashfs-tools/xz_wrapper.h ================================================ #ifndef XZ_WRAPPER_H #define XZ_WRAPPER_H /* * Squashfs * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xz_wrapper.h * */ #define MEMLIMIT (32 * 1024 * 1024) struct bcj { char *name; lzma_vli id; int selected; }; struct filter { void *buffer; lzma_filter filter[3]; size_t length; }; struct xz_stream { struct filter *filter; int filters; int dictionary_size; lzma_options_lzma opt; }; struct comp_opts { int dictionary_size; int flags; }; #endif ================================================ FILE: src/others/squashfs-4.2-official/Makefile ================================================ ############################################### # Compression build options # ############################################### # # ############# Building gzip support ########### # # Gzip support is by default enabled, and the compression type default # (COMP_DEFAULT) is gzip. # # If you don't want/need gzip support then comment out the GZIP SUPPORT line # below, and change COMP_DEFAULT to one of the compression types you have # selected. # # Obviously, you must select at least one of the available gzip, lzma, lzo # compression types. # GZIP_SUPPORT = 1 ########### Building XZ support ############# # # LZMA2 compression. # # XZ Utils liblzma (http://tukaani.org/xz/) is supported # # To build using XZ Utils liblzma - install the library and uncomment # the XZ_SUPPORT line below. # XZ_SUPPORT = 1 ############ Building LZO support ############## # # The LZO library (http://www.oberhumer.com/opensource/lzo/) is supported. # # To build using the LZO library - install the library and uncomment the # LZO_SUPPORT line below. If needed, uncomment and set LZO_DIR to the # installation prefix. # #LZO_SUPPORT = 1 #LZO_DIR = /usr/local ########### Building LZMA support ############# # # LZMA1 compression. # # LZMA1 compression is deprecated, and the newer and better XZ (LZMA2) # compression should be used in preference. # # Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK # (http://www.7-zip.org/sdk.html) are supported # # To build using XZ Utils liblzma - install the library and uncomment # the LZMA_XZ_SUPPORT line below. # # To build using the LZMA SDK (4.65 used in development, other versions may # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source, # and uncomment the LZMA_SUPPORT line below. # LZMA_XZ_SUPPORT = 1 #LZMA_SUPPORT = 1 #LZMA_DIR = ../../../../LZMA/lzma465 ######## Specifying default compression ######## # # The next line specifies which compression algorithm is used by default # in Mksquashfs. Obviously the compression algorithm must have been # selected to be built # COMP_DEFAULT = gzip ############################################### # Extended attribute (XATTRs) build options # ############################################### # # Building XATTR support for Mksquashfs and Unsquashfs # # If your C library or build/target environment doesn't support XATTRs then # comment out the next line to build Mksquashfs and Unsquashfs without XATTR # support XATTR_SUPPORT = 1 # Select whether you wish xattrs to be stored by Mksquashfs and extracted # by Unsquashfs by default. If selected users can disable xattr support by # using the -no-xattrs option # # If unselected, Mksquashfs/Unsquashfs won't store and extract xattrs by # default. Users can enable xattrs by using the -xattrs option. XATTR_DEFAULT = 1 ############################################### # End of BUILD options section # ############################################### INCLUDEDIR = -I. INSTALL_DIR = /usr/local/bin MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ unsquash-4.o swap.o compressor.o CFLAGS ?= -O2 CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \ -D_LARGEFILE_SOURCE -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" \ -Wall LIBS = -lpthread -lm ifeq ($(GZIP_SUPPORT),1) CFLAGS += -DGZIP_SUPPORT MKSQUASHFS_OBJS += gzip_wrapper.o UNSQUASHFS_OBJS += gzip_wrapper.o LIBS += -lz COMPRESSORS += gzip endif ifeq ($(LZMA_SUPPORT),1) LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o INCLUDEDIR += -I$(LZMA_DIR)/C CFLAGS += -DLZMA_SUPPORT MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) COMPRESSORS += lzma endif ifeq ($(LZMA_XZ_SUPPORT),1) CFLAGS += -DLZMA_SUPPORT MKSQUASHFS_OBJS += lzma_xz_wrapper.o UNSQUASHFS_OBJS += lzma_xz_wrapper.o LIBS += -llzma COMPRESSORS += lzma endif ifeq ($(XZ_SUPPORT),1) CFLAGS += -DXZ_SUPPORT MKSQUASHFS_OBJS += xz_wrapper.o UNSQUASHFS_OBJS += xz_wrapper.o LIBS += -llzma COMPRESSORS += xz endif ifeq ($(LZO_SUPPORT),1) CFLAGS += -DLZO_SUPPORT ifdef LZO_DIR INCLUDEDIR += -I$(LZO_DIR)/include LZO_LIBDIR = -L$(LZO_DIR)/lib endif MKSQUASHFS_OBJS += lzo_wrapper.o UNSQUASHFS_OBJS += lzo_wrapper.o LIBS += $(LZO_LIBDIR) -llzo2 COMPRESSORS += lzo endif ifeq ($(XATTR_SUPPORT),1) ifeq ($(XATTR_DEFAULT),1) CFLAGS += -DXATTR_SUPPORT -DXATTR_DEFAULT else CFLAGS += -DXATTR_SUPPORT endif MKSQUASHFS_OBJS += xattr.o read_xattrs.o UNSQUASHFS_OBJS += read_xattrs.o unsquashfs_xattr.o endif # # If LZMA_SUPPORT is specified then LZMA_DIR must be specified too # ifeq ($(LZMA_SUPPORT),1) ifndef LZMA_DIR $(error "LZMA_SUPPORT requires LZMA_DIR to be also defined") endif endif # # Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified # ifeq ($(LZMA_XZ_SUPPORT),1) ifeq ($(LZMA_SUPPORT),1) $(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified") endif endif # # At least one compressor must have been selected # ifndef COMPRESSORS $(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!") endif # # COMP_DEFAULT must be a selected compressor # ifeq (, $(findstring $(COMP_DEFAULT), $(COMPRESSORS))) $(error "COMP_DEFAULT isn't selected to be built!") endif .PHONY: all all: mksquashfs unsquashfs mksquashfs: $(MKSQUASHFS_OBJS) $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(MKSQUASHFS_OBJS) $(LIBS) -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h sort.h squashfs_swap.h \ xattr.h pseudo.h compressor.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h squashfs_swap.h compressor.h \ xattr.h sort.o: sort.c squashfs_fs.h sort.h mksquashfs.h swap.o: swap.c pseudo.o: pseudo.c pseudo.h compressor.o: compressor.c compressor.h squashfs_fs.h xattr.o: xattr.c xattr.h squashfs_fs.h squashfs_swap.h mksquashfs.h read_xattrs.o: read_xattrs.c xattr.h squashfs_fs.h squashfs_swap.h read_fs.h gzip_wrapper.o: gzip_wrapper.c compressor.h squashfs_fs.h lzma_wrapper.o: lzma_wrapper.c compressor.h squashfs_fs.h lzma_xz_wrapper.o: lzma_xz_wrapper.c compressor.h squashfs_fs.h lzo_wrapper.o: lzo_wrapper.c compressor.h squashfs_fs.h xz_wrapper.o: xz_wrapper.c compressor.h squashfs_fs.h unsquashfs: $(UNSQUASHFS_OBJS) $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(UNSQUASHFS_OBJS) $(LIBS) -o $@ unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ squashfs_compat.h xattr.h read_fs.h compressor.h unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h unsquash-2.o: unsquashfs.h unsquash-2.c squashfs_fs.h squashfs_compat.h unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ read_fs.h unsquashfs_xattr.o: unsquashfs_xattr.c unsquashfs.h squashfs_fs.h xattr.h .PHONY: clean clean: -rm -f *.o mksquashfs unsquashfs .PHONY: install install: mksquashfs unsquashfs mkdir -p $(INSTALL_DIR) cp mksquashfs $(INSTALL_DIR) cp unsquashfs $(INSTALL_DIR) ================================================ FILE: src/others/squashfs-4.2-official/compressor.c ================================================ /* * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.c */ #include <stdio.h> #include <string.h> #include "compressor.h" #include "squashfs_fs.h" #ifndef GZIP_SUPPORT static struct compressor gzip_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 }; #else extern struct compressor gzip_comp_ops; #endif #ifndef LZMA_SUPPORT static struct compressor lzma_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }; #else extern struct compressor lzma_comp_ops; #endif #ifndef LZO_SUPPORT static struct compressor lzo_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 }; #else extern struct compressor lzo_comp_ops; #endif #ifndef XZ_SUPPORT static struct compressor xz_comp_ops = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 }; #else extern struct compressor xz_comp_ops; #endif static struct compressor unknown_comp_ops = { NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, 0, "unknown", 0 }; struct compressor *compressor[] = { &gzip_comp_ops, &lzma_comp_ops, &lzo_comp_ops, &xz_comp_ops, &unknown_comp_ops }; struct compressor *lookup_compressor(char *name) { int i; for(i = 0; compressor[i]->id; i++) if(strcmp(compressor[i]->name, name) == 0) break; return compressor[i]; } struct compressor *lookup_compressor_id(int id) { int i; for(i = 0; compressor[i]->id; i++) if(id == compressor[i]->id) break; return compressor[i]; } void display_compressors(char *indent, char *def_comp) { int i; for(i = 0; compressor[i]->id; i++) if(compressor[i]->supported) fprintf(stderr, "%s\t%s%s\n", indent, compressor[i]->name, strcmp(compressor[i]->name, def_comp) == 0 ? " (default)" : ""); } void display_compressor_usage(char *def_comp) { int i; for(i = 0; compressor[i]->id; i++) if(compressor[i]->supported) { char *str = strcmp(compressor[i]->name, def_comp) == 0 ? " (default)" : ""; if(compressor[i]->usage) { fprintf(stderr, "\t%s%s\n", compressor[i]->name, str); compressor[i]->usage(); } else fprintf(stderr, "\t%s (no options)%s\n", compressor[i]->name, str); } } ================================================ FILE: src/others/squashfs-4.2-official/compressor.h ================================================ /* * * Copyright (c) 2009, 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * compressor.h */ struct compressor { int (*init)(void **, int, int); int (*compress)(void *, void *, void *, int, int, int *); int (*uncompress)(void *, void *, int, int, int *); int (*options)(char **, int); int (*options_post)(int); void *(*dump_options)(int, int *); int (*extract_options)(int, void *, int); void (*usage)(); int id; char *name; int supported; }; extern struct compressor *lookup_compressor(char *); extern struct compressor *lookup_compressor_id(int); extern void display_compressors(char *, char *); extern void display_compressor_usage(char *); static inline int compressor_init(struct compressor *comp, void **stream, int block_size, int datablock) { if(comp->init == NULL) return 0; return comp->init(stream, block_size, datablock); } static inline int compressor_compress(struct compressor *comp, void *strm, void *dest, void *src, int size, int block_size, int *error) { return comp->compress(strm, dest, src, size, block_size, error); } static inline int compressor_uncompress(struct compressor *comp, void *dest, void *src, int size, int block_size, int *error) { return comp->uncompress(dest, src, size, block_size, error); } static inline int compressor_options(struct compressor *comp, char *argv[], int argc) { if(comp->options == NULL) return -1; return comp->options(argv, argc); } static inline int compressor_options_post(struct compressor *comp, int block_size) { if(comp->options_post == NULL) return 0; return comp->options_post(block_size); } static inline void *compressor_dump_options(struct compressor *comp, int block_size, int *size) { if(comp->dump_options == NULL) return NULL; return comp->dump_options(block_size, size); } static inline int compressor_extract_options(struct compressor *comp, int block_size, void *buffer, int size) { if(comp->extract_options == NULL) return size ? -1 : 0; return comp->extract_options(block_size, buffer, size); } ================================================ FILE: src/others/squashfs-4.2-official/gzip_wrapper.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * gzip_wrapper.c */ #include <stdlib.h> #include <zlib.h> #include "squashfs_fs.h" #include "compressor.h" static int gzip_init(void **strm, int block_size, int flags) { int res; z_stream *stream; stream = *strm = malloc(sizeof(z_stream)); if(stream == NULL) goto failed; stream->zalloc = Z_NULL; stream->zfree = Z_NULL; stream->opaque = 0; res = deflateInit(stream, 9); if(res != Z_OK) goto failed2; return 0; failed2: free(stream); failed: return -1; } static int gzip_compress(void *strm, void *d, void *s, int size, int block_size, int *error) { int res; z_stream *stream = strm; res = deflateReset(stream); if(res != Z_OK) goto failed; stream->next_in = s; stream->avail_in = size; stream->next_out = d; stream->avail_out = block_size; res = deflate(stream, Z_FINISH); if(res == Z_STREAM_END) /* * Success, return the compressed size. */ return (int) stream->total_out; if(res == Z_OK) /* * Output buffer overflow. Return out of buffer space */ return 0; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error) { int res; unsigned long bytes = block_size; res = uncompress(d, &bytes, s, size); *error = res; return res == Z_OK ? (int) bytes : -1; } struct compressor gzip_comp_ops = { .init = gzip_init, .compress = gzip_compress, .uncompress = gzip_uncompress, .options = NULL, .usage = NULL, .id = ZLIB_COMPRESSION, .name = "gzip", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2-official/lzma_wrapper.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_wrapper.c * * Support for LZMA1 compression using LZMA SDK (4.65 used in * development, other versions may work) http://www.7-zip.org/sdk.html */ #include <LzmaLib.h> #include "squashfs_fs.h" #include "compressor.h" #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) { unsigned char *d = dest; size_t props_size = LZMA_PROPS_SIZE, outlen = block_size - LZMA_HEADER_SIZE; int res; res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest, &props_size, 5, block_size, 3, 0, 2, 32, 1); if(res == SZ_ERROR_OUTPUT_EOF) { /* * Output buffer overflow. Return out of buffer space error */ return 0; } if(res != SZ_OK) { /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } /* * Fill in the 8 byte little endian uncompressed size field in the * LZMA header. 8 bytes is excessively large for squashfs but * this is the standard LZMA header and which is expected by the kernel * code */ d[LZMA_PROPS_SIZE] = size & 255; d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; d[LZMA_PROPS_SIZE + 4] = 0; d[LZMA_PROPS_SIZE + 5] = 0; d[LZMA_PROPS_SIZE + 6] = 0; d[LZMA_PROPS_SIZE + 7] = 0; /* * Success, return the compressed size. Outlen returned by the LZMA * compressor does not include the LZMA header space */ return outlen + LZMA_HEADER_SIZE; } static int lzma_uncompress(void *dest, void *src, int size, int block_size, int *error) { unsigned char *s = src; size_t outlen, inlen = size - LZMA_HEADER_SIZE; int res; outlen = s[LZMA_PROPS_SIZE] | (s[LZMA_PROPS_SIZE + 1] << 8) | (s[LZMA_PROPS_SIZE + 2] << 16) | (s[LZMA_PROPS_SIZE + 3] << 24); res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src, LZMA_PROPS_SIZE); *error = res; return res == SZ_OK ? outlen : -1; } struct compressor lzma_comp_ops = { .init = NULL, .compress = lzma_compress, .uncompress = lzma_uncompress, .options = NULL, .usage = NULL, .id = LZMA_COMPRESSION, .name = "lzma", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2-official/lzma_xz_wrapper.c ================================================ /* * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzma_xz_wrapper.c * * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/ */ #include <stdio.h> #include <string.h> #include <lzma.h> #include "squashfs_fs.h" #include "compressor.h" #define LZMA_PROPS_SIZE 5 #define LZMA_UNCOMP_SIZE 8 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE) #define LZMA_OPTIONS 5 #define MEMLIMIT (32 * 1024 * 1024) static int lzma_compress(void *dummy, void *dest, void *src, int size, int block_size, int *error) { unsigned char *d = (unsigned char *) dest; lzma_options_lzma opt; lzma_stream strm = LZMA_STREAM_INIT; int res; lzma_lzma_preset(&opt, LZMA_OPTIONS); opt.dict_size = block_size; res = lzma_alone_encoder(&strm, &opt); if(res != LZMA_OK) { lzma_end(&strm); goto failed; } strm.next_out = dest; strm.avail_out = block_size; strm.next_in = src; strm.avail_in = size; res = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if(res == LZMA_STREAM_END) { /* * Fill in the 8 byte little endian uncompressed size field in * the LZMA header. 8 bytes is excessively large for squashfs * but this is the standard LZMA header and which is expected by * the kernel code */ d[LZMA_PROPS_SIZE] = size & 255; d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; d[LZMA_PROPS_SIZE + 4] = 0; d[LZMA_PROPS_SIZE + 5] = 0; d[LZMA_PROPS_SIZE + 6] = 0; d[LZMA_PROPS_SIZE + 7] = 0; return (int) strm.total_out; } if(res == LZMA_OK) /* * Output buffer overflow. Return out of buffer space */ return 0; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int lzma_uncompress(void *dest, void *src, int size, int block_size, int *error) { lzma_stream strm = LZMA_STREAM_INIT; int uncompressed_size = 0, res; unsigned char lzma_header[LZMA_HEADER_SIZE]; res = lzma_alone_decoder(&strm, MEMLIMIT); if(res != LZMA_OK) { lzma_end(&strm); goto failed; } memcpy(lzma_header, src, LZMA_HEADER_SIZE); uncompressed_size = lzma_header[LZMA_PROPS_SIZE] | (lzma_header[LZMA_PROPS_SIZE + 1] << 8) | (lzma_header[LZMA_PROPS_SIZE + 2] << 16) | (lzma_header[LZMA_PROPS_SIZE + 3] << 24); memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE); strm.next_out = dest; strm.avail_out = block_size; strm.next_in = lzma_header; strm.avail_in = LZMA_HEADER_SIZE; res = lzma_code(&strm, LZMA_RUN); if(res != LZMA_OK || strm.avail_in != 0) { lzma_end(&strm); goto failed; } strm.next_in = src + LZMA_HEADER_SIZE; strm.avail_in = size - LZMA_HEADER_SIZE; res = lzma_code(&strm, LZMA_FINISH); lzma_end(&strm); if(res == LZMA_STREAM_END || (res == LZMA_OK && strm.total_out >= uncompressed_size && strm.avail_in == 0)) return uncompressed_size; failed: *error = res; return -1; } struct compressor lzma_comp_ops = { .init = NULL, .compress = lzma_compress, .uncompress = lzma_uncompress, .options = NULL, .usage = NULL, .id = LZMA_COMPRESSION, .name = "lzma", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2-official/lzo_wrapper.c ================================================ /* * Copyright (c) 2010 LG Electronics * Chan Jeong <chan.jeong@lge.com> * * All modifications Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * lzo_wrapper.c */ #include <stdlib.h> #include <string.h> #include <lzo/lzoconf.h> #include <lzo/lzo1x.h> #include "squashfs_fs.h" #include "compressor.h" /* worst-case expansion calculation during compression, see LZO FAQ for more information */ #define LZO_OUTPUT_BUFFER_SIZE(size) (size + (size/16) + 64 + 3) struct lzo_stream { lzo_voidp wrkmem; lzo_bytep out; }; static int squashfs_lzo_init(void **strm, int block_size, int flags) { struct lzo_stream *stream; if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL) goto failed; /* work memory for compression */ if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL) goto failed2; /* temporal output buffer */ if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL) goto failed3; return 0; failed3: free(stream->wrkmem); failed2: free(stream); failed: return -1; } static int lzo_compress(void *strm, void *d, void *s, int size, int block_size, int *error) { int res; lzo_uint outlen; struct lzo_stream *stream = strm; res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem); if(res != LZO_E_OK) goto failed; if(outlen >= size) /* * Output buffer overflow. Return out of buffer space */ return 0; /* * Success, return the compressed size. */ memcpy(d, stream->out, outlen); return outlen; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error) { int res; lzo_uint bytes = block_size; res = lzo1x_decompress_safe(s, size, d, &bytes, NULL); *error = res; return res == LZO_E_OK ? bytes : -1; } struct compressor lzo_comp_ops = { .init = squashfs_lzo_init, .compress = lzo_compress, .uncompress = lzo_uncompress, .options = NULL, .usage = NULL, .id = LZO_COMPRESSION, .name = "lzo", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2-official/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <stddef.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/mman.h> #include <pthread.h> #include <math.h> #include <regex.h> #include <fnmatch.h> #include <sys/wait.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #include <sys/sysctl.h> #else #include <endian.h> #include <sys/sysinfo.h> #endif #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ if(progress_enabled) \ printf("\n"); \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) \ do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) \ do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args);\ pthread_mutex_unlock(&progress_mutex); \ } while(0) #define EXIT_MKSQUASHFS() \ do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) \ do {\ pthread_mutex_lock(&progress_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, "FATAL ERROR:" s, ##args);\ pthread_mutex_unlock(&progress_mutex); \ EXIT_MKSQUASHFS();\ } while(0) #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "sort.h" #include "pseudo.h" #include "compressor.h" #include "xattr.h" int delete = FALSE; int fd; int cur_uncompressed = 0, estimated_uncompressed = 0; int columns; /* filesystem flags for building */ int comp_opts = FALSE; int no_xattrs = XATTR_DEF, noX = 0; int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0; int silent = TRUE; long long global_uid = -1, global_gid = -1; int exportable = TRUE; int progress = TRUE; int progress_enabled = FALSE; int sparse_files = TRUE; int old_exclude = TRUE; int use_regex = FALSE; int first_freelist = TRUE; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned int id_count = 0; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* inode lookup table */ squashfs_inode *inode_lookup_table = NULL; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { struct squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536]; int dup_files = 0; /* exclude file handling */ /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int old_excluded(char *filename, struct stat *buf); struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 struct pathnames *paths = NULL; struct pathname *path = NULL; struct pathname *stickypath = NULL; int excluded(struct pathnames *paths, char *name, struct pathnames **new); /* fragment block data structures */ int fragments = 0; struct file_buffer *fragment_data = NULL; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 #define FRAG_INDEX (1LL << 32) struct squashfs_fragment_entry *fragment_table = NULL; int fragments_outstanding = 0; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char *name; struct inode_info inode; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long file_size; long long bytes; unsigned short checksum; unsigned short fragment_checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; char checksum_flag; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* flag if we're restoring existing filesystem */ int restoring = 0; /* restore orignal filesystem state if appending to existing filesystem is * cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache, *sdirectory_compressed; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, sdirectory_compressed_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count = 0, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; int threads; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* recovery file for abnormal exit on appending */ char recovery_file[1024] = ""; int recover = TRUE; /* struct describing a cache entry passed between threads */ struct file_buffer { struct cache *cache; int keep; long long file_size; long long index; long long block; long long sequence; int size; int c_byte; int used; int fragment; int error; struct file_buffer *hash_next; struct file_buffer *hash_prev; struct file_buffer *free_next; struct file_buffer *free_prev; struct file_buffer *next; char data[0]; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* in memory uid tables */ #define ID_ENTRIES 256 #define ID_HASH(id) (id & (ID_ENTRIES - 1)) #define ISA_UID 1 #define ISA_GID 2 struct id { unsigned int id; int index; char flags; struct id *next; }; struct id *id_hash_table[ID_ENTRIES]; struct id *id_table[SQUASHFS_IDS], *sid_table[SQUASHFS_IDS]; unsigned int uid_count = 0, guid_count = 0; unsigned int sid_count = 0, suid_count = 0, sguid_count = 0; struct cache *reader_buffer, *writer_buffer, *fragment_buffer; struct queue *to_reader, *from_reader, *to_writer, *from_writer, *from_deflate, *to_frag; pthread_t *thread, *deflator_thread, *frag_deflator_thread, progress_thread; pthread_mutex_t fragment_mutex; pthread_cond_t fragment_waiting; pthread_mutex_t pos_mutex; pthread_mutex_t progress_mutex; pthread_cond_t progress_wait; int rotate = 0; struct pseudo *pseudo = NULL; /* user options that control parallelisation */ int processors = -1; /* default size of output buffer in Mbytes */ #define WRITER_BUFFER_DEFAULT 512 /* default size of input buffer in Mbytes */ #define READER_BUFFER_DEFAULT 64 /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 64 int writer_buffer_size; /* compression operations */ static struct compressor *comp; int compressor_opts_parsed = 0; void *stream = NULL; /* xattr stats */ unsigned int xattr_bytes = 0, total_xattr_bytes = 0; char *read_from_disk(long long start, unsigned int avail_bytes); void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern struct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source); extern long long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), struct squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table); extern int read_sort_file(char *filename, int source, char *source_path[]); extern void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); struct dir_info *dir_scan1(char *, struct pathnames *, int (_readdir)(char *, char *, struct dir_info *)); struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo); void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info); struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag); extern int generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf); extern struct priority_entry *priority_list[65536]; void progress_bar(long long current, long long max, int columns); long long generic_write_table(int, void *, int, void *, int); void restorefs(); struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) goto failed; queue->data = malloc(sizeof(void *) * (size + 1)); if(queue->data == NULL) { free(queue); goto failed; } queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; failed: BAD_ERROR("Out of memory in queue_init\n"); } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; pthread_mutex_t mutex; pthread_cond_t wait_for_free; struct file_buffer *free_list; struct file_buffer *hash_table[65536]; }; #define INSERT_LIST(NAME, TYPE) \ void insert_##NAME##_list(TYPE **list, TYPE *entry) { \ if(*list) { \ entry->NAME##_next = *list; \ entry->NAME##_prev = (*list)->NAME##_prev; \ (*list)->NAME##_prev->NAME##_next = entry; \ (*list)->NAME##_prev = entry; \ } else { \ *list = entry; \ entry->NAME##_prev = entry->NAME##_next = entry; \ } \ } #define REMOVE_LIST(NAME, TYPE) \ void remove_##NAME##_list(TYPE **list, TYPE *entry) { \ if(entry->NAME##_prev == entry && entry->NAME##_next == entry) { \ /* only this entry in the list */ \ *list = NULL; \ } else if(entry->NAME##_prev != NULL && entry->NAME##_next != NULL) { \ /* more than one entry in the list */ \ entry->NAME##_next->NAME##_prev = entry->NAME##_prev; \ entry->NAME##_prev->NAME##_next = entry->NAME##_next; \ if(*list == entry) \ *list = entry->NAME##_next; \ } \ entry->NAME##_prev = entry->NAME##_next = NULL; \ } #define CALCULATE_HASH(start) (start & 0xffff) \ /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct file_buffer *entry) { int hash = CALCULATE_HASH(entry->index); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct file_buffer *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->index)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ INSERT_LIST(free, struct file_buffer) /* Called with the cache mutex held */ REMOVE_LIST(free, struct file_buffer) struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) BAD_ERROR("Out of memory in cache_init\n"); cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct file_buffer *) * 65536); pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); return cache; } struct file_buffer *cache_lookup(struct cache *cache, long long index) { /* Lookup block in the cache, if found return with usage count * incremented, if not found return NULL */ int hash = CALCULATE_HASH(index); struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->index == index) break; if(entry) { /* found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(&cache->free_list, entry); } pthread_mutex_unlock(&cache->mutex); return entry; } struct file_buffer *cache_get(struct cache *cache, long long index, int keep) { /* Get a free block out of the cache indexed on index. */ struct file_buffer *entry; pthread_mutex_lock(&cache->mutex); while(1) { /* first try to get a block from the free list */ if(first_freelist && cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else if(cache->count < cache->max_buffers) { /* next try to allocate new block */ entry = malloc(sizeof(struct file_buffer) + cache->buffer_size); if(entry == NULL) goto failed; entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; break; } else if(!first_freelist && cache->free_list) { /* a block on the free_list is a "keep" block */ entry = cache->free_list; remove_free_list(&cache->free_list, entry); remove_hash_table(cache, entry); break; } else /* wait for a block */ pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } /* initialise block and if a keep block insert into the hash table */ entry->used = 1; entry->error = FALSE; entry->keep = keep; if(keep) { entry->index = index; insert_hash_table(cache, entry); } pthread_mutex_unlock(&cache->mutex); return entry; failed: pthread_mutex_unlock(&cache->mutex); BAD_ERROR("Out of memory in cache_get\n"); } void cache_rehash(struct file_buffer *entry, long long index) { struct cache *cache = entry->cache; pthread_mutex_lock(&cache->mutex); if(entry->keep) remove_hash_table(cache, entry); entry->keep = TRUE; entry->index = index; insert_hash_table(cache, entry); pthread_mutex_unlock(&cache->mutex); } void cache_block_put(struct file_buffer *entry) { struct cache *cache; /* finished with this cache entry, once the usage count reaches zero it * can be reused and if a keep block put onto the free list. As keep * blocks remain accessible via the hash table they can be found * getting a new lease of life before they are reused. */ if(entry == NULL) return; cache = entry->cache; pthread_mutex_lock(&cache->mutex); entry->used --; if(entry->used == 0) { if(entry->keep) insert_free_list(&cache->free_list, entry); else { free(entry); cache->count --; } /* One or more threads may be waiting on this block */ pthread_cond_signal(&cache->wait_for_free); } pthread_mutex_unlock(&cache->mutex); } #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) \ + (((char *)A) - data_cache))) inline void inc_progress_bar() { cur_uncompressed ++; } inline void update_progress_bar() { pthread_mutex_lock(&progress_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&progress_mutex); } inline void waitforthread(int i) { TRACE("Waiting for thread %d\n", i); while(thread[i] != 0) sched_yield(); } void restorefs() { int i; if(thread == NULL || thread[0] == 0) return; if(restoring++) /* * Recursive failure when trying to restore filesystem! * Nothing to do except to exit, otherwise we'll just appear * to hang. The user should be able to restore from the * recovery file (which is why it was added, in case of * catastrophic failure in Mksquashfs) */ exit(1); ERROR("Exiting - restoring original filesystem!\n\n"); for(i = 0; i < 2 + processors * 2; i++) if(thread[i]) pthread_kill(thread[i], SIGUSR1); for(i = 0; i < 2 + processors * 2; i++) waitforthread(i); TRACE("All threads in signal handler\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, sdirectory_cache_bytes); directory_cache_bytes = sdirectory_cache_bytes; inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; memcpy(directory_table + directory_bytes, sdirectory_compressed, sdirectory_compressed_bytes); directory_bytes += sdirectory_compressed_bytes; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; id_count = sid_count; restore_xattrs(); longjmp(env, 1); } void sighandler() { if(++interrupted > 2) return; if(interrupted == 2) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); } } void sighandler2() { EXIT_MKSQUASHFS(); } void sigusr1_handler() { int i; sigset_t sigmask; pthread_t thread_id = pthread_self(); for(i = 0; i < (2 + processors * 2) && thread[i] != thread_id; i++); thread[i] = (pthread_t) 0; TRACE("Thread %d(%p) in sigusr1_handler\n", i, &thread_id); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); sigaddset(&sigmask, SIGUSR1); while(1) { sigsuspend(&sigmask); TRACE("After wait in sigusr1_handler :(\n"); } } void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } int mangle2(void *strm, char *d, char *s, int size, int block_size, int uncompressed, int data_block) { int error, c_byte = 0; if(!uncompressed) { c_byte = compressor_compress(comp, strm, d, s, size, block_size, &error); if(c_byte == -1) BAD_ERROR("mangle2:: %s compress failed with error " "code %d\n", comp->name, error); } if(c_byte == 0 || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return c_byte; } int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { return mangle2(stream, d, s, size, block_size, uncompressed, data_block); } void *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { void *it = realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(it == NULL) { goto failed; } inode_table = it; inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; void *dc = realloc(data_cache, cache_size + realloc_size); if(dc == NULL) { goto failed; } cache_size += realloc_size; data_cache = dc; } cache_bytes += req_size; return data_cache + cache_bytes - req_size; failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } int read_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) goto bytes_read; else if(errno != EINTR) { ERROR("Read failed because %s\n", strerror(errno)); return -1; } else res = 0; } } bytes_read: return count; } int read_fs_bytes(int fd, long long byte, int bytes, void *buff) { off_t off = byte; TRACE("read_fs_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); goto failed; } if(read_bytes(fd, buff, bytes) < bytes) { ERROR("Read on destination failed\n"); goto failed; } pthread_mutex_unlock(&pos_mutex); return 1; failed: pthread_mutex_unlock(&pos_mutex); return 0; } int write_bytes(int fd, void *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write failed because %s\n", strerror(errno)); return -1; } res = 0; } } return 0; } void write_destination(int fd, long long byte, int bytes, void *buff) { off_t off = byte; if(!restoring) pthread_mutex_lock(&pos_mutex); if(lseek(fd, off, SEEK_SET) == -1) BAD_ERROR("Lseek on destination failed because %s\n", strerror(errno)); if(write_bytes(fd, buff, bytes) == -1) BAD_ERROR("Write on destination failed\n"); if(!restoring) pthread_mutex_unlock(&pos_mutex); } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *it = realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(it == NULL) { BAD_ERROR("Out of memory in inode table " "reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; inode_table = it; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ 0x%x, size %d\n", inode_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, inode_table + inode_bytes, 1); inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_inode_bytes += avail_bytes + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } write_destination(fd, bytes, inode_bytes, inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *dt = realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2)); if(dt == NULL) { BAD_ERROR("Out of memory in directory table " "reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; directory_table = dt; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += avail_bytes + BLOCK_OFFSET; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_destination(fd, bytes, directory_bytes, directory_table); bytes += directory_bytes; return start_bytes; } long long write_id_table() { unsigned int id_bytes = SQUASHFS_ID_BYTES(id_count); unsigned int p[id_count]; int i; TRACE("write_id_table: ids %d, id_bytes %d\n", id_count, id_bytes); for(i = 0; i < id_count; i++) { TRACE("write_id_table: id index %d, id %d", i, id_table[i]->id); SQUASHFS_SWAP_INTS(&id_table[i]->id, p + i, 1); } return generic_write_table(id_bytes, p, 0, NULL, noI); } struct id *get_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = id_hash_table[hash]; for(; entry; entry = entry->next) if(entry->id == id) break; return entry; } struct id *create_id(unsigned int id) { int hash = ID_HASH(id); struct id *entry = malloc(sizeof(struct id)); if(entry == NULL) BAD_ERROR("Out of memory in create_id\n"); entry->id = id; entry->index = id_count ++; entry->flags = 0; entry->next = id_hash_table[hash]; id_hash_table[hash] = entry; id_table[entry->index] = entry; return entry; } unsigned int get_uid(unsigned int uid) { struct id *entry = get_id(uid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of uids!\n"); entry = create_id(uid); } if((entry->flags & ISA_UID) == 0) { entry->flags |= ISA_UID; uid_count ++; } return entry->index; } unsigned int get_guid(unsigned int guid) { struct id *entry = get_id(guid); if(entry == NULL) { if(id_count == SQUASHFS_IDS) BAD_ERROR("Out of gids!\n"); entry = create_id(guid); } if((entry->flags & ISA_GID) == 0) { entry->flags |= ISA_GID; guid_count ++; } return entry->index; } int create_inode(squashfs_inode *i_no, struct dir_info *dir_info, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in, long long sparse) { struct stat *buf = &dir_ent->inode->buf; union squashfs_inode_header inode_header; struct squashfs_base_inode_header *base = &inode_header.base; void *inode; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = type == SQUASHFS_DIR_TYPE ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; int xattr = read_xattrs(dir_ent); switch(type) { case SQUASHFS_FILE_TYPE: if(dir_ent->inode->nlink > 1 || byte_size >= (1LL << 32) || start_block >= (1LL << 32) || sparse || IS_XATTR(xattr)) type = SQUASHFS_LREG_TYPE; break; case SQUASHFS_DIR_TYPE: if(dir_info->dir_is_ldir || IS_XATTR(xattr)) type = SQUASHFS_LDIR_TYPE; break; case SQUASHFS_SYMLINK_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LSYMLINK_TYPE; break; case SQUASHFS_BLKDEV_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LBLKDEV_TYPE; break; case SQUASHFS_CHRDEV_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LCHRDEV_TYPE; break; case SQUASHFS_FIFO_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LFIFO_TYPE; break; case SQUASHFS_SOCKET_TYPE: if(IS_XATTR(xattr)) type = SQUASHFS_LSOCKET_TYPE; break; } base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((unsigned int) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((unsigned int) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; struct squashfs_reg_inode_header *reg = &inode_header.reg; size_t off = offsetof(struct squashfs_reg_inode_header, block_list); inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; SQUASHFS_SWAP_REG_INODE_HEADER(reg, inode); SQUASHFS_SWAP_INTS(block_list, inode + off, offset); TRACE("File inode, file_size %lld, start_block 0x%llx, blocks " "%d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; struct squashfs_lreg_inode_header *reg = &inode_header.lreg; size_t off = offsetof(struct squashfs_lreg_inode_header, block_list); inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(sparse && sparse >= byte_size) sparse = byte_size - 1; reg->sparse = sparse; reg->xattr = xattr; SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inode); SQUASHFS_SWAP_INTS(block_list, inode + off, offset); TRACE("Long file inode, file_size %lld, start_block 0x%llx, " "blocks %d, fragment %d, offset %d, size %d, nlink %d" "\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; struct squashfs_ldir_inode_header *dir = &inode_header.ldir; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; dir->xattr = xattr; SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = inode + offsetof(struct squashfs_ldir_inode_header, index); for(i = 0; i < i_count; i++) { SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); p += offsetof(struct squashfs_dir_index, name); memcpy(p, index[i].name, index[i].index.size + 1); p += index[i].index.size + 1; } TRACE("Long directory inode, file_size %lld, start_block " "0x%llx, offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { struct squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %lld, start_block 0x%llx, " "offset 0x%x, nlink %d\n", byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { struct squashfs_dev_inode_header *dev = &inode_header.dev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_LCHRDEV_TYPE || type == SQUASHFS_LBLKDEV_TYPE) { struct squashfs_ldev_inode_header *dev = &inode_header.ldev; unsigned int major = major(buf->st_rdev); unsigned int minor = minor(buf->st_rdev); if(major > 0xfff) { ERROR("Major %d out of range in device node %s, " "truncating to %d\n", major, filename, major & 0xfff); major &= 0xfff; } if(minor > 0xfffff) { ERROR("Minor %d out of range in device node %s, " "truncating to %d\n", minor, filename, minor & 0xfffff); minor &= 0xfffff; } inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (major << 8) | (minor & 0xff) | ((minor & ~0xff) << 12); dev->xattr = xattr; SQUASHFS_SWAP_LDEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev 0x%x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { struct squashfs_symlink_inode_header *symlink = &inode_header.symlink; int byte; char buff[65536]; size_t off = offsetof(struct squashfs_symlink_inode_header, symlink); byte = readlink(filename, buff, 65536); if(byte == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inode + off, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_LSYMLINK_TYPE) { struct squashfs_symlink_inode_header *symlink = &inode_header.symlink; int byte; char buff[65536]; size_t off = offsetof(struct squashfs_symlink_inode_header, symlink); byte = readlink(filename, buff, 65536); if(byte == -1) { ERROR("Failed to read symlink %s, creating empty " "symlink\n", filename); byte = 0; } if(byte == 65536) { ERROR("Symlink %s is greater than 65536 bytes! " "Creating empty symlink\n", filename); byte = 0; } inode = get_inode(sizeof(*symlink) + byte + sizeof(unsigned int)); symlink->nlink = nlink; symlink->symlink_size = byte; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inode + off, buff, byte); SQUASHFS_SWAP_INTS(&xattr, inode + off + byte, 1); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { struct squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else if(type == SQUASHFS_LFIFO_TYPE || type == SQUASHFS_LSOCKET_TYPE) { struct squashfs_lipc_inode_header *ipc = &inode_header.lipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; ipc->xattr = xattr; SQUASHFS_SWAP_LIPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else BAD_ERROR("Unrecognised inode %d in create_inode\n", type); *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan3_init_dir(struct directory *dir) { dir->buff = malloc(SQUASHFS_METADATA_SIZE); if(dir->buff == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; struct squashfs_dir_entry idir; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size = strlen(name); size_t name_off = offsetof(struct squashfs_dir_entry, name); if(size > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ..." "\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(struct squashfs_dir_entry) + size + sizeof(struct squashfs_dir_header) >= dir->buff + dir->size) { buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE); if(buff == NULL) { BAD_ERROR("Out of memory reallocating directory buffer" "\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(struct squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < -32768) { if(dir->entry_count_p) { struct squashfs_dir_header dir_header; if((dir->p + sizeof(struct squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) { dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index)); if(dir->index == NULL) BAD_ERROR("Out of memory in " "directory index table " "reallocation!\n"); } dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(struct squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(struct squashfs_dir_header); } idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); SQUASHFS_SWAP_DIR_ENTRY(&idir, dir->p); strncpy((char *) dir->p + name_off, name, size); dir->p += sizeof(struct squashfs_dir_entry) + size; dir->entry_count ++; } void write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = directory_cache_size - directory_cache_bytes; unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; void *dc = realloc(directory_data_cache, directory_cache_size + realloc_size); if(dc == NULL) { goto failed; } directory_cache_size += realloc_size; directory_data_cache = dc; } if(dir_size) { struct squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; SQUASHFS_SWAP_DIR_HEADER(&dir_header, dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { void *dt = realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(dt == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; directory_table = dt; } c_byte = mangle(directory_table + directory_bytes + BLOCK_OFFSET, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ 0x%x, size %d\n", directory_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, directory_table + directory_bytes, 1); directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; total_directory_bytes += SQUASHFS_METADATA_SIZE + BLOCK_OFFSET; memmove(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } create_inode(inode, dir_info, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir, 0); #ifdef SQUASHFS_TRACE { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; struct squashfs_dir_entry idir, *idirp; struct squashfs_dir_header dirh; SQUASHFS_SWAP_DIR_HEADER((struct squashfs_dir_header *) dirp, &dirh); count = dirh.count + 1; dirp += sizeof(struct squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh.start_block, count); while(count--) { idirp = (struct squashfs_dir_entry *) dirp; SQUASHFS_SWAP_DIR_ENTRY(idirp, &idir); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type " "%d\n", buffer, idir.offset, idir.type); dirp += sizeof(struct squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } struct file_buffer *get_fragment(struct fragment *fragment) { struct squashfs_fragment_entry *disk_fragment; int res, size; long long start_block; struct file_buffer *buffer, *compressed_buffer; if(fragment->index == SQUASHFS_INVALID_FRAG) return NULL; buffer = cache_lookup(fragment_buffer, fragment->index); if(buffer) return buffer; compressed_buffer = cache_lookup(writer_buffer, fragment->index + FRAG_INDEX); buffer = cache_get(fragment_buffer, fragment->index, 1); pthread_mutex_lock(&fragment_mutex); disk_fragment = &fragment_table[fragment->index]; size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); start_block = disk_fragment->start_block; pthread_mutex_unlock(&fragment_mutex); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int error; char *data; if(compressed_buffer) data = compressed_buffer->data; else data = read_from_disk(start_block, size); res = compressor_uncompress(comp, buffer->data, data, size, block_size, &error); if(res == -1) BAD_ERROR("%s uncompress failed with error code %d\n", comp->name, error); } else if(compressed_buffer) memcpy(buffer->data, compressed_buffer->data, size); else { res = read_fs_bytes(fd, start_block, size, buffer->data); if(res == 0) EXIT_MKSQUASHFS(); } cache_block_put(compressed_buffer); return buffer; } struct frag_locked { struct file_buffer *buffer; int c_byte; int fragment; struct frag_locked *fragment_prev; struct frag_locked *fragment_next; }; int fragments_locked = FALSE; struct frag_locked *frag_locked_list = NULL; INSERT_LIST(fragment, struct frag_locked) REMOVE_LIST(fragment, struct frag_locked) int lock_fragments() { int count; pthread_mutex_lock(&fragment_mutex); fragments_locked = TRUE; count = fragments_outstanding; pthread_mutex_unlock(&fragment_mutex); return count; } void unlock_fragments() { struct frag_locked *entry; int compressed_size; pthread_mutex_lock(&fragment_mutex); while(frag_locked_list) { entry = frag_locked_list; remove_fragment_list(&frag_locked_list, entry); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->c_byte); fragment_table[entry->fragment].size = entry->c_byte; fragment_table[entry->fragment].start_block = bytes; entry->buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, entry->buffer); TRACE("fragment_locked writing fragment %d, compressed size %d" "\n", entry->fragment, compressed_size); free(entry); } fragments_locked = FALSE; pthread_mutex_unlock(&fragment_mutex); } void add_pending_fragment(struct file_buffer *write_buffer, int c_byte, int fragment) { struct frag_locked *entry = malloc(sizeof(struct frag_locked)); if(entry == NULL) BAD_ERROR("Out of memory in add_pending fragment\n"); entry->buffer = write_buffer; entry->c_byte = c_byte; entry->fragment = fragment; entry->fragment_prev = entry->fragment_next = NULL; pthread_mutex_lock(&fragment_mutex); insert_fragment_list(&frag_locked_list, entry); pthread_mutex_unlock(&fragment_mutex); } void write_fragment() { if(fragment_size == 0) return; pthread_mutex_lock(&fragment_mutex); if(fragments % FRAG_SIZE == 0) { void *ft = realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(struct squashfs_fragment_entry)); if(ft == NULL) { pthread_mutex_unlock(&fragment_mutex); BAD_ERROR("Out of memory in fragment table\n"); } fragment_table = ft; } fragment_data->size = fragment_size; fragment_data->block = fragments; fragment_table[fragments].unused = 0; fragments_outstanding ++; queue_put(to_frag, fragment_data); fragments ++; fragment_size = 0; pthread_mutex_unlock(&fragment_mutex); } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(struct file_buffer *file_buffer) { struct fragment *ffrg; if(file_buffer == NULL || file_buffer->size == 0) return &empty_fragment; if(fragment_size + file_buffer->size > block_size) write_fragment(); ffrg = malloc(sizeof(struct fragment)); if(ffrg == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); if(fragment_size == 0) fragment_data = cache_get(fragment_buffer, fragments, 1); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = file_buffer->size; memcpy(fragment_data->data + fragment_size, file_buffer->data, file_buffer->size); fragment_size += file_buffer->size; return ffrg; } long long generic_write_table(int length, void *buffer, int length2, void *buffer2, int uncompressed) { int meta_blocks = (length + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE; long long list[meta_blocks], start_bytes; int compressed_size, i; unsigned short c_byte; char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; #ifdef SQUASHFS_TRACE long long obytes = bytes; int olength = length; #endif for(i = 0; i < meta_blocks; i++) { int avail_bytes = length > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : length; c_byte = mangle(cbuffer + BLOCK_OFFSET, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, uncompressed, 0); SQUASHFS_SWAP_SHORTS(&c_byte, cbuffer, 1); list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; TRACE("block %d @ 0x%llx, compressed size %d\n", i, bytes, compressed_size); write_destination(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; total_bytes += avail_bytes; length -= avail_bytes; } start_bytes = bytes; if(length2) { write_destination(fd, bytes, length2, buffer2); bytes += length2; total_bytes += length2; } SQUASHFS_INSWAP_LONG_LONGS(list, meta_blocks); write_destination(fd, bytes, sizeof(list), list); bytes += sizeof(list); total_bytes += sizeof(list); TRACE("generic_write_table: total uncompressed %d compressed %lld\n", olength, bytes - obytes); return start_bytes; } long long write_fragment_table() { unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments); struct squashfs_fragment_entry p[fragments]; int i; TRACE("write_fragment_table: fragments %d, frag_bytes %d\n", fragments, frag_bytes); for(i = 0; i < fragments; i++) { TRACE("write_fragment_table: fragment %d, start_block 0x%llx, " "size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p + i); } return generic_write_table(frag_bytes, p, 0, NULL, noF); } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk(long long start, unsigned int avail_bytes) { int res; res = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer); if(res == 0) EXIT_MKSQUASHFS(); return read_from_file_buffer; } char read_from_file_buffer2[SQUASHFS_FILE_MAX_SIZE]; char *read_from_disk2(long long start, unsigned int avail_bytes) { int res; res = read_fs_bytes(fd, start, avail_bytes, read_from_file_buffer2); if(res == 0) EXIT_MKSQUASHFS(); return read_from_file_buffer2; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *buff, int bytes, unsigned short chksum) { unsigned char *b = (unsigned char *) buff; while(bytes --) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } return chksum; } unsigned short get_checksum_disk(long long start, long long l, unsigned int *blocks) { unsigned short chksum = 0; unsigned int bytes; struct file_buffer *write_buffer; int i; for(i = 0; l; i++) { bytes = SQUASHFS_COMPRESSED_SIZE_BLOCK(blocks[i]); if(bytes == 0) /* sparse block */ continue; write_buffer = cache_lookup(writer_buffer, start); if(write_buffer) { chksum = get_checksum(write_buffer->data, bytes, chksum); cache_block_put(write_buffer); } else chksum = get_checksum(read_from_disk(start, bytes), bytes, chksum); l -= bytes; start += bytes; } return chksum; } unsigned short get_checksum_mem(char *buff, int bytes) { return get_checksum(buff, bytes, 0); } unsigned short get_checksum_mem_buffer(struct file_buffer *file_buffer) { if(file_buffer == NULL) return 0; else return get_checksum(file_buffer->data, file_buffer->size, 0); } #define DUP_HASH(a) (a & 0xffff) void add_file(long long start, long long file_size, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; unsigned int *block_list = block_listp; struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; if(!duplicate_checking || file_size == 0) return; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) { if(file_size != dupl_ptr->file_size) continue; if(blocks != 0 && start != dupl_ptr->start) continue; if(fragment != dupl_ptr->fragment->index) continue; if(fragment != SQUASHFS_INVALID_FRAG && (offset != dupl_ptr->fragment->offset || bytes != dupl_ptr->fragment->size)) continue; return; } frg = malloc(sizeof(struct fragment)); if(frg == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; add_non_dup(file_size, file_bytes, block_list, start, frg, 0, 0, FALSE); } int pre_duplicate(long long file_size) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(dupl_ptr->file_size == file_size) return TRUE; return FALSE; } int pre_duplicate_frag(long long file_size, unsigned short checksum) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && file_size == dupl_ptr->fragment->size) { if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, file_size); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(dupl_ptr->fragment_checksum == checksum) return TRUE; } return FALSE; } struct file_info *add_non_dup(long long file_size, long long bytes, unsigned int *block_list, long long start, struct fragment *fragment, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = malloc(sizeof(struct file_info)); if(dupl_ptr == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->file_size = file_size; dupl_ptr->bytes = bytes; dupl_ptr->block_list = block_list; dupl_ptr->start = start; dupl_ptr->fragment = fragment; dupl_ptr->checksum = checksum; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->checksum_flag = checksum_flag; dupl_ptr->next = dupl[DUP_HASH(file_size)]; dupl[DUP_HASH(file_size)] = dupl_ptr; dup_files ++; return dupl_ptr; } struct file_info *duplicate(long long file_size, long long bytes, unsigned int **block_list, long long *start, struct fragment **fragment, struct file_buffer *file_buffer, int blocks, unsigned short checksum, unsigned short fragment_checksum, int checksum_flag) { struct file_info *dupl_ptr = dupl[DUP_HASH(file_size)]; int frag_bytes = file_buffer ? file_buffer->size : 0; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(file_size == dupl_ptr->file_size && bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size) { long long target_start, dup_start = dupl_ptr->start; int block; if(memcmp(*block_list, dupl_ptr->block_list, blocks * sizeof(unsigned int)) != 0) continue; if(checksum_flag == FALSE) { checksum = get_checksum_disk(*start, bytes, *block_list); fragment_checksum = get_checksum_mem_buffer(file_buffer); checksum_flag = TRUE; } if(dupl_ptr->checksum_flag == FALSE) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); dupl_ptr->checksum = get_checksum_disk(dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->block_list); dupl_ptr->fragment_checksum = get_checksum_mem(frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes); cache_block_put(frag_buffer); dupl_ptr->checksum_flag = TRUE; } if(checksum != dupl_ptr->checksum || fragment_checksum != dupl_ptr->fragment_checksum) continue; target_start = *start; for(block = 0; block < blocks; block ++) { int size = SQUASHFS_COMPRESSED_SIZE_BLOCK ((*block_list)[block]); struct file_buffer *target_buffer = NULL; struct file_buffer *dup_buffer = NULL; char *target_data, *dup_data; int res; if(size == 0) continue; target_buffer = cache_lookup(writer_buffer, target_start); if(target_buffer) target_data = target_buffer->data; else target_data = read_from_disk(target_start, size); dup_buffer = cache_lookup(writer_buffer, dup_start); if(dup_buffer) dup_data = dup_buffer->data; else dup_data = read_from_disk2(dup_start, size); res = memcmp(target_data, dup_data, size); cache_block_put(target_buffer); cache_block_put(dup_buffer); if(res != 0) break; target_start += size; dup_start += size; } if(block == blocks) { struct file_buffer *frag_buffer = get_fragment(dupl_ptr->fragment); if(frag_bytes == 0 || memcmp(file_buffer->data, frag_buffer->data + dupl_ptr->fragment->offset, frag_bytes) == 0) { TRACE("Found duplicate file, start " "0x%llx, size %lld, checksum " "0x%x, fragment %d, size %d, " "offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; cache_block_put(frag_buffer); return 0; } cache_block_put(frag_buffer); } } return add_non_dup(file_size, bytes, *block_list, *start, *fragment, checksum, fragment_checksum, checksum_flag); } static int seq = 0; void reader_read_process(struct dir_ent *dir_ent) { struct file_buffer *prev_buffer = NULL, *file_buffer; int status, res, byte, count = 0; int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; long long bytes = 0; while(1) { file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; byte = read_bytes(file, file_buffer->data, block_size); if(byte == -1) goto read_err; file_buffer->size = byte; file_buffer->file_size = -1; file_buffer->block = count ++; file_buffer->error = FALSE; file_buffer->fragment = FALSE; bytes += byte; if(byte == 0) break; /* * Update estimated_uncompressed block count. This is done * on every block rather than waiting for all blocks to be * read incase write_file_process() is running in parallel * with this. Otherwise cur uncompressed block count may * get ahead of the total uncompressed block count. */ estimated_uncompressed ++; if(prev_buffer) queue_put(from_reader, prev_buffer); prev_buffer = file_buffer; } /* * Update inode file size now that the size of the dynamic pseudo file * is known. This is needed for the -info option. */ dir_ent->inode->buf.st_size = bytes; res = waitpid(child, &status, 0); if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) goto read_err; if(prev_buffer == NULL) prev_buffer = file_buffer; else { cache_block_put(file_buffer); seq --; } prev_buffer->file_size = bytes; prev_buffer->fragment = !no_fragments && (count == 2 || always_use_fragments) && (byte < block_size); queue_put(from_reader, prev_buffer); return; read_err: if(prev_buffer) { cache_block_put(file_buffer); seq --; file_buffer = prev_buffer; } file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_read_file(struct dir_ent *dir_ent) { struct stat *buf = &dir_ent->inode->buf, buf2; struct file_buffer *file_buffer; int blocks, byte, count, expected, file, frag_block; long long bytes, read_size; if(dir_ent->inode->read) return; dir_ent->inode->read = TRUE; again: bytes = 0; count = 0; file_buffer = NULL; read_size = buf->st_size; blocks = (read_size + block_size - 1) >> block_log; frag_block = !no_fragments && (always_use_fragments || (read_size < block_size)) ? read_size >> block_log : -1; file = open(dir_ent->pathname, O_RDONLY); if(file == -1) { file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; goto read_err; } do { expected = read_size - ((long long) count * block_size) > block_size ? block_size : read_size - ((long long) count * block_size); if(file_buffer) queue_put(from_reader, file_buffer); file_buffer = cache_get(reader_buffer, 0, 0); file_buffer->sequence = seq ++; /* * Always try to read block_size bytes from the file rather * than expected bytes (which will be less than the block_size * at the file tail) to check that the file hasn't grown * since being stated. If it is longer (or shorter) than * expected, then restat, and try again. Note the special * case where the file is an exact multiple of the block_size * is dealt with later. */ byte = file_buffer->size = read_bytes(file, file_buffer->data, block_size); file_buffer->file_size = read_size; if(byte == -1) goto read_err; if(byte != expected) goto restat; file_buffer->block = count; file_buffer->error = FALSE; file_buffer->fragment = (file_buffer->block == frag_block); bytes += byte; count ++; } while(count < blocks); if(read_size != bytes) goto restat; if(expected == block_size) { /* * Special case where we've not tried to read past the end of * the file. We expect to get EOF, i.e. the file isn't larger * than we expect. */ char buffer; int res; res = read_bytes(file, &buffer, 1); if(res == -1) goto read_err; if(res != 0) goto restat; } queue_put(from_reader, file_buffer); close(file); return; restat: fstat(file, &buf2); close(file); if(read_size != buf2.st_size) { memcpy(buf, &buf2, sizeof(struct stat)); file_buffer->error = 2; queue_put(from_deflate, file_buffer); goto again; } read_err: file_buffer->error = TRUE; queue_put(from_deflate, file_buffer); } void reader_scan(struct dir_info *dir) { int i; for(i = 0; i < dir->count; i++) { struct dir_ent *dir_ent = dir->list[i]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; if(IS_PSEUDO_PROCESS(dir_ent->inode)) { reader_read_process(dir_ent); continue; } switch(buf->st_mode & S_IFMT) { case S_IFREG: reader_read_file(dir_ent); break; case S_IFDIR: reader_scan(dir_ent->dir); break; } } } void *reader(void *arg) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); if(!sorted) reader_scan(queue_get(to_reader)); else { int i; struct priority_entry *entry; queue_get(to_reader); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) reader_read_file(entry->dir); } thread[0] = 0; pthread_exit(NULL); } void *writer(void *arg) { int write_error = FALSE; int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); while(1) { struct file_buffer *file_buffer = queue_get(to_writer); off_t off; if(file_buffer == NULL) { queue_put(from_writer, write_error ? &write_error : NULL); continue; } off = file_buffer->block; pthread_mutex_lock(&pos_mutex); if(!write_error && lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek on destination failed because %s\n", strerror(errno)); write_error = TRUE; } if(!write_error && write_bytes(fd, file_buffer->data, file_buffer->size) == -1) { ERROR("Write on destination failed because %s\n", strerror(errno)); write_error = TRUE; } pthread_mutex_unlock(&pos_mutex); cache_block_put(file_buffer); } } int all_zero(struct file_buffer *file_buffer) { int i; long entries = file_buffer->size / sizeof(long); long *p = (long *) file_buffer->data; for(i = 0; i < entries && p[i] == 0; i++); if(i == entries) { for(i = file_buffer->size & ~(sizeof(long) - 1); i < file_buffer->size && file_buffer->data[i] == 0; i++); return i == file_buffer->size; } return 0; } void *deflator(void *arg) { void *stream = NULL; int res, oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); res = compressor_init(comp, &stream, block_size, 1); if(res) BAD_ERROR("deflator:: compressor_init failed\n"); while(1) { struct file_buffer *file_buffer = queue_get(from_reader); struct file_buffer *write_buffer; if(sparse_files && all_zero(file_buffer)) { file_buffer->c_byte = 0; queue_put(from_deflate, file_buffer); } else if(file_buffer->fragment) { file_buffer->c_byte = file_buffer->size; queue_put(from_deflate, file_buffer); } else { write_buffer = cache_get(writer_buffer, 0, 0); write_buffer->c_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noD, 1); write_buffer->sequence = file_buffer->sequence; write_buffer->file_size = file_buffer->file_size; write_buffer->block = file_buffer->block; write_buffer->size = SQUASHFS_COMPRESSED_SIZE_BLOCK (write_buffer->c_byte); write_buffer->fragment = FALSE; write_buffer->error = FALSE; cache_block_put(file_buffer); queue_put(from_deflate, write_buffer); } } } void *frag_deflator(void *arg) { void *stream = NULL; int res, oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); res = compressor_init(comp, &stream, block_size, 1); if(res) BAD_ERROR("frag_deflator:: compressor_init failed\n"); while(1) { int c_byte, compressed_size; struct file_buffer *file_buffer = queue_get(to_frag); struct file_buffer *write_buffer = cache_get(writer_buffer, file_buffer->block + FRAG_INDEX, 1); c_byte = mangle2(stream, write_buffer->data, file_buffer->data, file_buffer->size, block_size, noF, 1); compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); write_buffer->size = compressed_size; pthread_mutex_lock(&fragment_mutex); if(fragments_locked == FALSE) { fragment_table[file_buffer->block].size = c_byte; fragment_table[file_buffer->block].start_block = bytes; write_buffer->block = bytes; bytes += compressed_size; fragments_outstanding --; queue_put(to_writer, write_buffer); pthread_mutex_unlock(&fragment_mutex); TRACE("Writing fragment %lld, uncompressed size %d, " "compressed size %d\n", file_buffer->block, file_buffer->size, compressed_size); } else { pthread_mutex_unlock(&fragment_mutex); add_pending_fragment(write_buffer, c_byte, file_buffer->block); } cache_block_put(file_buffer); } } #define HASH_ENTRIES 256 #define BLOCK_HASH(a) (a % HASH_ENTRIES) struct file_buffer *block_hash[HASH_ENTRIES]; void push_buffer(struct file_buffer *file_buffer) { int hash = BLOCK_HASH(file_buffer->sequence); file_buffer->next = block_hash[hash]; block_hash[hash] = file_buffer; } struct file_buffer *get_file_buffer(struct queue *queue) { static unsigned int sequence = 0; int hash = BLOCK_HASH(sequence); struct file_buffer *file_buffer = block_hash[hash], *prev = NULL; for(;file_buffer; prev = file_buffer, file_buffer = file_buffer->next) if(file_buffer->sequence == sequence) break; if(file_buffer) { if(prev) prev->next = file_buffer->next; else block_hash[hash] = file_buffer->next; } else { while(1) { file_buffer = queue_get(queue); if(file_buffer->sequence == sequence) break; push_buffer(file_buffer); } } sequence ++; return file_buffer; } void *progress_thrd(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) printf("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&progress_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &progress_mutex, ×pec); if(progress_enabled && estimated_uncompressed) progress_bar(cur_uncompressed, estimated_uncompressed, columns); } } void enable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&progress_mutex); } void disable_progress_bar() { pthread_mutex_lock(&progress_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&progress_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits, used, hashes, spaces; static int tty = -1; if(max == 0) return; max_digits = floor(log10(max)) + 1; used = max_digits * 2 + 11; hashes = (current * (columns - used)) / max; spaces = columns - used - hashes; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } void write_file_empty(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { file_count ++; *duplicate_file = FALSE; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, 0, 0, 0, NULL, &empty_fragment, NULL, 0); } void write_file_frag_dup(squashfs_inode *inode, struct dir_ent *dir_ent, int size, int *duplicate_file, struct file_buffer *file_buffer, unsigned short checksum) { struct file_info *dupl_ptr; struct fragment *fragment; unsigned int *block_listp = NULL; long long start = 0; dupl_ptr = duplicate(size, 0, &block_listp, &start, &fragment, file_buffer, 0, 0, checksum, TRUE); if(dupl_ptr) { *duplicate_file = FALSE; fragment = get_and_fill_fragment(file_buffer); dupl_ptr->fragment = fragment; } else *duplicate_file = TRUE; cache_block_put(file_buffer); total_bytes += size; file_count ++; inc_progress_bar(); create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); } void write_file_frag(squashfs_inode *inode, struct dir_ent *dir_ent, int size, struct file_buffer *file_buffer, int *duplicate_file) { struct fragment *fragment; unsigned short checksum; checksum = get_checksum_mem_buffer(file_buffer); if(pre_duplicate_frag(size, checksum)) { write_file_frag_dup(inode, dir_ent, size, duplicate_file, file_buffer, checksum); return; } fragment = get_and_fill_fragment(file_buffer); cache_block_put(file_buffer); if(duplicate_checking) add_non_dup(size, 0, NULL, 0, fragment, 0, checksum, TRUE); total_bytes += size; file_count ++; *duplicate_file = FALSE; inc_progress_bar(); create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, size, 0, 0, NULL, fragment, NULL, 0); return; } int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, struct file_buffer *read_buffer, int *duplicate_file) { long long read_size, file_bytes, start; struct fragment *fragment; unsigned int *block_list = NULL; int block = 0, status; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; lock_fragments(); file_bytes = 0; start = bytes; while (1) { read_size = read_buffer->file_size; if(read_buffer->fragment && read_buffer->c_byte) fragment_buffer = read_buffer; else { block_list = realloc(block_list, (block + 1) * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list" "\n"); block_list[block ++] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(read_size != -1) break; read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, block, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { long long file_bytes, start; struct fragment *fragment; unsigned int *block_list; int block, status; int blocks = (read_size + block_size - 1) >> block_log; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; *duplicate_file = FALSE; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); lock_fragments(); file_bytes = 0; start = bytes; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); file_bytes += read_buffer->size; queue_put(to_writer, read_buffer); } else { sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } unlock_fragments(); fragment = get_and_fill_fragment(fragment_buffer); cache_block_put(fragment_buffer); if(duplicate_checking) add_non_dup(read_size, file_bytes, block_list, start, fragment, 0, 0, FALSE); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_list, fragment, NULL, sparse); if(duplicate_checking == FALSE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(!block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); free(block_list); cache_block_put(read_buffer); return status; } int write_file_blocks_dup(squashfs_inode *inode, struct dir_ent *dir_ent, long long read_size, struct file_buffer *read_buffer, int *duplicate_file) { int block, thresh; long long file_bytes, dup_start, start; struct fragment *fragment; struct file_info *dupl_ptr; int blocks = (read_size + block_size - 1) >> block_log; unsigned int *block_list, *block_listp; struct file_buffer **buffer_list; int status, num_locked_fragments; long long sparse = 0; struct file_buffer *fragment_buffer = NULL; block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; buffer_list = malloc(blocks * sizeof(struct file_buffer *)); if(buffer_list == NULL) BAD_ERROR("Out of memory allocating file block list\n"); num_locked_fragments = lock_fragments(); file_bytes = 0; start = dup_start = bytes; thresh = blocks > (writer_buffer_size - num_locked_fragments) ? blocks - (writer_buffer_size - num_locked_fragments): 0; for(block = 0; block < blocks;) { if(read_buffer->fragment && read_buffer->c_byte) { fragment_buffer = read_buffer; blocks = read_size >> block_log; } else { block_list[block] = read_buffer->c_byte; if(read_buffer->c_byte) { read_buffer->block = bytes; bytes += read_buffer->size; file_bytes += read_buffer->size; cache_rehash(read_buffer, read_buffer->block); if(block < thresh) { buffer_list[block] = NULL; queue_put(to_writer, read_buffer); } else buffer_list[block] = read_buffer; } else { buffer_list[block] = NULL; sparse += read_buffer->size; cache_block_put(read_buffer); } } inc_progress_bar(); if(++block < blocks) { read_buffer = get_file_buffer(from_deflate); if(read_buffer->error) goto read_err; } } dupl_ptr = duplicate(read_size, file_bytes, &block_listp, &dup_start, &fragment, fragment_buffer, blocks, 0, 0, FALSE); if(dupl_ptr) { *duplicate_file = FALSE; for(block = thresh; block < blocks; block ++) if(buffer_list[block]) queue_put(to_writer, buffer_list[block]); fragment = get_and_fill_fragment(fragment_buffer); dupl_ptr->fragment = fragment; } else { *duplicate_file = TRUE; for(block = thresh; block < blocks; block ++) cache_block_put(buffer_list[block]); bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because" " %s\n", strerror(errno)); } } unlock_fragments(); cache_block_put(fragment_buffer); free(buffer_list); file_count ++; total_bytes += read_size; /* * sparse count is needed to ensure squashfs correctly reports a * a smaller block count on stat calls to sparse files. This is * to ensure intelligent applications like cp correctly handle the * file as a sparse file. If the file in the original filesystem isn't * stored as a sparse file then still store it sparsely in squashfs, but * report it as non-sparse on stat calls to preserve semantics */ if(sparse && (dir_ent->inode->buf.st_blocks << 9) >= read_size) sparse = 0; create_inode(inode, NULL, dir_ent, SQUASHFS_FILE_TYPE, read_size, dup_start, blocks, block_listp, fragment, NULL, sparse); if(*duplicate_file == TRUE) free(block_list); return 0; read_err: cur_uncompressed -= block; status = read_buffer->error; bytes = start; if(thresh && !block_device) { int res; queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); res = ftruncate(fd, bytes); if(res != 0) BAD_ERROR("Failed to truncate dest file because %s\n", strerror(errno)); } unlock_fragments(); for(blocks = thresh; blocks < block; blocks ++) cache_block_put(buffer_list[blocks]); free(buffer_list); free(block_list); cache_block_put(read_buffer); return status; } void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *duplicate_file) { int status; struct file_buffer *read_buffer; long long read_size; again: read_buffer = get_file_buffer(from_deflate); status = read_buffer->error; if(status) { cache_block_put(read_buffer); goto file_err; } read_size = read_buffer->file_size; if(read_size == -1) status = write_file_process(inode, dir_ent, read_buffer, duplicate_file); else if(read_size == 0) { write_file_empty(inode, dir_ent, duplicate_file); cache_block_put(read_buffer); } else if(read_buffer->fragment && read_buffer->c_byte) write_file_frag(inode, dir_ent, read_size, read_buffer, duplicate_file); else if(pre_duplicate(read_size)) status = write_file_blocks_dup(inode, dir_ent, read_size, read_buffer, duplicate_file); else status = write_file_blocks(inode, dir_ent, read_size, read_buffer, duplicate_file); file_err: if(status == 2) { ERROR("File %s changed size while reading filesystem, " "attempting to re-read\n", dir_ent->pathname); goto again; } else if(status == 1) { ERROR("Failed to read file %s, creating empty file\n", dir_ent->pathname); write_file_empty(inode, dir_ent, duplicate_file); } } #define BUFF_SIZE 8192 char b_buffer[BUFF_SIZE]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getcwd(b_buffer, BUFF_SIZE); if(result == NULL) return NULL; strcat(strcat(b_buffer, "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } inode = malloc(sizeof(struct inode_info)); if(inode == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation" "\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->read = FALSE; inode->root_entry = FALSE; inode->pseudo_file = FALSE; inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFREG) estimated_uncompressed += (buf->st_size + block_size - 1) >> block_log; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) { dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *)); if(dir->list == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); } dir->list[dir->count] = malloc(sizeof(struct dir_ent)); if(dir->list[dir->count] == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count++]->our_dir = dir; dir->byte_count += strlen(name) + sizeof(struct squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { struct dir_info *dir; dir = malloc(sizeof(struct dir_info)); if(dir == NULL) BAD_ERROR("Out of memory in scan1_opendir\n"); if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { static int index = 0; if(dir->count < old_root_entries) { int i; for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } } while(index < source) { char *basename = getbase(source_path[index]); int n, pass = 1; if(basename == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i; if(dir->count < old_root_entries) { for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, &old_root_entry[i].inode, dir); } } if((d_name = readdir(dir->linuxdir)) != NULL) { int pass = 1; strcpy(dir_name, d_name->d_name); for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying" " ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name = readdir(dir->linuxdir); if(d_name != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) continue; else return dir_info->list[current_count]; return NULL; } struct dir_ent *scan2_lookup(struct dir_info *dir, char *name) { int i; for(i = 0; i < dir->count; i++) if(strcmp(dir->list[i]->name, name) == 0) return dir->list[i]; return NULL; } struct dir_ent *scan3_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->inode->root_entry) add_dir(dir_info->list[current_count]->inode->inode, dir_info->list[current_count]->inode->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->inode->type, dir); else return dir_info->list[current_count]; return NULL; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); free(dir->pathname); dir->pathname = NULL; } void scan2_freedir(struct dir_info *dir) { dir->current_count = 0; if(dir->pathname) { free(dir->pathname); dir->pathname = NULL; } } void scan3_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct stat buf; struct dir_info *dir_info = dir_scan1(pathname, paths, _readdir); struct dir_ent *dir_ent; if(dir_info == NULL) return; dir_scan2(dir_info, pseudo); dir_ent = malloc(sizeof(struct dir_ent)); if(dir_ent == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if(pathname[0] == '\0') { /* * dummy top level directory, if multiple sources specified on * command line */ memset(&buf, 0, sizeof(buf)); buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); buf.st_dev = 0; buf.st_ino = 0; dir_ent->inode = lookup_inode(&buf); dir_ent->inode->pseudo_file = PSEUDO_FILE_OTHER; } else { if(lstat(pathname, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", pathname, strerror(errno)); return; } dir_ent->inode = lookup_inode(&buf); } if(root_inode_number) { dir_ent->inode->inode_number = root_inode_number; dir_inode_no --; } dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->our_dir = NULL; dir_info->dir_ent = dir_ent; if(sorted) { int res = generate_file_priorities(dir_info, 0, &dir_info->dir_ent->inode->buf); if(res == FALSE) BAD_ERROR("generate_file_priorities failed\n"); } queue_put(to_reader, dir_info); if(sorted) sort_files_and_write(dir_info); if(progress) enable_progress_bar(); dir_scan3(inode, dir_info); dir_ent->inode->inode = *inode; dir_ent->inode->type = SQUASHFS_DIR_TYPE; } struct dir_info *dir_scan1(char *pathname, struct pathnames *paths, int (_readdir)(char *, char *, struct dir_info *)) { char filename[8192], dir_name[8192]; struct dir_info *dir = scan1_opendir(pathname); if(dir == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { struct dir_info *sub_dir; struct stat buf; struct pathnames *new; if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { ERROR("Cannot stat dir/file %s because %s, ignoring", filename, strerror(errno)); continue; } if((buf.st_mode & S_IFMT) != S_IFREG && (buf.st_mode & S_IFMT) != S_IFDIR && (buf.st_mode & S_IFMT) != S_IFLNK && (buf.st_mode & S_IFMT) != S_IFCHR && (buf.st_mode & S_IFMT) != S_IFBLK && (buf.st_mode & S_IFMT) != S_IFIFO && (buf.st_mode & S_IFMT) != S_IFSOCK) { ERROR("File %s has unrecognised filetype %d, ignoring" "\n", filename, buf.st_mode & S_IFMT); continue; } if(old_exclude) { if(old_excluded(filename, &buf)) continue; } else { if(excluded(paths, dir_name, &new)) continue; } if((buf.st_mode & S_IFMT) == S_IFDIR) { sub_dir = dir_scan1(filename, new, scan1_readdir); if(sub_dir == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), dir); } scan1_freedir(dir); error: return dir; } struct dir_info *dir_scan2(struct dir_info *dir, struct pseudo *pseudo) { struct dir_info *sub_dir; struct dir_ent *dir_ent; struct pseudo_entry *pseudo_ent; struct stat buf; static int pseudo_ino = 1; if(dir == NULL && (dir = scan1_opendir("")) == NULL) return NULL; while((dir_ent = scan2_readdir(dir)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *name = dir_ent->name; if((buf->st_mode & S_IFMT) == S_IFDIR) dir_scan2(dir_ent->dir, pseudo_subdir(name, pseudo)); } while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { dir_ent = scan2_lookup(dir, pseudo_ent->name); if(pseudo_ent->dev->type == 'm') { struct stat *buf; if(dir_ent == NULL) { ERROR("Pseudo modify file \"%s\" does not exist " "in source filesystem. Ignoring.\n", pseudo_ent->pathname); continue; } if(dir_ent->inode->root_entry) { ERROR("Pseudo modify file \"%s\" is a pre-existing" " file in the filesystem being appended" " to. It cannot be modified. " "Ignoring.\n", pseudo_ent->pathname); continue; } buf = &dir_ent->inode->buf; buf->st_mode = (buf->st_mode & S_IFMT) | pseudo_ent->dev->mode; buf->st_uid = pseudo_ent->dev->uid; buf->st_gid = pseudo_ent->dev->gid; continue; } if(dir_ent) { if(dir_ent->inode->root_entry) ERROR("Pseudo file \"%s\" is a pre-existing" " file in the filesystem being appended" " to. Ignoring.\n", pseudo_ent->pathname); else ERROR("Pseudo file \"%s\" exists in source " "filesystem \"%s\".\nIgnoring, " "exclude it (-e/-ef) to override.\n", pseudo_ent->pathname, dir_ent->pathname); continue; } if(pseudo_ent->dev->type == 'd') { sub_dir = dir_scan2(NULL, pseudo_ent->pseudo); if(sub_dir == NULL) { ERROR("Could not create pseudo directory \"%s\"" ", skipping...\n", pseudo_ent->pathname); continue; } dir->directory_count ++; } else sub_dir = NULL; memset(&buf, 0, sizeof(buf)); buf.st_mode = pseudo_ent->dev->mode; buf.st_uid = pseudo_ent->dev->uid; buf.st_gid = pseudo_ent->dev->gid; buf.st_rdev = makedev(pseudo_ent->dev->major, pseudo_ent->dev->minor); buf.st_mtime = time(NULL); buf.st_ino = pseudo_ino ++; if(pseudo_ent->dev->type == 'f') { #ifdef USE_TMP_FILE struct stat buf2; int res = stat(pseudo_ent->dev->filename, &buf2); struct inode_info *inode; if(res == -1) { ERROR("Stat on pseudo file \"%s\" failed, " "skipping...", pseudo_ent->pathname); continue; } buf.st_size = buf2.st_size; inode = lookup_inode(&buf); inode->pseudo_file = PSEUDO_FILE_OTHER; add_dir_entry(pseudo_ent->name, pseudo_ent->dev->filename, sub_dir, inode, dir); #else struct inode_info *inode = lookup_inode(&buf); inode->pseudo_id = pseudo_ent->dev->pseudo_id; inode->pseudo_file = PSEUDO_FILE_PROCESS; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, inode, dir); #endif } else { struct inode_info *inode = lookup_inode(&buf); inode->pseudo_file = PSEUDO_FILE_OTHER; add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, inode, dir); } } scan2_freedir(dir); sort_directory(dir); return dir; } void dir_scan3(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int duplicate_file; char *pathname = dir_info->dir_ent->pathname; struct directory dir; struct dir_ent *dir_ent; scan3_init_dir(&dir); while((dir_ent = scan3_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; write_file(inode, dir_ent, &duplicate_file); INFO("file %s, uncompressed size %lld " "bytes %s\n", filename, (long long) buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; dir_scan3(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("character device %s inode 0x%llx" "\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("fifo %s inode 0x%llx\n",dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; create_inode(inode, NULL, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0); INFO("unix domain socket %s inode " "0x%llx\n", dir_name, *inode); sock_count ++; break; default: BAD_ERROR("%s unrecognised file type, " "mode is %x\n", filename, buf->st_mode); } dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed " "size %lld bytes LINK" "\n", filename, (long long) buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx " "LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode " "0x%llx LINK\n", dir_name, *inode); break; } } add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); update_progress_bar(); } write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan3_freedir(&dir); } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int old_excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) { \ exclude_paths = realloc(exclude_paths, (exclude + EXCLUDE_SIZE) \ * sizeof(struct exclude_info)); \ if(exclude_paths == NULL) \ BAD_ERROR("Out of memory in exclude dir/file table\n"); \ } \ exclude_paths[exclude].st_dev = buf.st_dev; \ exclude_paths[exclude++].st_ino = buf.st_ino; int old_add_exclude(char *path) { int i; char filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { ERROR("Cannot stat exclude dir/file %s because %s, " "ignoring", path, strerror(errno)); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) ERROR("Cannot stat exclude dir/file %s because " "%s, ignoring", filename, strerror(errno)); continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { old_root_entry = realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1)); if(old_root_entry == NULL) BAD_ERROR("Out of memory in old root directory entries " "reallocation\n"); old_root_entry[old_root_entries].name = strdup(name); old_root_entry[old_root_entries].inode.inode = inode; old_root_entry[old_root_entries].inode.inode_number = inode_number; old_root_entry[old_root_entries].inode.type = type; old_root_entry[old_root_entries++].inode.root_entry = TRUE; } void initialise_threads(int readb_mbytes, int writeb_mbytes, int fragmentb_mbytes) { int i; sigset_t sigmask, old_mask; int reader_buffer_size = readb_mbytes << (20 - block_log); int fragment_buffer_size = fragmentb_mbytes << (20 - block_log); /* * writer_buffer_size is global because it is needed in * write_file_blocks_dup() */ writer_buffer_size = writeb_mbytes << (20 - block_log); sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); signal(SIGUSR1, sigusr1_handler); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = sysconf(_SC_NPROCESSORS_ONLN); #endif } thread = malloc((2 + processors * 2) * sizeof(pthread_t)); if(thread == NULL) BAD_ERROR("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[2]; frag_deflator_thread = &deflator_thread[processors]; to_reader = queue_init(1); from_reader = queue_init(reader_buffer_size); to_writer = queue_init(writer_buffer_size); from_writer = queue_init(1); from_deflate = queue_init(reader_buffer_size); to_frag = queue_init(fragment_buffer_size); reader_buffer = cache_init(block_size, reader_buffer_size); writer_buffer = cache_init(block_size, writer_buffer_size); fragment_buffer = cache_init(block_size, fragment_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&progress_thread, NULL, progress_thrd, NULL); pthread_mutex_init(&fragment_mutex, NULL); pthread_cond_init(&fragment_waiting, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); if(pthread_create(&frag_deflator_thread[i], NULL, frag_deflator, NULL) != 0) BAD_ERROR("Failed to create thread\n"); } printf("Parallel mksquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) BAD_ERROR("Failed to set signal mask in intialise_threads\n"); } long long write_inode_lookup_table() { int i, inode_number, lookup_bytes = SQUASHFS_LOOKUP_BYTES(inode_count); void *it; if(inode_count == sinode_count) goto skip_inode_hash_table; it = realloc(inode_lookup_table, lookup_bytes); if(it == NULL) BAD_ERROR("Out of memory in write_inode_table\n"); inode_lookup_table = it; for(i = 0; i < INODE_HASH_SIZE; i ++) { struct inode_info *inode = inode_info[i]; for(inode = inode_info[i]; inode; inode = inode->next) { inode_number = inode->type == SQUASHFS_DIR_TYPE ? inode->inode_number : inode->inode_number + dir_inode_no; SQUASHFS_SWAP_LONG_LONGS(&inode->inode, &inode_lookup_table[inode_number - 1], 1); } } skip_inode_hash_table: return generic_write_table(lookup_bytes, inode_lookup_table, 0, NULL, noI); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; target = get_component(target, targname); if(paths == NULL) { paths = malloc(sizeof(struct pathname)); if(paths == NULL) BAD_ERROR("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); if(paths->name == NULL) BAD_ERROR("Out of memory in add path\n"); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(paths->name[i].preg == NULL) BAD_ERROR("Out of memory in add_path\n"); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); BAD_ERROR("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* at leaf pathname component */ paths->name[i].paths = NULL; else /* recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* existing matching entry */ if(paths->name[i].paths == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing exclude which subsumes * the exclude currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* at leaf pathname component and child components exist * from more specific excludes, delete as they're * subsumed by this exclude */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } void add_exclude(char *target) { if(target[0] == '/' || strncmp(target, "./", 2) == 0 || strncmp(target, "../", 3) == 0) BAD_ERROR("/, ./ and ../ prefixed excludes not supported with " "-wildcards or -regex options\n"); else if(strncmp(target, "... ", 4) == 0) stickypath = add_path(stickypath, target + 4, target + 4); else path = add_path(path, target, target); } void display_path(int depth, struct pathname *paths) { int i, n; if(paths == NULL) return; for(i = 0; i < paths->names; i++) { for(n = 0; n < depth; n++) printf("\t"); printf("%d: %s\n", depth, paths->name[i].name); display_path(depth + 1, paths->name[i].paths); } } void display_path2(struct pathname *paths, char *string) { int i; char path[1024]; if(paths == NULL) { printf("%s\n", string); return; } for(i = 0; i < paths->names; i++) { strcat(strcat(strcpy(path, string), "/"), paths->name[i].name); display_path2(paths->name[i].paths, path); } } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); if(new == NULL) BAD_ERROR("Out of memory in init_subdir\n"); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) { paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); if(paths == NULL) BAD_ERROR("Out of memory in add_subdir\n"); } paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int excluded(struct pathnames *paths, char *name, struct pathnames **new) { int i, n, res; if(paths == NULL) { *new = NULL; return FALSE; } *new = init_subdir(); if(stickypath) *new = add_subdir(*new, stickypath); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) { /* match on a leaf component, any subdirectories * in the filesystem should be excluded */ res = TRUE; goto empty_set; } if(match) /* match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* no matching names found, return empty new search set */ res = FALSE; goto empty_set; } /* one or more matches with sub-directories found (no leaf matches). * Return new set */ return FALSE; empty_set: free_subdir(*new); *new = NULL; return res; } #define RECOVER_ID "Squashfs recovery file v1.0\n" #define RECOVER_ID_SIZE 28 void write_recovery_data(struct squashfs_super_block *sBlk) { int res, recoverfd, bytes = sBlk->bytes_used - sBlk->inode_table_start; pid_t pid = getpid(); char *metadata; char header[] = RECOVER_ID; if(recover == FALSE) { printf("No recovery data option specified.\n"); printf("Skipping saving recovery file.\n\n"); return; } metadata = malloc(bytes); if(metadata == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "write_recovery_data\n"); res = read_fs_bytes(fd, sBlk->inode_table_start, bytes, metadata); if(res == 0) EXIT_MKSQUASHFS(); sprintf(recovery_file, "squashfs_recovery_%s_%d", getbase(destination_file), pid); recoverfd = open(recovery_file, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(recoverfd == -1) BAD_ERROR("Failed to create recovery file, because %s. " "Aborting\n", strerror(errno)); if(write_bytes(recoverfd, header, RECOVER_ID_SIZE) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, sBlk, sizeof(struct squashfs_super_block)) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); if(write_bytes(recoverfd, metadata, bytes) == -1) BAD_ERROR("Failed to write recovery file, because %s\n", strerror(errno)); close(recoverfd); free(metadata); printf("Recovery file \"%s\" written\n", recovery_file); printf("If Mksquashfs aborts abnormally (i.e. power failure), run\n"); printf("mksquashfs dummy %s -recover %s\n", destination_file, recovery_file); printf("to restore filesystem\n\n"); } void read_recovery_data(char *recovery_file, char *destination_file) { int fd, recoverfd, bytes; struct squashfs_super_block orig_sBlk, sBlk; char *metadata; int res; struct stat buf; char header[] = RECOVER_ID; char header2[RECOVER_ID_SIZE]; recoverfd = open(recovery_file, O_RDONLY); if(recoverfd == -1) BAD_ERROR("Failed to open recovery file because %s\n", strerror(errno)); if(stat(destination_file, &buf) == -1) BAD_ERROR("Failed to stat destination file, because %s\n", strerror(errno)); fd = open(destination_file, O_RDWR); if(fd == -1) BAD_ERROR("Failed to open destination file because %s\n", strerror(errno)); res = read_bytes(recoverfd, header2, RECOVER_ID_SIZE); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < RECOVER_ID_SIZE) BAD_ERROR("Recovery file appears to be truncated\n"); if(strncmp(header, header2, RECOVER_ID_SIZE) !=0 ) BAD_ERROR("Not a recovery file\n"); res = read_bytes(recoverfd, &sBlk, sizeof(struct squashfs_super_block)); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < sizeof(struct squashfs_super_block)) BAD_ERROR("Recovery file appears to be truncated\n"); res = read_fs_bytes(fd, 0, sizeof(struct squashfs_super_block), &orig_sBlk); if(res == 0) EXIT_MKSQUASHFS(); if(memcmp(((char *) &sBlk) + 4, ((char *) &orig_sBlk) + 4, sizeof(struct squashfs_super_block) - 4) != 0) BAD_ERROR("Recovery file and destination file do not seem to " "match\n"); bytes = sBlk.bytes_used - sBlk.inode_table_start; metadata = malloc(bytes); if(metadata == NULL) BAD_ERROR("Failed to alloc metadata buffer in " "read_recovery_data\n"); res = read_bytes(recoverfd, metadata, bytes); if(res == -1) BAD_ERROR("Failed to read recovery file, because %s\n", strerror(errno)); if(res < bytes) BAD_ERROR("Recovery file appears to be truncated\n"); write_destination(fd, 0, sizeof(struct squashfs_super_block), &sBlk); write_destination(fd, sBlk.inode_table_start, bytes, metadata); close(recoverfd); close(fd); printf("Successfully wrote recovery file \"%s\". Exiting\n", recovery_file); exit(0); } #define VERSION() \ printf("mksquashfs version 4.2 (2011/02/28)\n");\ printf("copyright (C) 2011 Phillip Lougher "\ "<phillip@lougher.demon.co.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or"\ "\n");\ printf("modify it under the terms of the GNU General Public License"\ "\n");\ printf("as published by the Free Software Foundation; either version "\ "2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be "\ "useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty "\ "of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int res, i; struct squashfs_super_block sBlk; char *b, *root_name = NULL; int nopad = FALSE, keep_as_directory = FALSE; squashfs_inode inode; int readb_mbytes = READER_BUFFER_DEFAULT, writeb_mbytes = WRITER_BUFFER_DEFAULT, fragmentb_mbytes = FRAGMENT_BUFFER_DEFAULT; pthread_mutex_init(&progress_mutex, NULL); block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; /* * lookup default compressor. Note the Makefile ensures the default * compressor has been built, and so we don't need to to check * for failure here */ comp = lookup_compressor(COMP_DEFAULT); for(; i < argc; i++) { if(strcmp(argv[i], "-comp") == 0) { if(compressor_opts_parsed) { ERROR("%s: -comp must appear before -X options" "\n", argv[0]); exit(1); } if(++i == argc) { ERROR("%s: -comp missing compression type\n", argv[0]); exit(1); } comp = lookup_compressor(argv[i]); if(!comp->supported) { ERROR("%s: Compressor \"%s\" is not supported!" "\n", argv[0], argv[i]); ERROR("%s: Compressors available:\n", argv[0]); display_compressors("", COMP_DEFAULT); exit(1); } } else if(strncmp(argv[i], "-X", 2) == 0) { int args = compressor_options(comp, argv + i, argc - i); if(args < 0) { if(args == -1) { ERROR("%s: Unrecognised compressor" " option %s\n", argv[0], argv[i]); ERROR("%s: Did you forget to specify" " -comp, or specify it after" " the compressor specific" " option?\n", argv[0]); } exit(1); } i += args; compressor_opts_parsed = 1; } else if(strcmp(argv[i], "-pf") == 0) { if(++i == argc) { ERROR("%s: -pf missing filename\n", argv[0]); exit(1); } if(read_pseudo_file(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-p") == 0) { if(++i == argc) { ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } if(read_pseudo_def(&pseudo, argv[i]) == FALSE) exit(1); } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { ERROR("%s: -recover missing recovery file\n", argv[0]); exit(1); } read_recovery_data(argv[i], argv[source + 1]); } else if(strcmp(argv[i], "-no-recovery") == 0) recover = FALSE; else if(strcmp(argv[i], "-wildcards") == 0) { old_exclude = FALSE; use_regex = FALSE; } else if(strcmp(argv[i], "-regex") == 0) { old_exclude = FALSE; use_regex = TRUE; } else if(strcmp(argv[i], "-no-sparse") == 0) sparse_files = FALSE; else if(strcmp(argv[i], "-no-progress") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-exports") == 0) exportable = FALSE; else if(strcmp(argv[i], "-processors") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-read-queue") == 0) { if((++i == argc) || (readb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -read-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(readb_mbytes < 1) { ERROR("%s: -read-queue should be 1 megabyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-write-queue") == 0) { if((++i == argc) || (writeb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -write-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(writeb_mbytes < 1) { ERROR("%s: -write-queue should be 1 megabyte " "or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-fragment-queue") == 0) { if((++i == argc) || (fragmentb_mbytes = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -fragment-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragmentb_mbytes < 1) { ERROR("%s: -fragment-queue should be 1 " "megabyte or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-b") == 0) { if(++i == argc) { ERROR("%s: -b missing block size\n", argv[0]); exit(1); } block_size = strtol(argv[i], &b, 10); if(*b == 'm' || *b == 'M') block_size *= 1048576; else if(*b == 'k' || *b == 'K') block_size *= 1024; else if(*b != '\0') { ERROR("%s: -b invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or " "not between 4096 and 1Mbyte\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range" "\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or " "unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range" "\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or " "unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-noX") == 0 || strcmp(argv[i], "-noXattrCompression") == 0) noX = TRUE; else if(strcmp(argv[i], "-no-xattrs") == 0) no_xattrs = TRUE; else if(strcmp(argv[i], "-xattrs") == 0) no_xattrs = FALSE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-info") == 0) { silent = FALSE; progress = FALSE; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] " "[-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nFilesystem build options:\n"); ERROR("-comp <comp>\t\tselect <comp> compression\n"); ERROR("\t\t\tCompressors available:\n"); display_compressors("\t\t\t", COMP_DEFAULT); ERROR("-b <block_size>\t\tset data block to " "<block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-no-exports\t\tdon't make the filesystem " "exportable via NFS\n"); ERROR("-no-sparse\t\tdon't detect sparse files\n"); ERROR("-no-xattrs\t\tdon't store extended attributes" NOXOPT_STR "\n"); ERROR("-xattrs\t\t\tstore extended attributes" XOPT_STR "\n"); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-noX\t\t\tdo not compress extended " "attributes\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for " "files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate " "checking\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " "of 4K\n"); ERROR("-keep-as-directory\tif one source directory is " "specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, " "rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("\nFilesystem filter options:\n"); ERROR("-p <pseudo-definition>\tAdd pseudo file " "definition\n"); ERROR("-pf <pseudo-file>\tAdd list of pseudo file " "definitions\n"); ERROR("-sort <sort_file>\tsort files according to " "priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. " "Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files." " One per line\n"); ERROR("-wildcards\t\tAllow extended shell wildcards " "(globbing) to be used in\n\t\t\texclude " "dirs/files\n"); ERROR("-regex\t\t\tAllow POSIX regular expressions to " "be used in exclude\n\t\t\tdirs/files\n"); ERROR("\nFilesystem append options:\n"); ERROR("-noappend\t\tdo not append to existing " "filesystem\n"); ERROR("-root-becomes <name>\twhen appending source " "files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in " "the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new " "source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("\nMksquashfs runtime options:\n"); ERROR("-version\t\tprint version, licence and " "copyright message\n"); ERROR("-recover <name>\t\trecover filesystem data " "using recovery file <name>\n"); ERROR("-no-recovery\t\tdon't generate a recovery " "file\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-no-progress\t\tdon't display the progress " "bar\n"); ERROR("-processors <number>\tUse <number> processors." " By default will use number of\n"); ERROR("\t\t\tprocessors available\n"); ERROR("-read-queue <size>\tSet input queue to <size> " "Mbytes. Default %d Mbytes\n", READER_BUFFER_DEFAULT); ERROR("-write-queue <size>\tSet output queue to <size> " "Mbytes. Default %d Mbytes\n", WRITER_BUFFER_DEFAULT); ERROR("-fragment-queue <size>\tSet fragment queue to " "<size> Mbytes. Default %d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\nMiscellaneous options:\n"); ERROR("-root-owned\t\talternative name for -all-root" "\n"); ERROR("-noInodeCompression\talternative name for -noI" "\n"); ERROR("-noDataCompression\talternative name for -noD" "\n"); ERROR("-noFragmentCompression\talternative name for " "-noF\n"); ERROR("-noXattrCompression\talternative name for " "-noX\n"); ERROR("\nCompressors available and compressor specific " "options:\n"); display_compressor_usage(COMP_DEFAULT); exit(1); } } /* * Some compressors may need the options to be checked for validity * once all the options have been processed */ res = compressor_options_post(comp, block_size); if(res) EXIT_MKSQUASHFS(); for(i = 0; i < source; i++) if(lstat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" " "because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(fd == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as " "destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR); if(fd == -1) { perror("Could not open regular file for " "writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); /* * process the exclude files - must be done afer destination file has * been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) if(old_exclude) old_add_exclude(filename); else add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc) if(old_exclude) old_add_exclude(argv[i++]); else add_exclude(argv[i++]); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { int res = read_sort_file(argv[++i], source, source_path); if(res == FALSE) BAD_ERROR("Failed to read sort file\n"); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-pf") == 0 || strcmp(argv[i], "-comp") == 0) i++; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(!delete) { comp = read_super(fd, &sBlk, argv[source + 1]); if(comp == NULL) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); noX = SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); exportable = SQUASHFS_EXPORTABLE(sBlk.flags); no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags); comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags); } initialise_threads(readb_mbytes, writeb_mbytes, fragmentb_mbytes); res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0); if(res) BAD_ERROR("compressor_init failed\n"); if(delete) { int size; void *comp_data = compressor_dump_options(comp, block_size, &size); printf("Creating %d.%d filesystem on %s, block size %d.\n", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); /* * store any compressor specific options after the superblock, * and set the COMP_OPT flag to show that the filesystem has * compressor specfic options */ if(comp_data) { unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT; SQUASHFS_INSWAP_SHORTS(&c_byte, 1); write_destination(fd, sizeof(struct squashfs_super_block), sizeof(c_byte), &c_byte); write_destination(fd, sizeof(struct squashfs_super_block) + sizeof(c_byte), size, comp_data); bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte) + size; comp_opts = TRUE; } else bytes = sizeof(struct squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table, &inode_lookup_table)) == 0) { ERROR("Failed to read existing filesystem - will not " "overwrite - ABORTING!\n"); ERROR("To force Mksquashfs to write to this block " "device or file use -noappend\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) { fragment_table = realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(struct squashfs_fragment_entry)); if(fragment_table == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); } printf("Appending to existing %d.%d filesystem on %s, block " "size %d\n", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -b, -noI, -noD, -noF, -noX, no-duplicates, no-fragments, " "-always-use-fragments,\n-exportable and -comp options " "ignored\n"); printf("\nIf appending is not wanted, please re-run with " "-noappend specified!\n\n"); compressed_data = (inode_dir_offset + inode_dir_file_size) & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = (inode_dir_offset + inode_dir_file_size) & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; scache_bytes = root_inode_offset + root_inode_size; sdirectory_cache_bytes = uncompressed_data; sdata_cache = malloc(scache_bytes); if(sdata_cache == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); sdirectory_data_cache = malloc(sdirectory_cache_bytes); if(sdirectory_data_cache == NULL) BAD_ERROR("Out of memory in save filesystem state\n"); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; sid_count = id_count; write_recovery_data(&sBlk); if(save_xattrs() == FALSE) BAD_ERROR("Failed to save xattrs from existing " "filesystem\n"); restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_destination(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* * set the filesystem state up to be able to append to the * original filesystem. The filesystem state differs depending * on whether we're appending to the original root directory, or * if the original root directory becomes a sub-directory * (root-becomes specified on command line, here root_name != * NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { sdirectory_bytes = last_directory_block; sdirectory_compressed_bytes = 0; root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { sdirectory_compressed_bytes = last_directory_block - inode_dir_start_block; sdirectory_compressed = malloc(sdirectory_compressed_bytes); if(sdirectory_compressed == NULL) BAD_ERROR("Out of memory in save filesystem " "state\n"); memcpy(sdirectory_compressed, directory_table + inode_dir_start_block, sdirectory_compressed_bytes); sdirectory_bytes = inode_dir_start_block; root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; /* * The default use freelist before growing cache policy behaves * poorly with appending - with many deplicates the caches * do not grow due to the fact that large queues of outstanding * fragments/writer blocks do not occur, leading to small caches * and un-uncessary performance loss to frequent cache * replacement in the small caches. Therefore with appending * change the policy to grow the caches before reusing blocks * from the freelist */ first_freelist = FALSE; } if(path || stickypath) { paths = init_subdir(); if(path) paths = add_subdir(paths, path); if(stickypath) paths = add_subdir(paths, stickypath); } if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, no_fragments, always_use_fragments, duplicate_checking, exportable, no_xattrs, comp_opts); sBlk.mkfs_time = time(NULL); restore_filesystem: if(progress && estimated_uncompressed) { disable_progress_bar(); progress_bar(cur_uncompressed, estimated_uncompressed, columns); } write_fragment(); sBlk.fragments = fragments; if(!restoring) { unlock_fragments(); pthread_mutex_lock(&fragment_mutex); while(fragments_outstanding) { pthread_mutex_unlock(&fragment_mutex); sched_yield(); pthread_mutex_lock(&fragment_mutex); } queue_put(to_writer, NULL); if(queue_get(from_writer) != 0) EXIT_MKSQUASHFS(); } sBlk.no_ids = id_count; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); sBlk.lookup_table_start = exportable ? write_inode_lookup_table() : SQUASHFS_INVALID_BLK; sBlk.id_table_start = write_id_table(); sBlk.xattr_id_table_start = write_xattrs(); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk.fragment_table_start); if(exportable) TRACE("sBlk->lookup_table_start 0x%llx\n", sBlk.lookup_table_start); sBlk.bytes_used = bytes; sBlk.compression = comp->id; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk); write_destination(fd, SQUASHFS_START, sizeof(sBlk), &sBlk); if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_destination(fd, bytes, 4096 - i, temp); } close(fd); delete_pseudo_files(); if(recovery_file[0] != '\0') unlink(recovery_file); total_bytes += total_inode_bytes + total_directory_bytes + sizeof(struct squashfs_super_block) + total_xattr_bytes; printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, comp->name, block_size); printf("\t%s data, %s metadata, %s fragments, %s xattrs\n", noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed", no_xattrs ? "no" : noX ? "uncompressed" : "compressed"); printf("\tduplicates are %sremoved\n", duplicate_checking ? "" : "not "); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(total_xattr_bytes) { printf("Xattr table size %d bytes (%.2f Kbytes)\n", xattr_bytes, xattr_bytes / 1024.0); printf("\t%.2f%% of uncompressed xattr table size (%d bytes)\n", ((float) xattr_bytes / total_xattr_bytes) * 100.0, total_xattr_bytes); } if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of ids (unique uids + gids) %d\n", id_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_UID) { struct passwd *user = getpwuid(id_table[i]->id); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, id_table[i]->id); } } printf("Number of gids %d\n", guid_count); for(i = 0; i < id_count; i++) { if(id_table[i]->flags & ISA_GID) { struct group *group = getgrgid(id_table[i]->id); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, id_table[i]->id); } } return 0; } ================================================ FILE: src/others/squashfs-4.2-official/mksquashfs.h ================================================ #ifndef MKSQUASHFS_H #define MKSQUASHFS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(s, d, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(s, d, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) swap_le64_num(s, d, n) #define SWAP_LE16(s, d) swap_le16(s, d) #define SWAP_LE32(s, d) swap_le32(s, d) #define SWAP_LE64(s, d) swap_le64(s, d) #else #define SQUASHFS_MEMCPY(s, d, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(s, d, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(s, d, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \ memcpy(d, s, n * sizeof(long long)) #endif struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; }; struct inode_info { struct stat buf; struct inode_info *next; squashfs_inode inode; unsigned int inode_number; unsigned int nlink; int pseudo_id; char type; char read; char root_entry; char pseudo_file; }; #endif #define PSEUDO_FILE_OTHER 1 #define PSEUDO_FILE_PROCESS 2 #define IS_PSEUDO(a) ((a)->pseudo_file) #define IS_PSEUDO_PROCESS(a) ((a)->pseudo_file & PSEUDO_FILE_PROCESS) #define IS_PSEUDO_OTHER(a) ((a)->pseudo_file & PSEUDO_FILE_OTHER) /* offset of data in compressed metadata blocks (allowing room for * compressed size */ #define BLOCK_OFFSET 2 ================================================ FILE: src/others/squashfs-4.2-official/pseudo.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.c */ #include <pwd.h> #include <grp.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include "pseudo.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() \ do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) \ do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); #define TRUE 1 #define FALSE 0 struct pseudo_dev **pseudo_file = NULL; int pseudo_count = 0; static void dump_pseudo(struct pseudo *pseudo, char *string) { int i; char path[1024]; for(i = 0; i < pseudo->names; i++) { struct pseudo_entry *entry = &pseudo->name[i]; if(string) strcat(strcat(strcpy(path, string), "/"), entry->name); else strcpy(path, entry->name); if(entry->pseudo == NULL) ERROR("%s %c %o %d %d %d %d\n", path, entry->dev->type, entry->dev->mode, entry->dev->uid, entry->dev->gid, entry->dev->major, entry->dev->minor); else dump_pseudo(entry->pseudo, path); } } static char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } /* * Add pseudo device target to the set of pseudo devices. Pseudo_dev * describes the pseudo device attributes. */ struct pseudo *add_pseudo(struct pseudo *pseudo, struct pseudo_dev *pseudo_dev, char *target, char *alltarget) { char targname[1024]; int i; target = get_component(target, targname); if(pseudo == NULL) { if((pseudo = malloc(sizeof(struct pseudo))) == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->names = 0; pseudo->count = 0; pseudo->name = NULL; } for(i = 0; i < pseudo->names; i++) if(strcmp(pseudo->name[i].name, targname) == 0) break; if(i == pseudo->names) { /* allocate new name entry */ pseudo->names ++; pseudo->name = realloc(pseudo->name, (i + 1) * sizeof(struct pseudo_entry)); if(pseudo->name == NULL) BAD_ERROR("failed to allocate pseudo file\n"); pseudo->name[i].name = strdup(targname); if(target[0] == '\0') { /* at leaf pathname component */ pseudo->name[i].pseudo = NULL; pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else { /* recurse adding child components */ pseudo->name[i].dev = NULL; pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); } } else { /* existing matching entry */ if(pseudo->name[i].pseudo == NULL) { /* No sub-directory which means this is the leaf * component of a pre-existing pseudo file. */ if(target[0] != '\0') { /* entry must exist as a 'd' type pseudo file */ if(pseudo->name[i].dev->type == 'd') /* recurse adding child components */ pseudo->name[i].pseudo = add_pseudo(NULL, pseudo_dev, target, alltarget); else ERROR("%s already exists as a non " "directory. Ignoring %s!\n", targname, alltarget); } else if(memcmp(pseudo_dev, pseudo->name[i].dev, sizeof(struct pseudo_dev)) != 0) ERROR("%s already exists as a different pseudo " "definition. Ignoring!\n", alltarget); else ERROR("%s already exists as an identical " "pseudo definition!\n", alltarget); } else { /* sub-directory exists which means this can only be a * 'd' type pseudo file */ if(target[0] == '\0') { if(pseudo->name[i].dev == NULL && pseudo_dev->type == 'd') { pseudo->name[i].pathname = strdup(alltarget); pseudo->name[i].dev = pseudo_dev; } else ERROR("%s already exists as a " "directory. Ignoring %s!\n", targname, alltarget); } else /* recurse adding child components */ add_pseudo(pseudo->name[i].pseudo, pseudo_dev, target, alltarget); } } return pseudo; } /* * Find subdirectory in pseudo directory referenced by pseudo, matching * filename. If filename doesn't exist or if filename is a leaf file * return NULL */ struct pseudo *pseudo_subdir(char *filename, struct pseudo *pseudo) { int i; if(pseudo == NULL) return NULL; for(i = 0; i < pseudo->names; i++) if(strcmp(filename, pseudo->name[i].name) == 0) return pseudo->name[i].pseudo; return NULL; } struct pseudo_entry *pseudo_readdir(struct pseudo *pseudo) { if(pseudo == NULL) return NULL; while(pseudo->count < pseudo->names) { if(pseudo->name[pseudo->count].dev != NULL) return &pseudo->name[pseudo->count++]; else pseudo->count++; } return NULL; } int exec_file(char *command, struct pseudo_dev *dev) { int child, res; static pid_t pid = -1; int pipefd[2]; #ifdef USE_TMP_FILE char filename[1024]; int status; static int number = 0; #endif if(pid == -1) pid = getpid(); #ifdef USE_TMP_FILE sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); if(pipefd[1] == -1) { printf("open failed\n"); return -1; } #else res = pipe(pipefd); if(res == -1) { printf("pipe failed\n"); return -1; } #endif child = fork(); if(child == -1) { printf("fork failed\n"); goto failed; } if(child == 0) { close(STDOUT_FILENO); res = dup(pipefd[1]); if(res == -1) { printf("dup failed\n"); exit(EXIT_FAILURE); } execl("/bin/sh", "sh", "-c", command, (char *) NULL); printf("execl failed\n"); exit(EXIT_FAILURE); } #ifdef USE_TMP_FILE res = waitpid(child, &status, 0); close(pipefd[1]); if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { dev->filename = strdup(filename); return 0; } failed: unlink(filename); return -1; #else close(pipefd[1]); dev->fd = pipefd[0]; dev->child = child; return 0; failed: return -1; #endif } void add_pseudo_file(struct pseudo_dev *dev) { pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * sizeof(struct pseudo_dev *)); if(pseudo_file == NULL) BAD_ERROR("Failed to realloc pseudo_file\n"); dev->pseudo_id = pseudo_count; pseudo_file[pseudo_count ++] = dev; } void delete_pseudo_files() { #ifdef USE_TMP_FILE int i; for(i = 0; i < pseudo_count; i++) unlink(pseudo_file[i]->filename); #endif } struct pseudo_dev *get_pseudo_file(int pseudo_id) { return pseudo_file[pseudo_id]; } int read_pseudo_def(struct pseudo **pseudo, char *def) { int n, bytes; unsigned int major = 0, minor = 0, mode; char filename[2048], type, suid[100], sgid[100], *ptr; long long uid, gid; struct pseudo_dev *dev; n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, sgid, &bytes); if(n < 5) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } switch(type) { case 'b': case 'c': n = sscanf(def + bytes, "%u %u", &major, &minor); if(n < 2) { ERROR("Not enough or invalid arguments in pseudo file " "definition\n"); goto error; } if(major > 0xfff) { ERROR("Major %d out of range\n", major); goto error; } if(minor > 0xfffff) { ERROR("Minor %d out of range\n", minor); goto error; } case 'f': if(def[bytes] == '\0') { ERROR("Not enough arguments in pseudo file " "definition\n"); goto error; } break; case 'd': case 'm': break; default: ERROR("Unsupported type %c\n", type); goto error; } if(mode > 07777) { ERROR("Mode %o out of range\n", mode); goto error; } uid = strtoll(suid, &ptr, 10); if(*ptr == '\0') { if(uid < 0 || uid > ((1LL << 32) - 1)) { ERROR("Uid %s out of range\n", suid); goto error; } } else { struct passwd *pwuid = getpwnam(suid); if(pwuid) uid = pwuid->pw_uid; else { ERROR("Uid %s invalid uid or unknown user\n", suid); goto error; } } gid = strtoll(sgid, &ptr, 10); if(*ptr == '\0') { if(gid < 0 || gid > ((1LL << 32) - 1)) { ERROR("Gid %s out of range\n", sgid); goto error; } } else { struct group *grgid = getgrnam(sgid); if(grgid) gid = grgid->gr_gid; else { ERROR("Gid %s invalid uid or unknown user\n", sgid); goto error; } } switch(type) { case 'b': mode |= S_IFBLK; break; case 'c': mode |= S_IFCHR; break; case 'd': mode |= S_IFDIR; break; case 'f': mode |= S_IFREG; break; } dev = malloc(sizeof(struct pseudo_dev)); if(dev == NULL) BAD_ERROR("Failed to create pseudo_dev\n"); dev->type = type; dev->mode = mode; dev->uid = uid; dev->gid = gid; dev->major = major; dev->minor = minor; if(type == 'f') { int res; printf("Executing dynamic pseudo file\n"); printf("\t\"%s\"\n", def); res = exec_file(def + bytes, dev); if(res == -1) { ERROR("Failed to execute dynamic pseudo file definition" " \"%s\"\n", def); return FALSE; } add_pseudo_file(dev); } *pseudo = add_pseudo(*pseudo, dev, filename, filename); return TRUE; error: ERROR("Bad pseudo file definition \"%s\"\n", def); return FALSE; } #define MAX_LINE 2048 int read_pseudo_file(struct pseudo **pseudo, char *filename) { FILE *fd; char *line = NULL; int size = 0; int res = TRUE; fd = fopen(filename, "r"); if(fd == NULL) { ERROR("Could not open pseudo device file \"%s\" because %s\n", filename, strerror(errno)); return FALSE; } while(1) { int total = 0; while(1) { int n, err; if(total + MAX_LINE > size) { line = realloc(line, size += MAX_LINE); if(line == NULL) { ERROR("No space in read_pseudo_file\n"); return FALSE; } } err = fscanf(fd, "%2047[^\n]%n\n", line + total, &n); if(err <= 0) goto done; if(line[total] == '#') continue; if(line[total + n - 1] != '\\') break; total += n - 1; } res = read_pseudo_def(pseudo, line); if(res == FALSE) break; } done: fclose(fd); free(line); return res; } ================================================ FILE: src/others/squashfs-4.2-official/pseudo.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * pseudo.h */ struct pseudo_dev { char type; unsigned int mode; unsigned int uid; unsigned int gid; unsigned int major; unsigned int minor; int pseudo_id; int fd; int child; #ifdef USE_TMP_FILE char *filename; #endif }; struct pseudo_entry { char *name; char *pathname; struct pseudo *pseudo; struct pseudo_dev *dev; }; struct pseudo { int names; int count; struct pseudo_entry *name; }; extern int read_pseudo_def(struct pseudo **, char *); extern int read_pseudo_file(struct pseudo **, char *); extern struct pseudo *pseudo_subdir(char *, struct pseudo *); extern struct pseudo_entry *pseudo_readdir(struct pseudo *); extern struct pseudo_dev *get_pseudo_file(int); extern void delete_pseudo_files(); ================================================ FILE: src/others/squashfs-4.2-official/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "compressor.h" #include "xattr.h" extern int read_fs_bytes(int, long long, int, void *); extern int add_file(long long, long long, long long, unsigned int *, int, unsigned int, int, int); extern void *create_id(unsigned int); extern unsigned int get_uid(unsigned int); extern unsigned int get_guid(unsigned int); static struct compressor *comp; int read_block(int fd, long long start, long long *next, void *block) { unsigned short c_byte; int res; res = read_fs_bytes(fd, start, 2, &c_byte); if(res == 0) return 0; SQUASHFS_INSWAP_SHORTS(&c_byte, 1); if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); res = read_fs_bytes(fd, start + 2, c_byte, buffer); if(res == 0) return 0; res = compressor_uncompress(comp, block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); return 0; } if(next) *next = start + 2 + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); res = read_fs_bytes(fd, start + 2, c_byte, block); if(res == 0) return 0; if(next) *next = start + 2 + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, struct squashfs_super_block *sBlk, union squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, unsigned int *id_table) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; struct squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start " "0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx " "containing root inode\n", start); *root_inode_block = bytes; } if(size - bytes < SQUASHFS_METADATA_SIZE) { *inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE); if(*inode_table == NULL) return FALSE; } TRACE("scan_inode_table: reading block 0x%llx\n", start); byte = read_block(fd, start, &start, *inode_table + bytes); if(byte == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain * the last directory start block index. This is used when calculating * the total uncompressed directory size. The directory bytes in the * last * block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, *inode_table + bytes); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, *inode_table + bytes); directory_start_block = dir_inode->dir.start_block; } else { SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, *inode_table + bytes); directory_start_block = dir_inode->ldir.start_block; } get_uid(id_table[dir_inode->base.uid]); get_guid(id_table[dir_inode->base.guid]); for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { SQUASHFS_SWAP_REG_INODE_HEADER(&inode, cur_ptr); TRACE("scan_inode_table: processing inode @ byte position " "0x%x, type 0x%x\n", (unsigned int) (cur_ptr - *inode_table), inode.inode_type); get_uid(id_table[inode.uid]); get_guid(id_table[inode.guid]); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i; long long start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, " "file_size %d, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { struct squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i; long long start; unsigned int *block_list; SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, cur_ptr); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; TRACE("scan_inode_table: extended regular " "file, file_size %lld, blocks %d\n", inode.file_size, blocks); block_list = malloc(blocks * sizeof(unsigned int)); if(block_list == NULL) { ERROR("Out of memory in block list " "malloc\n"); goto failed; } cur_ptr += sizeof(inode); SQUASHFS_SWAP_INTS(block_list, cur_ptr, blocks); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK (block_list[i]); add_file(start, inode.file_size, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { struct squashfs_symlink_inode_header inodep; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, cur_ptr); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; if (inode.inode_type == SQUASHFS_LSYMLINK_TYPE) cur_ptr += sizeof(unsigned int); break; } case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header dir_inode; SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(struct squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header dir_inode; int i; SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, cur_ptr); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(struct squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { struct squashfs_dir_index index; SQUASHFS_SWAP_DIR_INDEX(&index, cur_ptr); cur_ptr += sizeof(struct squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(struct squashfs_dev_inode_header); break; case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(struct squashfs_ldev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(struct squashfs_ipc_inode_header); break; case SQUASHFS_LFIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(struct squashfs_lipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(struct squashfs_ipc_inode_header); break; case SQUASHFS_LSOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(struct squashfs_lipc_inode_header); break; default: ERROR("Unknown inode type %d in " "scan_inode_table!\n", inode.inode_type); goto failed; } } printf("Read existing filesystem, %d inodes scanned\n", files); return TRUE; failed: free(*inode_table); return FALSE; } struct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source) { int res, bytes = 0; char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned)); res = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), sBlk); if(res == 0) goto failed_mount; SQUASHFS_INSWAP_SUPER_BLOCK(sBlk); if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) ERROR("Pre 4.0 big-endian filesystem on %s, appending" " to this is unsupported\n", source); else ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 4) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem." " Appending\nto SQUASHFS %d.%d filesystems is " "not supported. Please convert it to a " "SQUASHFS 4 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Filesystem on %s is %d.%d, which is a later " "filesystem version than I support\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } /* Check the compression type */ comp = lookup_compressor_id(sBlk->compression); if(!comp->supported) { ERROR("Filesystem on %s uses %s compression, this is" "unsupported by this version\n", source, comp->name); ERROR("Compressors available:\n"); display_compressors("", ""); goto failed_mount; } /* * Read extended superblock information from disk. * * Read compressor specific options from disk if present, and pass * to compressor to set compressor options. * * Note, if there's no compressor options present, the compressor * is still called to set the default options (the defaults may have * been changed by the user specifying options on the command * line which need to be over-ridden). */ if(SQUASHFS_COMP_OPTS(sBlk->flags)) { bytes = read_block(fd, sizeof(*sBlk), NULL, buffer); if(bytes == 0) goto failed_mount; } res = compressor_extract_options(comp, sBlk->block_size, buffer, bytes); if(res == -1) { ERROR("Compressor failed to set compressor options\n"); goto failed_mount; } printf("Found a valid %sSQUASHFS superblock on %s.\n", SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); printf("\tCompression used %s\n", comp->name); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tXattrs are %scompressed\n", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? "un" : ""); printf("\tFragments are %spresent in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : ""); printf("\tAlways_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not "); printf("\tDuplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not "); printf("\tXattrs are %sstored\n", SQUASHFS_NO_XATTRS(sBlk->flags) ? "not " : ""); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of ids %d\n", sBlk->no_ids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); TRACE("sBlk->xattr_id_table_start %llx\n", sBlk->xattr_id_table_start); printf("\n"); return comp; failed_mount: return NULL; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, struct squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { struct squashfs_dir_header dirh; char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1] __attribute__ ((aligned)); struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block = start; size += offset; directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1)); if(directory_table == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so " "far %d\n", start, bytes); last_start_block = start; byte = read_block(fd, start, &start, directory_table + bytes); if(byte == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, directory_table + bytes); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position " "0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, directory_table + bytes); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, " "inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } unsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk) { int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids); long long index[indexes]; int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids); unsigned int *id_table; int res, i; id_table = malloc(bytes); if(id_table == NULL) { ERROR("Failed to allocate id table\n"); return NULL; } res = read_fs_bytes(fd, sBlk->id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index); if(res == 0) { free(id_table); return NULL; } SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) id_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read id table block %d, from 0x%llx, length %d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read id table block %d, from 0x%llx, " "length %d\n", i, index[i], length); free(id_table); return NULL; } } SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); for(i = 0; i < sBlk->no_ids; i++) { TRACE("Adding id %d to id tables\n", id_table[i]); create_id(id_table[i]); } return id_table; } int read_fragment_table(int fd, struct squashfs_super_block *sBlk, struct squashfs_fragment_entry **fragment_table) { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; *fragment_table = malloc(sBlk->fragments * sizeof(struct squashfs_fragment_entry)); if(*fragment_table == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } res = read_fs_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), fragment_table_index); if(res == 0) { free(*fragment_table); return 0; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == 0) { ERROR("Failed to read fragment table block %d, from " "0x%llx, length %d\n", i, fragment_table_index[i], length); free(*fragment_table); return 0; } } for(i = 0; i < sBlk->fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]); return 1; } int read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk, squashfs_inode **inode_lookup_table) { int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes); int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes); long long index[indexes]; int res, i; if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK) return 1; *inode_lookup_table = malloc(lookup_bytes); if(*inode_lookup_table == NULL) { ERROR("Failed to allocate inode lookup table\n"); return 0; } res = read_fs_bytes(fd, sBlk->lookup_table_start, SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index); if(res == 0) { free(*inode_lookup_table); return 0; } SQUASHFS_INSWAP_LONG_LONGS(index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) *inode_lookup_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read inode lookup table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read inode lookup table block %d, " "from 0x%llx, length %d\n", i, index[i], length); free(*inode_lookup_table); return 0; } } SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); return 1; } long long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), struct squashfs_fragment_entry **fragment_table, squashfs_inode **inode_lookup_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start; long long end = sBlk->directory_table_start; long long root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode); unsigned int root_inode_block; union squashfs_inode_header inode; unsigned int *id_table; int res; printf("Scanning existing filesystem...\n"); if(get_xattrs(fd, sBlk) == 0) goto error; if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0) goto error; id_table = read_id_table(fd, sBlk); if(id_table == NULL) goto error; res = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count, id_table); if(res == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry); if(directory_table == NULL) { ERROR("read_filesystem: Could not read root directory" "\n"); goto error; } root_inode_start -= start; *cinode_table = malloc(root_inode_start); if(*cinode_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem inode table\n"); goto error; } res = read_fs_bytes(fd, start, root_inode_start, *cinode_table); if(res == 0) goto error; *cdirectory_table = malloc(*last_directory_block); if(*cdirectory_table == NULL) { ERROR("read_filesystem: failed to alloc space for " "existing filesystem directory table\n"); goto error; } res = read_fs_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if(res == 0) goto error; *data_cache = malloc(root_inode_offset + *root_inode_size); if(*data_cache == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); *directory_data_cache = malloc(*inode_dir_offset + *inode_dir_file_size); if(*directory_data_cache == NULL) { ERROR("read_filesystem: failed to alloc directory " "cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/others/squashfs-4.2-official/read_fs.h ================================================ #ifndef READ_FS_H #define READ_FS_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.h * */ #if __BYTE_ORDER == __BIG_ENDIAN #define SQUASHFS_SWAP_SHORTS(d, s, n) swap_le16_num(s, d, n) #define SQUASHFS_SWAP_INTS(d, s, n) swap_le32_num(s, d, n) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) swap_le64_num(s, d, n) #define SWAP_LE16(d, s) swap_le16(s, d) #define SWAP_LE32(d, s) swap_le32(s, d) #define SWAP_LE64(d, s) swap_le64(s, d) #else #define SQUASHFS_MEMCPY(d, s, n) memcpy(d, s, n) #define SQUASHFS_SWAP_SHORTS(d, s, n) memcpy(d, s, n * sizeof(short)) #define SQUASHFS_SWAP_INTS(d, s, n) memcpy(d, s, n * sizeof(int)) #define SQUASHFS_SWAP_LONG_LONGS(d, s, n) \ memcpy(d, s, n * sizeof(long long)) #endif #endif ================================================ FILE: src/others/squashfs-4.2-official/read_xattrs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_xattrs.c */ /* * Common xattr read code shared between mksquashfs and unsquashfs */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <string.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #include "squashfs_swap.h" #include "read_fs.h" #include "xattr.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("read_xattrs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) extern int read_fs_bytes(int, long long, int, void *); extern int read_block(int, long long, long long *, void *); static struct hash_entry { long long start; unsigned int offset; struct hash_entry *next; } *hash_table[65536]; static struct squashfs_xattr_id *xattr_ids; static void *xattrs = NULL; static long long xattr_table_start; /* * Prefix lookup table, storing mapping to/from prefix string and prefix id */ struct prefix prefix_table[] = { { "user.", SQUASHFS_XATTR_USER }, { "trusted.", SQUASHFS_XATTR_TRUSTED }, { "security.", SQUASHFS_XATTR_SECURITY }, { "", -1 } }; /* * store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ static int save_xattr_block(long long start, int offset) { struct hash_entry *hash_entry = malloc(sizeof(*hash_entry)); int hash = start & 0xffff; TRACE("save_xattr_block: start %lld, offset %d\n", start, offset); if(hash_entry == NULL) { ERROR("Failed to allocate hash entry\n"); return -1; } hash_entry->start = start; hash_entry->offset = offset; hash_entry->next = hash_table[hash]; hash_table[hash] = hash_entry; return 1; } /* * map from location of compressed block in fs -> * location of uncompressed block in memory */ static int get_xattr_block(long long start) { int hash = start & 0xffff; struct hash_entry *hash_entry = hash_table[hash]; for(; hash_entry; hash_entry = hash_entry->next) if(hash_entry->start == start) break; TRACE("get_xattr_block: start %lld, offset %d\n", start, hash_entry ? hash_entry->offset : -1); return hash_entry ? hash_entry->offset : -1; } /* * construct the xattr_list entry from the fs xattr, including * mapping name and prefix into a full name */ static int read_xattr_entry(struct xattr_list *xattr, struct squashfs_xattr_entry *entry, void *name) { int i, len, type = entry->type & XATTR_PREFIX_MASK; for(i = 0; prefix_table[i].type != -1; i++) if(prefix_table[i].type == type) break; if(prefix_table[i].type == -1) { ERROR("Unrecognised type in read_xattr_entry\n"); return 0; } len = strlen(prefix_table[i].prefix); xattr->full_name = malloc(len + entry->size + 1); if(xattr->full_name == NULL) { ERROR("Out of memory in read_xattr_entry\n"); return -1; } memcpy(xattr->full_name, prefix_table[i].prefix, len); memcpy(xattr->full_name + len, name, entry->size); xattr->full_name[len + entry->size] = '\0'; xattr->name = xattr->full_name + len; xattr->size = entry->size; xattr->type = type; return 1; } /* * Read and decompress the xattr id table and the xattr metadata. * This is cached in memory for later use by get_xattr() */ int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { int res, bytes, i, indexes, index_bytes, ids; long long *index, start, end; struct squashfs_xattr_table id_table; TRACE("read_xattrs_from_disk\n"); if(sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK) return SQUASHFS_INVALID_BLK; /* * Read xattr id table, containing start of xattr metadata and the * number of xattrs in the file system */ res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table); if(res == 0) return 0; SQUASHFS_INSWAP_XATTR_TABLE(&id_table); /* * Allocate and read the index to the xattr id table metadata * blocks */ ids = id_table.xattr_ids; xattr_table_start = id_table.xattr_table_start; index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids); indexes = SQUASHFS_XATTR_BLOCKS(ids); index = malloc(index_bytes); if(index == NULL) { ERROR("Failed to allocate index array\n"); return 0; } res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index); if(res ==0) goto failed1; SQUASHFS_INSWAP_LONG_LONGS(index, indexes); /* * Allocate enough space for the uncompressed xattr id table, and * read and decompress it */ bytes = SQUASHFS_XATTR_BYTES(ids); xattr_ids = malloc(bytes); if(xattr_ids == NULL) { ERROR("Failed to allocate xattr id table\n"); goto failed1; } for(i = 0; i < indexes; i++) { int length = read_block(fd, index[i], NULL, ((unsigned char *) xattr_ids) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr id table block %d, from 0x%llx, length " "%d\n", i, index[i], length); if(length == 0) { ERROR("Failed to read xattr id table block %d, " "from 0x%llx, length %d\n", i, index[i], length); goto failed2; } } /* * Read and decompress the xattr metadata * * Note the first xattr id table metadata block is immediately after * the last xattr metadata block, so we can use index[0] to work out * the end of the xattr metadata */ start = xattr_table_start; end = index[0]; for(i = 0; start < end; i++) { int length; void *x = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE); if(x == NULL) { ERROR("Failed to realloc xattr data\n"); goto failed3; } xattrs = x; /* store mapping from location of compressed block in fs -> * location of uncompressed block in memory */ res = save_xattr_block(start, i * SQUASHFS_METADATA_SIZE); if(res == -1) goto failed3; length = read_block(fd, start, &start, ((unsigned char *) xattrs) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read xattr block %d, length %d\n", i, length); if(length == 0) { ERROR("Failed to read xattr block %d\n", i); goto failed3; } } /* swap if necessary the xattr id entries */ for(i = 0; i < ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]); free(index); return ids; failed3: free(xattrs); failed2: free(xattr_ids); failed1: free(index); return 0; } /* * Construct and return the list of xattr name:value pairs for the passed xattr * id */ struct xattr_list *get_xattr(int i, unsigned int *count) { long long start; struct xattr_list *xattr_list = NULL; unsigned int offset; void *xptr; int j; TRACE("get_xattr\n"); *count = xattr_ids[i].count; start = SQUASHFS_XATTR_BLK(xattr_ids[i].xattr) + xattr_table_start; offset = SQUASHFS_XATTR_OFFSET(xattr_ids[i].xattr); xptr = xattrs + get_xattr_block(start) + offset; TRACE("get_xattr: xattr_id %d, count %d, start %lld, offset %d\n", i, *count, start, offset); for(j = 0; j < *count; j++) { struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; int res; xattr_list = realloc(xattr_list, (j + 1) * sizeof(struct xattr_list)); if(xattr_list == NULL) { ERROR("Out of memory in get_xattrs\n"); goto failed; } SQUASHFS_SWAP_XATTR_ENTRY(&entry, xptr); xptr += sizeof(entry); res = read_xattr_entry(&xattr_list[j], &entry, xptr); if(res != 1) goto failed; xptr += entry.size; TRACE("get_xattr: xattr %d, type %d, size %d, name %s\n", j, entry.type, entry.size, xattr_list[j].full_name); if(entry.type & SQUASHFS_XATTR_VALUE_OOL) { long long xattr; void *ool_xptr; xptr += sizeof(val); SQUASHFS_SWAP_LONG_LONGS(&xattr, xptr, 1); xptr += sizeof(xattr); start = SQUASHFS_XATTR_BLK(xattr) + xattr_table_start; offset = SQUASHFS_XATTR_OFFSET(xattr); ool_xptr = xattrs + get_xattr_block(start) + offset; SQUASHFS_SWAP_XATTR_VAL(&val, ool_xptr); xattr_list[j].value = ool_xptr + sizeof(val); } else { SQUASHFS_SWAP_XATTR_VAL(&val, xptr); xattr_list[j].value = xptr + sizeof(val); xptr += sizeof(val) + val.vsize; } TRACE("get_xattr: xattr %d, vsize %d\n", j, val.vsize); xattr_list[j].vsize = val.vsize; } return xattr_list; failed: free(xattr_list); return NULL; } ================================================ FILE: src/others/squashfs-4.2-official/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include "squashfs_fs.h" #include "mksquashfs.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) \ do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry *priority_list[65536]; extern int silent; extern void write_file(squashfs_inode *inode, struct dir_ent *dir_ent, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %d, st_ino " "%lld\n", path, priority, (int) buf.st_dev, (long long) buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is " "supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry"); ERROR(" should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to " "$PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source " "directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory " "test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) { ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more " "than one source entry! Please use an absolute path." "\n", path); return FALSE; } error: ERROR("Cannot stat sortlist entry \"%s\"\n", path); ERROR("This is probably because you're using the wrong file\n"); ERROR("path relative to the source directories\n"); /* * Historical note * Failure to stat a sortlist entry is deliberately ignored, even * though it is an error. Squashfs release 2.2 changed the behaviour * to treat it as a fatal error, but it was changed back to * the original behaviour to ignore it in release 2.2-r2 following * feedback from users at the time. */ return TRUE; } int generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { int res; priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->inode->root_entry) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: res = add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); if(res == FALSE) return FALSE; break; case S_IFDIR: res = generate_file_priorities(dir_ent->dir, priority, buf); if(res == FALSE) return FALSE; break; } } dir->current_count = 0; return TRUE; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int res, priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) { res = add_sort_list(sort_filename, priority, source, source_path); if(res == FALSE) return FALSE; } else ERROR("Sort file %s, priority %d outside range of " "-32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { write_file(&inode, entry->dir, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s" "\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } else INFO("file %s, uncompressed size %lld bytes " "LINK\n", entry->dir->pathname, (long long) entry->dir->inode->buf.st_size); } } ================================================ FILE: src/others/squashfs-4.2-official/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; #endif ================================================ FILE: src/others/squashfs-4.2-official/squashfs_compat.h ================================================ #ifndef SQUASHFS_COMPAT #define SQUASHFS_COMPAT /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_compat.h */ /* * definitions for structures on disk - layout 3.x */ #define SQUASHFS_CHECK 2 #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 struct squashfs_super_block_3 { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; } __attribute__ ((packed)); struct squashfs_dir_index_3 { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER_3 \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; } __attribute__ ((packed)); struct squashfs_ipc_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; squashfs_block start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; squashfs_block start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_3 { SQUASHFS_BASE_INODE_HEADER_3; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index_3 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_3 { struct squashfs_base_inode_header_3 base; struct squashfs_dev_inode_header_3 dev; struct squashfs_symlink_inode_header_3 symlink; struct squashfs_reg_inode_header_3 reg; struct squashfs_lreg_inode_header_3 lreg; struct squashfs_dir_inode_header_3 dir; struct squashfs_ldir_inode_header_3 ldir; struct squashfs_ipc_inode_header_3 ipc; }; struct squashfs_dir_entry_3 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header_3 { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry_3 { long long start_block; unsigned int size; unsigned int pending; } __attribute__ ((packed)); typedef struct squashfs_super_block_3 squashfs_super_block_3; typedef struct squashfs_dir_index_3 squashfs_dir_index_3; typedef struct squashfs_base_inode_header_3 squashfs_base_inode_header_3; typedef struct squashfs_ipc_inode_header_3 squashfs_ipc_inode_header_3; typedef struct squashfs_dev_inode_header_3 squashfs_dev_inode_header_3; typedef struct squashfs_symlink_inode_header_3 squashfs_symlink_inode_header_3; typedef struct squashfs_reg_inode_header_3 squashfs_reg_inode_header_3; typedef struct squashfs_lreg_inode_header_3 squashfs_lreg_inode_header_3; typedef struct squashfs_dir_inode_header_3 squashfs_dir_inode_header_3; typedef struct squashfs_ldir_inode_header_3 squashfs_ldir_inode_header_3; typedef struct squashfs_dir_entry_3 squashfs_dir_entry_3; typedef struct squashfs_dir_header_3 squashfs_dir_header_3; typedef struct squashfs_fragment_entry_3 squashfs_fragment_entry_3; /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block_3));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER_3(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ipc_inode_header_3))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dev_inode_header_3)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_symlink_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_reg_inode_header_3));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_lreg_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_dir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_3(s, d, \ sizeof(struct squashfs_ldir_inode_header_3));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_3));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_3));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_3));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_INODE_T_3(s, d) SQUASHFS_SWAP_LONG_LONGS_3(s, d, 1) #define SQUASHFS_SWAP_SHORTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS_3(s, d, n) SQUASHFS_SWAP_LONG_LONGS_3(s, d, n) #define SQUASHFS_SWAP_FRAGMENT_ENTRY_3(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_3));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_3(A) ((A) * sizeof(struct squashfs_fragment_entry_3)) #define SQUASHFS_FRAGMENT_INDEX_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_3(A) (SQUASHFS_FRAGMENT_BYTES_3(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_3(A) ((SQUASHFS_FRAGMENT_BYTES_3(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_3(A) (SQUASHFS_FRAGMENT_INDEXES_3(A) *\ sizeof(long long)) /* * definitions for structures on disk - layout 1.x */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); union squashfs_inode_header_1 { struct squashfs_base_inode_header_1 base; struct squashfs_dev_inode_header_1 dev; struct squashfs_symlink_inode_header_1 symlink; struct squashfs_reg_inode_header_1 reg; struct squashfs_dir_inode_header_1 dir; struct squashfs_ipc_inode_header_1 ipc; }; typedef struct squashfs_dir_index_1 squashfs_dir_index_1; typedef struct squashfs_base_inode_header_1 squashfs_base_inode_header_1; typedef struct squashfs_ipc_inode_header_1 squashfs_ipc_inode_header_1; typedef struct squashfs_dev_inode_header_1 squashfs_dev_inode_header_1; typedef struct squashfs_symlink_inode_header_1 squashfs_symlink_inode_header_1; typedef struct squashfs_reg_inode_header_1 squashfs_reg_inode_header_1; typedef struct squashfs_dir_inode_header_1 squashfs_dir_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } /* * definitions for structures on disk - layout 2.x */ struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); typedef struct squashfs_dir_index_2 squashfs_dir_index_2; typedef struct squashfs_base_inode_header_2 squashfs_base_inode_header_2; typedef struct squashfs_ipc_inode_header_2 squashfs_ipc_inode_header_2; typedef struct squashfs_dev_inode_header_2 squashfs_dev_inode_header_2; typedef struct squashfs_symlink_inode_header_2 squashfs_symlink_inode_header_2; typedef struct squashfs_reg_inode_header_2 squashfs_reg_inode_header_2; typedef struct squashfs_lreg_inode_header_2 squashfs_lreg_inode_header_2; typedef struct squashfs_dir_inode_header_2 squashfs_dir_inode_header_2; typedef struct squashfs_ldir_inode_header_2 squashfs_ldir_inode_header_2; typedef struct squashfs_dir_entry_2 squashfs_dir_entry_2; typedef struct squashfs_dir_header_2 squashfs_dir_header_2; typedef struct squashfs_fragment_entry_2 squashfs_fragment_entry_2; #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS_3(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) ((A) * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif ================================================ FILE: src/others/squashfs-4.2-official/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE #define SQUASHFS_MAJOR 4 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /* Max number of uids and gids */ #define SQUASHFS_IDS 65536 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_XATTR ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 #define SQUASHFS_NOX 8 #define SQUASHFS_NO_XATTR 9 #define SQUASHFS_COMP_OPT 10 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) #define SQUASHFS_UNCOMPRESSED_XATTRS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOX) #define SQUASHFS_NO_XATTRS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_XATTR) #define SQUASHFS_COMP_OPTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_COMP_OPT) #define SQUASHFS_MKFLAGS(noi, nod, nof, nox, no_frag, always_frag, \ duplicate_checking, exportable, no_xattr, comp_opt) (noi | \ (nod << 1) | (nof << 3) | (no_frag << 4) | \ (always_frag << 5) | (duplicate_checking << 6) | \ (exportable << 7) | (nox << 8) | (no_xattr << 9) | \ (comp_opt << 10)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 #define SQUASHFS_LSYMLINK_TYPE 10 #define SQUASHFS_LBLKDEV_TYPE 11 #define SQUASHFS_LCHRDEV_TYPE 12 #define SQUASHFS_LFIFO_TYPE 13 #define SQUASHFS_LSOCKET_TYPE 14 /* Xattr types */ #define SQUASHFS_XATTR_USER 0 #define SQUASHFS_XATTR_TRUSTED 1 #define SQUASHFS_XATTR_SECURITY 2 #define SQUASHFS_XATTR_VALUE_OOL 256 #define SQUASHFS_XATTR_PREFIX_MASK 0xff /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) /* inode lookup table defines */ #define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode)) #define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ sizeof(long long)) /* uid lookup table defines */ #define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int)) #define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ sizeof(long long)) /* xattr id lookup table defines */ #define SQUASHFS_XATTR_BYTES(A) ((A) * sizeof(struct squashfs_xattr_id)) #define SQUASHFS_XATTR_BLOCK(A) (SQUASHFS_XATTR_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCK_OFFSET(A) (SQUASHFS_XATTR_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCKS(A) ((SQUASHFS_XATTR_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_XATTR_BLOCK_BYTES(A) (SQUASHFS_XATTR_BLOCKS(A) *\ sizeof(long long)) #define SQUASHFS_XATTR_BLK(A) ((unsigned int) ((A) >> 16)) #define SQUASHFS_XATTR_OFFSET(A) ((unsigned int) ((A) & 0xffff)) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* meta index cache */ #define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) #define SQUASHFS_META_ENTRIES 31 #define SQUASHFS_META_NUMBER 8 #define SQUASHFS_SLOTS 4 struct meta_entry { long long data_block; unsigned int index_block; unsigned short offset; unsigned short pad; }; struct meta_index { unsigned int inode_number; unsigned int offset; unsigned short entries; unsigned short skip; unsigned short locked; unsigned short pad; struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; }; /* * definitions for structures on disk */ typedef long long squashfs_block; typedef long long squashfs_inode; #define ZLIB_COMPRESSION 1 #define LZMA_COMPRESSION 2 #define LZO_COMPRESSION 3 #define XZ_COMPRESSION 4 struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int mkfs_time /* time of filesystem creation */; unsigned int block_size; unsigned int fragments; unsigned short compression; unsigned short block_log; unsigned short flags; unsigned short no_ids; unsigned short s_major; unsigned short s_minor; squashfs_inode root_inode; long long bytes_used; long long id_table_start; long long xattr_id_table_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long lookup_table_start; }; struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned int size; unsigned char name[0]; }; struct squashfs_base_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; }; struct squashfs_ipc_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; }; struct squashfs_lipc_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int xattr; }; struct squashfs_dev_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int rdev; }; struct squashfs_ldev_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int rdev; unsigned int xattr; }; struct squashfs_symlink_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int symlink_size; char symlink[0]; }; struct squashfs_reg_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned int block_list[0]; }; struct squashfs_lreg_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; squashfs_block start_block; long long file_size; long long sparse; unsigned int nlink; unsigned int fragment; unsigned int offset; unsigned int xattr; unsigned int block_list[0]; }; struct squashfs_dir_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int start_block; unsigned int nlink; unsigned short file_size; unsigned short offset; unsigned int parent_inode; }; struct squashfs_ldir_inode_header { unsigned short inode_type; unsigned short mode; unsigned short uid; unsigned short guid; unsigned int mtime; unsigned int inode_number; unsigned int nlink; unsigned int file_size; unsigned int start_block; unsigned int parent_inode; unsigned short i_count; unsigned short offset; unsigned int xattr; struct squashfs_dir_index index[0]; }; union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_ldev_inode_header ldev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; struct squashfs_lipc_inode_header lipc; }; struct squashfs_dir_entry { unsigned short offset; short inode_number; unsigned short type; unsigned short size; char name[0]; }; struct squashfs_dir_header { unsigned int count; unsigned int start_block; unsigned int inode_number; }; struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; }; struct squashfs_xattr_entry { unsigned short type; unsigned short size; char data[0]; }; struct squashfs_xattr_val { unsigned int vsize; char value[0]; }; struct squashfs_xattr_id { long long xattr; unsigned int count; unsigned int size; }; struct squashfs_xattr_table { long long xattr_table_start; unsigned int xattr_ids; unsigned int unused; }; #endif ================================================ FILE: src/others/squashfs-4.2-official/squashfs_swap.h ================================================ #ifndef SQUASHFS_SWAP_H #define SQUASHFS_SWAP_H /* * Squashfs * * Copyright (c) 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_swap.h */ /* * macros to convert each stucture from big endian to little endian */ #if __BYTE_ORDER == __BIG_ENDIAN #include <stddef.h> extern void swap_le16(void *, void *); extern void swap_le32(void *, void *); extern void swap_le64(void *, void *); extern void swap_le16_num(void *, void *, int); extern void swap_le32_num(void *, void *, int); extern void swap_le64_num(void *, void *, int); extern unsigned short inswap_le16(unsigned short); extern unsigned int inswap_le32(unsigned int); extern long long inswap_le64(long long); extern void inswap_le16_num(unsigned short *, int); extern void inswap_le32_num(unsigned int *, int); extern void inswap_le64_num(long long *, int); #define _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, s_magic, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, inodes, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, mkfs_time, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, block_size, struct squashfs_super_block);\ SWAP_FUNC(32, s, d, fragments, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, compression, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, block_log, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, flags, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, no_ids, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, s_major, struct squashfs_super_block);\ SWAP_FUNC(16, s, d, s_minor, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, root_inode, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, bytes_used, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, id_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, xattr_id_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, inode_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, directory_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, fragment_table_start, struct squashfs_super_block);\ SWAP_FUNC(64, s, d, lookup_table_start, struct squashfs_super_block);\ } #define _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, index, struct squashfs_dir_index);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_index);\ SWAP_FUNC(32, s, d, size, struct squashfs_dir_index);\ } #define _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_base_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_base_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_base_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_base_inode_header);\ } #define _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ipc_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ipc_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ipc_inode_header);\ } #define _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_lipc_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_lipc_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_lipc_inode_header);\ } #define _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_dev_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_dev_inode_header);\ SWAP_FUNC(32, s, d, rdev, struct squashfs_dev_inode_header);\ } #define _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ldev_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, rdev, struct squashfs_ldev_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_ldev_inode_header);\ } #define _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_symlink_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_symlink_inode_header);\ SWAP_FUNC(32, s, d, symlink_size, struct squashfs_symlink_inode_header);\ } #define _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_reg_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, fragment, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, offset, struct squashfs_reg_inode_header);\ SWAP_FUNC(32, s, d, file_size, struct squashfs_reg_inode_header);\ } #define _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_lreg_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, start_block, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, file_size, struct squashfs_lreg_inode_header);\ SWAP_FUNC(64, s, d, sparse, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, fragment, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, offset, struct squashfs_lreg_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_lreg_inode_header);\ } #define _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, file_size, struct squashfs_dir_inode_header);\ SWAP_FUNC(16, s, d, offset, struct squashfs_dir_inode_header);\ SWAP_FUNC(32, s, d, parent_inode, struct squashfs_dir_inode_header);\ } #define _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, inode_type, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, mode, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, uid, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, guid, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, mtime, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, nlink, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, file_size, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, parent_inode, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, i_count, struct squashfs_ldir_inode_header);\ SWAP_FUNC(16, s, d, offset, struct squashfs_ldir_inode_header);\ SWAP_FUNC(32, s, d, xattr, struct squashfs_ldir_inode_header);\ } #define _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, offset, struct squashfs_dir_entry);\ SWAP_FUNC##S(16, s, d, inode_number, struct squashfs_dir_entry);\ SWAP_FUNC(16, s, d, type, struct squashfs_dir_entry);\ SWAP_FUNC(16, s, d, size, struct squashfs_dir_entry);\ } #define _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, count, struct squashfs_dir_header);\ SWAP_FUNC(32, s, d, start_block, struct squashfs_dir_header);\ SWAP_FUNC(32, s, d, inode_number, struct squashfs_dir_header);\ } #define _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, start_block, struct squashfs_fragment_entry);\ SWAP_FUNC(32, s, d, size, struct squashfs_fragment_entry);\ } #define _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_FUNC) {\ SWAP_FUNC(16, s, d, type, struct squashfs_xattr_entry);\ SWAP_FUNC(16, s, d, size, struct squashfs_xattr_entry);\ } #define _SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_FUNC) {\ SWAP_FUNC(32, s, d, vsize, struct squashfs_xattr_val);\ } #define _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, xattr, struct squashfs_xattr_id);\ SWAP_FUNC(32, s, d, count, struct squashfs_xattr_id);\ SWAP_FUNC(32, s, d, size, struct squashfs_xattr_id);\ } #define _SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_FUNC) {\ SWAP_FUNC(64, s, d, xattr_table_start, struct squashfs_xattr_table);\ SWAP_FUNC(32, s, d, xattr_ids, struct squashfs_xattr_table);\ } /* big endian architecture copy and swap macros */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ _SQUASHFS_SWAP_DIR_INDEX(s, d, SWAP_LE) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ _SQUASHFS_SWAP_DIR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ _SQUASHFS_SWAP_DIR_HEADER(s, d, SWAP_LE) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \ _SQUASHFS_SWAP_XATTR_ENTRY(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_VAL(s, d) \ _SQUASHFS_SWAP_XATTR_VAL(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_ID(s, d) \ _SQUASHFS_SWAP_XATTR_ID(s, d, SWAP_LE) #define SQUASHFS_SWAP_XATTR_TABLE(s, d) \ _SQUASHFS_SWAP_XATTR_TABLE(s, d, SWAP_LE) #define SWAP_LE(bits, s, d, field, type) \ SWAP_LE##bits(((void *)(s)) + offsetof(type, field), \ ((void *)(d)) + offsetof(type, field)) #define SWAP_LES(bits, s, d, field, type) \ SWAP_LE(bits, s, d, field, type) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \ SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) /* big endian architecture swap in-place macros */ #define SQUASHFS_INSWAP_SUPER_BLOCK(s) \ _SQUASHFS_SWAP_SUPER_BLOCK(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INDEX(s) \ _SQUASHFS_SWAP_DIR_INDEX(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) \ _SQUASHFS_SWAP_BASE_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_IPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s) \ _SQUASHFS_SWAP_LIPC_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_DEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDEV_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) \ _SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) \ _SQUASHFS_SWAP_REG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) \ _SQUASHFS_SWAP_LREG_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_DIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) \ _SQUASHFS_SWAP_LDIR_INODE_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_ENTRY(s) \ _SQUASHFS_SWAP_DIR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_DIR_HEADER(s) \ _SQUASHFS_SWAP_DIR_HEADER(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) \ _SQUASHFS_SWAP_FRAGMENT_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_ENTRY(s) \ _SQUASHFS_SWAP_XATTR_ENTRY(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_VAL(s) \ _SQUASHFS_SWAP_XATTR_VAL(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_ID(s) \ _SQUASHFS_SWAP_XATTR_ID(s, s, INSWAP_LE) #define SQUASHFS_INSWAP_XATTR_TABLE(s) \ _SQUASHFS_SWAP_XATTR_TABLE(s, s, INSWAP_LE) #define INSWAP_LE(bits, s, d, field, type) \ (s)->field = inswap_le##bits((s)->field) #define INSWAP_LES(bits, s, d, field, type) \ (s)->field = (short) inswap_le##bits((unsigned short) \ (s)->field) #define SQUASHFS_INSWAP_INODE_T(s) s = inswap_le64(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) inswap_le64_num(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) inswap_le16_num(s, n) #define SQUASHFS_INSWAP_INTS(s, n) inswap_le32_num(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) inswap_le64_num(s, n) #else /* little endian architecture, just copy */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INDEX(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LIPC_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDEV_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_DIR_HEADER(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_ENTRY(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_VAL(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_ID(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_XATTR_TABLE(s, d) \ SQUASHFS_MEMCPY(s, d, sizeof(*(s))) #define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) \ SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) /* little endian architecture, data already in place so do nothing */ #define SQUASHFS_INSWAP_SUPER_BLOCK(s) #define SQUASHFS_INSWAP_DIR_INDEX(s) #define SQUASHFS_INSWAP_BASE_INODE_HEADER(s) #define SQUASHFS_INSWAP_IPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_LIPC_INODE_HEADER(s) #define SQUASHFS_INSWAP_DEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDEV_INODE_HEADER(s) #define SQUASHFS_INSWAP_SYMLINK_INODE_HEADER(s) #define SQUASHFS_INSWAP_REG_INODE_HEADER(s) #define SQUASHFS_INSWAP_LREG_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_LDIR_INODE_HEADER(s) #define SQUASHFS_INSWAP_DIR_ENTRY(s) #define SQUASHFS_INSWAP_DIR_HEADER(s) #define SQUASHFS_INSWAP_FRAGMENT_ENTRY(s) #define SQUASHFS_INSWAP_XATTR_ENTRY(s) #define SQUASHFS_INSWAP_XATTR_VAL(s) #define SQUASHFS_INSWAP_XATTR_ID(s) #define SQUASHFS_INSWAP_XATTR_TABLE(s) #define SQUASHFS_INSWAP_INODE_T(s) #define SQUASHFS_INSWAP_FRAGMENT_INDEXES(s, n) #define SQUASHFS_INSWAP_LOOKUP_BLOCKS(s, n) #define SQUASHFS_INSWAP_ID_BLOCKS(s, n) #define SQUASHFS_INSWAP_SHORTS(s, n) #define SQUASHFS_INSWAP_INTS(s, n) #define SQUASHFS_INSWAP_LONG_LONGS(s, n) #endif #endif ================================================ FILE: src/others/squashfs-4.2-official/swap.c ================================================ /* * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * swap.c */ #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #if __BYTE_ORDER == __BIG_ENDIAN void swap_le16(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[1]; d[1] = s[0]; } void swap_le32(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } void swap_le64(void *src, void *dest) { unsigned char *s = src; unsigned char *d = dest; d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; d[3] = s[4]; d[4] = s[3]; d[5] = s[2]; d[6] = s[1]; d[7] = s[0]; } unsigned short inswap_le16(unsigned short num) { return (num >> 8) | ((num & 0xff) << 8); } unsigned int inswap_le32(unsigned int num) { return (num >> 24) | ((num & 0xff0000) >> 8) | ((num & 0xff00) << 8) | ((num & 0xff) << 24); } long long inswap_le64(long long n) { unsigned long long num = n; return (num >> 56) | ((num & 0xff000000000000LL) >> 40) | ((num & 0xff0000000000LL) >> 24) | ((num & 0xff00000000LL) >> 8) | ((num & 0xff000000) << 8) | ((num & 0xff0000) << 24) | ((num & 0xff00) << 40) | ((num & 0xff) << 56); } #define SWAP_LE_NUM(BITS) \ void swap_le##BITS##_num(void *s, void *d, int n) \ {\ int i;\ for(i = 0; i < n; i++, s += BITS / 8, d += BITS / 8)\ swap_le##BITS(s, d);\ } SWAP_LE_NUM(16) SWAP_LE_NUM(32) SWAP_LE_NUM(64) #define INSWAP_LE_NUM(BITS, TYPE) \ void inswap_le##BITS##_num(TYPE *s, int n) \ {\ int i;\ for(i = 0; i < n; i++)\ s[i] = inswap_le##BITS(s[i]);\ } INSWAP_LE_NUM(16, unsigned short) INSWAP_LE_NUM(32, unsigned int) INSWAP_LE_NUM(64, long long) #endif ================================================ FILE: src/others/squashfs-4.2-official/unsquash-1.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-1.c */ #include "unsquashfs.h" #include "squashfs_compat.h" void read_block_list_1(unsigned int *block_list, char *block_ptr, int blocks) { unsigned short block_size; int i; TRACE("read_block_list: blocks %d\n", blocks); for(i = 0; i < blocks; i++, block_ptr += 2) { if(swap) { unsigned short sblock_size; memcpy(&sblock_size, block_ptr, sizeof(unsigned short)); SQUASHFS_SWAP_SHORTS_3((&block_size), &sblock_size, 1); } else memcpy(&block_size, block_ptr, sizeof(unsigned short)); block_list[i] = SQUASHFS_COMPRESSED_SIZE(block_size) | (SQUASHFS_COMPRESSED(block_size) ? 0 : SQUASHFS_COMPRESSED_BIT_BLOCK); } } int read_fragment_table_1() { TRACE("read_fragment_table\n"); return TRUE; } struct inode *read_inode_1(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_1 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_1(&header.base, &sinode, sizeof(squashfs_base_inode_header_1)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.uid = (uid_t) uid_table[(header.base.inode_type - 1) / SQUASHFS_TYPES * 16 + header.base.uid]; if(header.base.inode_type == SQUASHFS_IPC_TYPE) { squashfs_ipc_inode_header_1 *inodep = &header.ipc; if(swap) { squashfs_ipc_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_IPC_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); if(inodep->type == SQUASHFS_SOCKET_TYPE) { i.mode = S_IFSOCK | header.base.mode; i.type = SQUASHFS_SOCKET_TYPE; } else { i.mode = S_IFIFO | header.base.mode; i.type = SQUASHFS_FIFO_TYPE; } i.uid = (uid_t) uid_table[inodep->offset * 16 + inodep->uid]; } else { i.mode = lookup_type[(header.base.inode_type - 1) % SQUASHFS_TYPES + 1] | header.base.mode; i.type = (header.base.inode_type - 1) % SQUASHFS_TYPES + 1; } i.xattr = SQUASHFS_INVALID_XATTR; i.gid = header.base.guid == 15 ? i.uid : (uid_t) guid_table[header.base.guid]; i.time = sBlk.s.mkfs_time; i.inode_number = inode_number ++; switch(i.type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_1 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_1 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_1 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_1(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.blocks = (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log; i.start = inode->start_block; i.block_ptr = block_ptr + sizeof(*inode); i.fragment = 0; i.frag_bytes = 0; i.offset = 0; i.sparse = 0; break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_1 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_1), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_1 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_1 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_1(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: { i.data = 0; break; } default: EXIT_UNSQUASH("Unknown inode type %d in " " read_inode_header_1!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_1(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_2 dirh; char buffer[sizeof(squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); squashfs_dir_entry_2 *dire = (squashfs_dir_entry_2 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_2 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_2 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_1() { int res; TRACE("read_uids_guids: no_uids %d, no_guids %d\n", sBlk.no_uids, sBlk.no_guids); uid_table = malloc((sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int)); if(uid_table == NULL) { ERROR("read_uids_guids: failed to allocate uid/gid table\n"); return FALSE; } guid_table = uid_table + sBlk.no_uids; if(swap) { unsigned int suid_table[sBlk.no_uids + sBlk.no_guids]; res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), suid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } SQUASHFS_SWAP_INTS_3(uid_table, suid_table, sBlk.no_uids + sBlk.no_guids); } else { res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids + sBlk.no_guids) * sizeof(unsigned int), uid_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read uid/gid table" "\n"); return FALSE; } } return TRUE; } ================================================ FILE: src/others/squashfs-4.2-official/unsquash-2.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-2.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_2 *fragment_table; void read_block_list_2(unsigned int *block_list, char *block_ptr, int blocks) { TRACE("read_block_list: blocks %d\n", blocks); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS_3(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); } int read_fragment_table_2() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_2(sBlk.s.fragments); unsigned int fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(squashfs_fragment_entry_2)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { unsigned int sfragment_table_index[indexes]; res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_2(fragment_table_index, sfragment_table_index, indexes); } else { res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_2 sfragment; for(i = 0; i < sBlk.s.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_2((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_2)); } } return TRUE; } void read_fragment_2(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_2 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_2(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_2 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_2(&header.base, &sinode, sizeof(squashfs_base_inode_header_2)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.xattr = SQUASHFS_INVALID_XATTR; i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = sBlk.s.mkfs_time; i.inode_number = inode_number++; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_2 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_2(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_2 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_2(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.time = inode->mtime; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_2 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_2 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_2(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.time = inode->mtime; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_2 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_2), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_2 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_2 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: EXIT_UNSQUASH("Unknown inode type %d in " "read_inode_header_2!\n", header.base.inode_type); } return &i; } ================================================ FILE: src/others/squashfs-4.2-official/unsquash-3.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-3.c */ #include "unsquashfs.h" #include "squashfs_compat.h" static squashfs_fragment_entry_3 *fragment_table; int read_fragment_table_3() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.s.fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(squashfs_fragment_entry_3)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); if(swap) { long long sfragment_table_index[indexes]; res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), sfragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } SQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index, sfragment_table_index, indexes); } else { res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table block\n"); return FALSE; } } if(swap) { squashfs_fragment_entry_3 sfragment; for(i = 0; i < sBlk.s.fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry_3)); } } return TRUE; } void read_fragment_3(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); squashfs_fragment_entry_3 *fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_3(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header_3 header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); if(swap) { squashfs_base_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER_3(&header.base, &sinode, sizeof(squashfs_base_inode_header_3)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); i.xattr = SQUASHFS_INVALID_XATTR; i.uid = (uid_t) uid_table[header.base.uid]; i.gid = header.base.guid == SQUASHFS_GUIDS ? i.uid : (uid_t) guid_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header_3 *inode = &header.dir; if(swap) { squashfs_dir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER_3(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header_3 *inode = &header.ldir; if(swap) { squashfs_ldir_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER_3(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; break; } case SQUASHFS_FILE_TYPE: { squashfs_reg_inode_header_3 *inode = &header.reg; if(swap) { squashfs_reg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header_3 *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header_3 sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER_3(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.s.block_size - 1) >> sBlk.s.block_log : inode->file_size >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 1; i.block_ptr = block_ptr + sizeof(*inode); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header_3 *inodep = &header.symlink; if(swap) { squashfs_symlink_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.symlink = malloc(inodep->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(squashfs_symlink_inode_header_3), inodep->symlink_size); i.symlink[inodep->symlink_size] = '\0'; i.data = inodep->symlink_size; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header_3 *inodep = &header.dev; if(swap) { squashfs_dev_inode_header_3 sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER_3(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); i.data = inodep->rdev; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; break; default: EXIT_UNSQUASH("Unknown inode type %d in read_inode!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_3(unsigned int block_start, unsigned int offset, struct inode **i) { squashfs_dir_header_3 dirh; char buffer[sizeof(squashfs_dir_entry_3) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); squashfs_dir_entry_3 *dire = (squashfs_dir_entry_3 *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes - 3; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header_3 sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER_3(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry_3 sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY_3(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(*dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } ================================================ FILE: src/others/squashfs-4.2-official/unsquash-4.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash-4.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "read_fs.h" static struct squashfs_fragment_entry *fragment_table; static unsigned int *id_table; int read_fragment_table_4() { int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.s.fragments); long long fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes " "from 0x%llx\n", sBlk.s.fragments, indexes, sBlk.s.fragment_table_start); if(sBlk.s.fragments == 0) return TRUE; fragment_table = malloc(sBlk.s.fragments * sizeof(struct squashfs_fragment_entry)); if(fragment_table == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate " "fragment table\n"); res = read_fs_bytes(fd, sBlk.s.fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.s.fragments), fragment_table_index); if(res == FALSE) { ERROR("read_fragment_table: failed to read fragment table " "index\n"); return FALSE; } SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE)); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); if(length == FALSE) { ERROR("read_fragment_table: failed to read fragment " "table index\n"); return FALSE; } } for(i = 0; i < sBlk.s.fragments; i++) SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]); return TRUE; } void read_fragment_4(unsigned int fragment, long long *start_block, int *size) { TRACE("read_fragment: reading fragment %d\n", fragment); struct squashfs_fragment_entry *fragment_entry; fragment_entry = &fragment_table[fragment]; *start_block = fragment_entry->start_block; *size = fragment_entry->size; } struct inode *read_inode_4(unsigned int start_block, unsigned int offset) { static union squashfs_inode_header header; long long start = sBlk.s.inode_table_start + start_block; int bytes = lookup_entry(inode_table_hash, start); char *block_ptr = inode_table + bytes + offset; static struct inode i; TRACE("read_inode: reading inode [%d:%d]\n", start_block, offset); if(bytes == -1) EXIT_UNSQUASH("read_inode: inode table block %lld not found\n", start); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, block_ptr); i.uid = (uid_t) id_table[header.base.uid]; i.gid = (uid_t) id_table[header.base.guid]; i.mode = lookup_type[header.base.inode_type] | header.base.mode; i.type = header.base.inode_type; i.time = header.base.mtime; i.inode_number = header.base.inode_number; switch(header.base.inode_type) { case SQUASHFS_DIR_TYPE: { struct squashfs_dir_inode_header *inode = &header.dir; SQUASHFS_SWAP_DIR_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LDIR_TYPE: { struct squashfs_ldir_inode_header *inode = &header.ldir; SQUASHFS_SWAP_LDIR_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.offset = inode->offset; i.start = inode->start_block; i.xattr = inode->xattr; break; } case SQUASHFS_FILE_TYPE: { struct squashfs_reg_inode_header *inode = &header.reg; SQUASHFS_SWAP_REG_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (i.data + sBlk.s.block_size - 1) >> sBlk.s.block_log : i.data >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = 0; i.block_ptr = block_ptr + sizeof(*inode); i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LREG_TYPE: { struct squashfs_lreg_inode_header *inode = &header.lreg; SQUASHFS_SWAP_LREG_INODE_HEADER(inode, block_ptr); i.data = inode->file_size; i.frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk.s.block_size; i.fragment = inode->fragment; i.offset = inode->offset; i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk.s.block_size - 1) >> sBlk.s.block_log : inode->file_size >> sBlk.s.block_log; i.start = inode->start_block; i.sparse = inode->sparse != 0; i.block_ptr = block_ptr + sizeof(*inode); i.xattr = inode->xattr; break; } case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: { struct squashfs_symlink_inode_header *inode = &header.symlink; SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inode, block_ptr); i.symlink = malloc(inode->symlink_size + 1); if(i.symlink == NULL) EXIT_UNSQUASH("read_inode: failed to malloc " "symlink data\n"); strncpy(i.symlink, block_ptr + sizeof(struct squashfs_symlink_inode_header), inode->symlink_size); i.symlink[inode->symlink_size] = '\0'; i.data = inode->symlink_size; if(header.base.inode_type == SQUASHFS_LSYMLINK_TYPE) SQUASHFS_SWAP_INTS(&i.xattr, block_ptr + sizeof(struct squashfs_symlink_inode_header) + inode->symlink_size, 1); else i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { struct squashfs_dev_inode_header *inode = &header.dev; SQUASHFS_SWAP_DEV_INODE_HEADER(inode, block_ptr); i.data = inode->rdev; i.xattr = SQUASHFS_INVALID_XATTR; break; } case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { struct squashfs_ldev_inode_header *inode = &header.ldev; SQUASHFS_SWAP_LDEV_INODE_HEADER(inode, block_ptr); i.data = inode->rdev; i.xattr = inode->xattr; break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_SOCKET_TYPE: i.data = 0; i.xattr = SQUASHFS_INVALID_XATTR; break; case SQUASHFS_LFIFO_TYPE: case SQUASHFS_LSOCKET_TYPE: { struct squashfs_lipc_inode_header *inode = &header.lipc; SQUASHFS_SWAP_LIPC_INODE_HEADER(inode, block_ptr); i.data = 0; i.xattr = inode->xattr; break; } default: EXIT_UNSQUASH("Unknown inode type %d in read_inode!\n", header.base.inode_type); } return &i; } struct dir *squashfs_opendir_4(unsigned int block_start, unsigned int offset, struct inode **i) { struct squashfs_dir_header dirh; char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1] __attribute__((aligned)); struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; long long start; int bytes; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); *i = s_ops.read_inode(block_start, offset); start = sBlk.s.directory_table_start + (*i)->start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) EXIT_UNSQUASH("squashfs_opendir: directory block %d not " "found!\n", block_start); bytes += (*i)->offset; size = (*i)->data + bytes - 3; dir = malloc(sizeof(struct dir)); if(dir == NULL) EXIT_UNSQUASH("squashfs_opendir: malloc failed!\n"); dir->dir_count = 0; dir->cur_entry = 0; dir->mode = (*i)->mode; dir->uid = (*i)->uid; dir->guid = (*i)->gid; dir->mtime = (*i)->time; dir->xattr = (*i)->xattr; dir->dirs = NULL; while(bytes < size) { SQUASHFS_SWAP_DIR_HEADER(&dirh, directory_table + bytes); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position " "%d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { SQUASHFS_SWAP_DIR_ENTRY(dire, directory_table + bytes); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode " "%d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent)); if(new_dir == NULL) EXIT_UNSQUASH("squashfs_opendir: " "realloc failed!\n"); dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int read_uids_guids_4() { int res, i, indexes = SQUASHFS_ID_BLOCKS(sBlk.s.no_ids); long long id_index_table[indexes]; TRACE("read_uids_guids: no_ids %d\n", sBlk.s.no_ids); id_table = malloc(SQUASHFS_ID_BYTES(sBlk.s.no_ids)); if(id_table == NULL) { ERROR("read_uids_guids: failed to allocate id table\n"); return FALSE; } res = read_fs_bytes(fd, sBlk.s.id_table_start, SQUASHFS_ID_BLOCK_BYTES(sBlk.s.no_ids), id_index_table); if(res == FALSE) { ERROR("read_uids_guids: failed to read id index table\n"); return FALSE; } SQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes); for(i = 0; i < indexes; i++) { res = read_block(fd, id_index_table[i], NULL, ((char *) id_table) + i * SQUASHFS_METADATA_SIZE); if(res == FALSE) { ERROR("read_uids_guids: failed to read id table block" "\n"); return FALSE; } } SQUASHFS_INSWAP_INTS(id_table, sBlk.s.no_ids); return TRUE; } ================================================ FILE: src/others/squashfs-4.2-official/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.c */ #include "unsquashfs.h" #include "squashfs_swap.h" #include "squashfs_compat.h" #include "read_fs.h" #include "compressor.h" #include "xattr.h" #include <sys/sysinfo.h> #include <sys/types.h> struct cache *fragment_cache, *data_cache; struct queue *to_reader, *to_deflate, *to_writer, *from_writer; pthread_t *thread, *deflator_thread; pthread_mutex_t fragment_mutex; /* user options that control parallelisation */ int processors = -1; struct super_block sBlk; squashfs_operations s_ops; struct compressor *comp; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; unsigned int block_log; int lsonly = FALSE, info = FALSE, force = FALSE, short_ls = TRUE; int use_regex = FALSE; char **created_inode; int root_process; int columns; int rotate = 0; pthread_mutex_t screen_mutex; pthread_cond_t progress_wait; int progress = TRUE, progress_enabled = FALSE; unsigned int total_blocks = 0, total_files = 0, total_inodes = 0; unsigned int cur_blocks = 0; int inode_number = 1; int no_xattrs = XATTR_DEF; int lookup_type[] = { 0, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK, S_IFDIR, S_IFREG, S_IFLNK, S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK }; struct test table[] = { { S_IFMT, S_IFSOCK, 0, 's' }, { S_IFMT, S_IFLNK, 0, 'l' }, { S_IFMT, S_IFBLK, 0, 'b' }, { S_IFMT, S_IFDIR, 0, 'd' }, { S_IFMT, S_IFCHR, 0, 'c' }, { S_IFMT, S_IFIFO, 0, 'p' }, { S_IRUSR, S_IRUSR, 1, 'r' }, { S_IWUSR, S_IWUSR, 2, 'w' }, { S_IRGRP, S_IRGRP, 4, 'r' }, { S_IWGRP, S_IWGRP, 5, 'w' }, { S_IROTH, S_IROTH, 7, 'r' }, { S_IWOTH, S_IWOTH, 8, 'w' }, { S_IXUSR | S_ISUID, S_IXUSR | S_ISUID, 3, 's' }, { S_IXUSR | S_ISUID, S_ISUID, 3, 'S' }, { S_IXUSR | S_ISUID, S_IXUSR, 3, 'x' }, { S_IXGRP | S_ISGID, S_IXGRP | S_ISGID, 6, 's' }, { S_IXGRP | S_ISGID, S_ISGID, 6, 'S' }, { S_IXGRP | S_ISGID, S_IXGRP, 6, 'x' }, { S_IXOTH | S_ISVTX, S_IXOTH | S_ISVTX, 9, 't' }, { S_IXOTH | S_ISVTX, S_ISVTX, 9, 'T' }, { S_IXOTH | S_ISVTX, S_IXOTH, 9, 'x' }, { 0, 0, 0, 0} }; void progress_bar(long long current, long long max, int columns); void update_progress_bar(); void sigwinch_handler() { struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; } void sigalrm_handler() { rotate = (rotate + 1) % 4; } struct queue *queue_init(int size) { struct queue *queue = malloc(sizeof(struct queue)); if(queue == NULL) EXIT_UNSQUASH("Out of memory in queue_init\n"); queue->data = malloc(sizeof(void *) * (size + 1)); if(queue->data == NULL) EXIT_UNSQUASH("Out of memory in queue_init\n"); queue->size = size + 1; queue->readp = queue->writep = 0; pthread_mutex_init(&queue->mutex, NULL); pthread_cond_init(&queue->empty, NULL); pthread_cond_init(&queue->full, NULL); return queue; } void queue_put(struct queue *queue, void *data) { int nextp; pthread_mutex_lock(&queue->mutex); while((nextp = (queue->writep + 1) % queue->size) == queue->readp) pthread_cond_wait(&queue->full, &queue->mutex); queue->data[queue->writep] = data; queue->writep = nextp; pthread_cond_signal(&queue->empty); pthread_mutex_unlock(&queue->mutex); } void *queue_get(struct queue *queue) { void *data; pthread_mutex_lock(&queue->mutex); while(queue->readp == queue->writep) pthread_cond_wait(&queue->empty, &queue->mutex); data = queue->data[queue->readp]; queue->readp = (queue->readp + 1) % queue->size; pthread_cond_signal(&queue->full); pthread_mutex_unlock(&queue->mutex); return data; } /* Called with the cache mutex held */ void insert_hash_table(struct cache *cache, struct cache_entry *entry) { int hash = CALCULATE_HASH(entry->block); entry->hash_next = cache->hash_table[hash]; cache->hash_table[hash] = entry; entry->hash_prev = NULL; if(entry->hash_next) entry->hash_next->hash_prev = entry; } /* Called with the cache mutex held */ void remove_hash_table(struct cache *cache, struct cache_entry *entry) { if(entry->hash_prev) entry->hash_prev->hash_next = entry->hash_next; else cache->hash_table[CALCULATE_HASH(entry->block)] = entry->hash_next; if(entry->hash_next) entry->hash_next->hash_prev = entry->hash_prev; entry->hash_prev = entry->hash_next = NULL; } /* Called with the cache mutex held */ void insert_free_list(struct cache *cache, struct cache_entry *entry) { if(cache->free_list) { entry->free_next = cache->free_list; entry->free_prev = cache->free_list->free_prev; cache->free_list->free_prev->free_next = entry; cache->free_list->free_prev = entry; } else { cache->free_list = entry; entry->free_prev = entry->free_next = entry; } } /* Called with the cache mutex held */ void remove_free_list(struct cache *cache, struct cache_entry *entry) { if(entry->free_prev == NULL && entry->free_next == NULL) /* not in free list */ return; else if(entry->free_prev == entry && entry->free_next == entry) { /* only this entry in the free list */ cache->free_list = NULL; } else { /* more than one entry in the free list */ entry->free_next->free_prev = entry->free_prev; entry->free_prev->free_next = entry->free_next; if(cache->free_list == entry) cache->free_list = entry->free_next; } entry->free_prev = entry->free_next = NULL; } struct cache *cache_init(int buffer_size, int max_buffers) { struct cache *cache = malloc(sizeof(struct cache)); if(cache == NULL) EXIT_UNSQUASH("Out of memory in cache_init\n"); cache->max_buffers = max_buffers; cache->buffer_size = buffer_size; cache->count = 0; cache->free_list = NULL; memset(cache->hash_table, 0, sizeof(struct cache_entry *) * 65536); cache->wait_free = FALSE; cache->wait_pending = FALSE; pthread_mutex_init(&cache->mutex, NULL); pthread_cond_init(&cache->wait_for_free, NULL); pthread_cond_init(&cache->wait_for_pending, NULL); return cache; } struct cache_entry *cache_get(struct cache *cache, long long block, int size) { /* * Get a block out of the cache. If the block isn't in the cache * it is added and queued to the reader() and deflate() threads for * reading off disk and decompression. The cache grows until max_blocks * is reached, once this occurs existing discarded blocks on the free * list are reused */ int hash = CALCULATE_HASH(block); struct cache_entry *entry; pthread_mutex_lock(&cache->mutex); for(entry = cache->hash_table[hash]; entry; entry = entry->hash_next) if(entry->block == block) break; if(entry) { /* * found the block in the cache, increment used count and * if necessary remove from free list so it won't disappear */ entry->used ++; remove_free_list(cache, entry); pthread_mutex_unlock(&cache->mutex); } else { /* * not in the cache * * first try to allocate new block */ if(cache->count < cache->max_buffers) { entry = malloc(sizeof(struct cache_entry)); if(entry == NULL) EXIT_UNSQUASH("Out of memory in cache_get\n"); entry->data = malloc(cache->buffer_size); if(entry->data == NULL) EXIT_UNSQUASH("Out of memory in cache_get\n"); entry->cache = cache; entry->free_prev = entry->free_next = NULL; cache->count ++; } else { /* * try to get from free list */ while(cache->free_list == NULL) { cache->wait_free = TRUE; pthread_cond_wait(&cache->wait_for_free, &cache->mutex); } entry = cache->free_list; remove_free_list(cache, entry); remove_hash_table(cache, entry); } /* * initialise block and insert into the hash table */ entry->block = block; entry->size = size; entry->used = 1; entry->error = FALSE; entry->pending = TRUE; insert_hash_table(cache, entry); /* * queue to read thread to read and ultimately (via the * decompress threads) decompress the buffer */ pthread_mutex_unlock(&cache->mutex); queue_put(to_reader, entry); } return entry; } void cache_block_ready(struct cache_entry *entry, int error) { /* * mark cache entry as being complete, reading and (if necessary) * decompression has taken place, and the buffer is valid for use. * If an error occurs reading or decompressing, the buffer also * becomes ready but with an error... */ pthread_mutex_lock(&entry->cache->mutex); entry->pending = FALSE; entry->error = error; /* * if the wait_pending flag is set, one or more threads may be waiting * on this buffer */ if(entry->cache->wait_pending) { entry->cache->wait_pending = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_pending); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_wait(struct cache_entry *entry) { /* * wait for this cache entry to become ready, when reading and (if * necessary) decompression has taken place */ pthread_mutex_lock(&entry->cache->mutex); while(entry->pending) { entry->cache->wait_pending = TRUE; pthread_cond_wait(&entry->cache->wait_for_pending, &entry->cache->mutex); } pthread_mutex_unlock(&entry->cache->mutex); } void cache_block_put(struct cache_entry *entry) { /* * finished with this cache entry, once the usage count reaches zero it * can be reused and is put onto the free list. As it remains * accessible via the hash table it can be found getting a new lease of * life before it is reused. */ pthread_mutex_lock(&entry->cache->mutex); entry->used --; if(entry->used == 0) { insert_free_list(entry->cache, entry); /* * if the wait_free flag is set, one or more threads may be * waiting on this buffer */ if(entry->cache->wait_free) { entry->cache->wait_free = FALSE; pthread_cond_broadcast(&entry->cache->wait_for_free); } } pthread_mutex_unlock(&entry->cache->mutex); } char *modestr(char *str, int mode) { int i; strcpy(str, "----------"); for(i = 0; table[i].mask != 0; i++) { if((mode & table[i].mask) == table[i].value) str[table[i].position] = table[i].mode; } return str; } #define TOTALCHARS 25 int print_filename(char *pathname, struct inode *inode) { char str[11], dummy[100], dummy2[100], *userstr, *groupstr; int padchars; struct passwd *user; struct group *group; struct tm *t; if(short_ls) { printf("%s\n", pathname); return 1; } user = getpwuid(inode->uid); if(user == NULL) { sprintf(dummy, "%d", inode->uid); userstr = dummy; } else userstr = user->pw_name; group = getgrgid(inode->gid); if(group == NULL) { sprintf(dummy2, "%d", inode->gid); groupstr = dummy2; } else groupstr = group->gr_name; printf("%s %s/%s ", modestr(str, inode->mode), userstr, groupstr); switch(inode->mode & S_IFMT) { case S_IFREG: case S_IFDIR: case S_IFSOCK: case S_IFIFO: case S_IFLNK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr); printf("%*lld ", padchars > 0 ? padchars : 0, inode->data); break; case S_IFCHR: case S_IFBLK: padchars = TOTALCHARS - strlen(userstr) - strlen(groupstr) - 7; printf("%*s%3d,%3d ", padchars > 0 ? padchars : 0, " ", (int) inode->data >> 8, (int) inode->data & 0xff); break; } t = localtime(&inode->time); printf("%d-%02d-%02d %02d:%02d %s", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, pathname); if((inode->mode & S_IFMT) == S_IFLNK) printf(" -> %s", inode->symlink); printf("\n"); return 1; } void add_entry(struct hash_table_entry *hash_table[], long long start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; hash_table_entry = malloc(sizeof(struct hash_table_entry)); if(hash_table_entry == NULL) EXIT_UNSQUASH("Out of memory in add_entry\n"); hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; } int lookup_entry(struct hash_table_entry *hash_table[], long long start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_fs_bytes(int fd, long long byte, int bytes, void *buff) { off_t off = byte; int res, count; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\n", strerror(errno)); return FALSE; } for(count = 0; count < bytes; count += res) { res = read(fd, buff + count, bytes - count); if(res < 1) { if(res == 0) { ERROR("Read on filesystem failed because " "EOF\n"); return FALSE; } else if(errno != EINTR) { ERROR("Read on filesystem failed because %s\n", strerror(errno)); return FALSE; } else res = 0; } } return TRUE; } int read_block(int fd, long long start, long long *next, void *block) { unsigned short c_byte; int offset = 2; if(swap) { if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) goto failed; c_byte = (c_byte >> 8) | ((c_byte & 0xff) << 8); } else if(read_fs_bytes(fd, start, 2, &c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk.s.flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int error, res; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_fs_bytes(fd, start + offset, c_byte, buffer) == FALSE) goto failed; res = compressor_uncompress(comp, block, buffer, c_byte, SQUASHFS_METADATA_SIZE, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } if(next) *next = start + offset + c_byte; return res; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_fs_bytes(fd, start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: ERROR("read_block: failed to read block @0x%llx\n", start); return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int error, res; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_fs_bytes(fd, start, c_byte, data) == FALSE) goto failed; res = compressor_uncompress(comp, block, data, c_byte, block_size, &error); if(res == -1) { ERROR("%s uncompress failed with error code %d\n", comp->name, error); goto failed; } return res; } else { if(read_fs_bytes(fd, start, c_byte, block) == FALSE) goto failed; return c_byte; } failed: ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, c_byte); return FALSE; } void uncompress_inode_table(long long start, long long end) { int size = 0, bytes = 0, res; TRACE("uncompress_inode_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE) { inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE); if(inode_table == NULL) EXIT_UNSQUASH("Out of memory in " "uncompress_inode_table"); } TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); res = read_block(fd, start, &start, inode_table + bytes); if(res == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read " "block \n"); } bytes += res; } } int set_attributes(char *pathname, int mode, uid_t uid, gid_t guid, time_t time, unsigned int xattr, unsigned int set_mode) { struct utimbuf times = { time, time }; write_xattr(pathname, xattr); if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(root_process) { if(chown(pathname, uid, guid) == -1) { ERROR("set_attributes: failed to change uid and gids " "on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } else mode &= ~07000; if((set_mode || (mode & 07000)) && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } return TRUE; } int write_bytes(int fd, char *buff, int bytes) { int res, count; for(count = 0; count < bytes; count += res) { res = write(fd, buff + count, bytes - count); if(res == -1) { if(errno != EINTR) { ERROR("Write on output file failed because " "%s\n", strerror(errno)); return -1; } res = 0; } } return 0; } int lseek_broken = FALSE; char *zero_data = NULL; int write_block(int file_fd, char *buffer, int size, long long hole, int sparse) { off_t off = hole; if(hole) { if(sparse && lseek_broken == FALSE) { int error = lseek(file_fd, off, SEEK_CUR); if(error == -1) /* failed to seek beyond end of file */ lseek_broken = TRUE; } if((sparse == FALSE || lseek_broken) && zero_data == NULL) { if((zero_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("write_block: failed to alloc " "zero data block\n"); memset(zero_data, 0, block_size); } if(sparse == FALSE || lseek_broken) { int blocks = (hole + block_size -1) / block_size; int avail_bytes, i; for(i = 0; i < blocks; i++, hole -= avail_bytes) { avail_bytes = hole > block_size ? block_size : hole; if(write_bytes(file_fd, zero_data, avail_bytes) == -1) goto failure; } } } if(write_bytes(file_fd, buffer, size) == -1) goto failure; return TRUE; failure: return FALSE; } int write_file(struct inode *inode, char *pathname) { unsigned int file_fd, i; unsigned int *block_list; int file_end = inode->data / block_size; long long start = inode->start; struct squashfs_file *file; TRACE("write_file: regular file, blocks %d\n", inode->blocks); file_fd = open(pathname, O_CREAT | O_WRONLY | (force ? O_TRUNC : 0), (mode_t) inode->mode & 0777); if(file_fd == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); return FALSE; } block_list = malloc(inode->blocks * sizeof(unsigned int)); if(block_list == NULL) EXIT_UNSQUASH("write_file: unable to malloc block list\n"); s_ops.read_block_list(block_list, inode->block_ptr, inode->blocks); file = malloc(sizeof(struct squashfs_file)); if(file == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); /* * the writer thread is queued a squashfs_file structure describing the * file. If the file has one or more blocks or a fragments they are * queued separately (references to blocks in the cache). */ file->fd = file_fd; file->file_size = inode->data; file->mode = inode->mode; file->gid = inode->gid; file->uid = inode->uid; file->time = inode->time; file->pathname = strdup(pathname); file->blocks = inode->blocks + (inode->frag_bytes > 0); file->sparse = inode->sparse; file->xattr = inode->xattr; queue_put(to_writer, file); for(i = 0; i < inode->blocks; i++) { int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); block->offset = 0; block->size = i == file_end ? inode->data & (block_size - 1) : block_size; if(block_list[i] == 0) /* sparse file */ block->buffer = NULL; else { block->buffer = cache_get(data_cache, start, block_list[i]); start += c_byte; } queue_put(to_writer, block); } if(inode->frag_bytes) { int size; long long start; struct file_entry *block = malloc(sizeof(struct file_entry)); if(block == NULL) EXIT_UNSQUASH("write_file: unable to malloc file\n"); s_ops.read_fragment(inode->fragment, &start, &size); block->buffer = cache_get(fragment_cache, start, size); block->offset = inode->offset; block->size = inode->frag_bytes; queue_put(to_writer, block); } free(block_list); return TRUE; } int create_inode(char *pathname, struct inode *i) { TRACE("create_inode: pathname %s\n", pathname); if(created_inode[i->inode_number - 1]) { TRACE("create_inode: hard link\n"); if(force) unlink(pathname); if(link(created_inode[i->inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, " "because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(i->type) { case SQUASHFS_FILE_TYPE: case SQUASHFS_LREG_TYPE: TRACE("create_inode: regular file, file_size %lld, " "blocks %d\n", i->data, i->blocks); if(write_file(i, pathname)) file_count ++; break; case SQUASHFS_SYMLINK_TYPE: case SQUASHFS_LSYMLINK_TYPE: TRACE("create_inode: symlink, symlink_size %lld\n", i->data); if(force) unlink(pathname); if(symlink(i->symlink, pathname) == -1) { ERROR("create_inode: failed to create symlink " "%s, because %s\n", pathname, strerror(errno)); break; } write_xattr(pathname, i->xattr); if(root_process) { if(lchown(pathname, i->uid, i->gid) == -1) ERROR("create_inode: failed to change " "uid and gids on %s, because " "%s\n", pathname, strerror(errno)); } sym_count ++; break; case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: case SQUASHFS_LBLKDEV_TYPE: case SQUASHFS_LCHRDEV_TYPE: { int chrdev = i->type == SQUASHFS_CHRDEV_TYPE; TRACE("create_inode: dev, rdev 0x%llx\n", i->data); if(root_process) { if(force) unlink(pathname); if(mknod(pathname, chrdev ? S_IFCHR : S_IFBLK, makedev((i->data >> 8) & 0xff, i->data & 0xff)) == -1) { ERROR("create_inode: failed to create " "%s device %s, because %s\n", chrdev ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s " "device %s, because you're not " "superuser!\n", chrdev ? "character" : "block", pathname); break; } case SQUASHFS_FIFO_TYPE: case SQUASHFS_LFIFO_TYPE: TRACE("create_inode: fifo\n"); if(force) unlink(pathname); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, " "because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, i->mode, i->uid, i->gid, i->time, i->xattr, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: case SQUASHFS_LSOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", i->type); return FALSE; } created_inode[i->inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end) { int bytes = 0, size = 0, res; TRACE("uncompress_directory_table: start %lld, end %lld\n", start, end); while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE) { directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE); if(directory_table == NULL) EXIT_UNSQUASH("Out of memory in " "uncompress_directory_table\n"); } TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); res = read_block(fd, start, &start, directory_table + bytes); if(res == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to " "read block\n"); bytes += res; } } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } char *get_component(char *target, char *targname) { while(*target == '/') target ++; while(*target != '/' && *target!= '\0') *targname ++ = *target ++; *targname = '\0'; return target; } void free_path(struct pathname *paths) { int i; for(i = 0; i < paths->names; i++) { if(paths->name[i].paths) free_path(paths->name[i].paths); free(paths->name[i].name); if(paths->name[i].preg) { regfree(paths->name[i].preg); free(paths->name[i].preg); } } free(paths); } struct pathname *add_path(struct pathname *paths, char *target, char *alltarget) { char targname[1024]; int i, error; TRACE("add_path: adding \"%s\" extract file\n", target); target = get_component(target, targname); if(paths == NULL) { paths = malloc(sizeof(struct pathname)); if(paths == NULL) EXIT_UNSQUASH("failed to allocate paths\n"); paths->names = 0; paths->name = NULL; } for(i = 0; i < paths->names; i++) if(strcmp(paths->name[i].name, targname) == 0) break; if(i == paths->names) { /* * allocate new name entry */ paths->names ++; paths->name = realloc(paths->name, (i + 1) * sizeof(struct path_entry)); if(paths->name == NULL) EXIT_UNSQUASH("Out of memory in add_path\n"); paths->name[i].name = strdup(targname); paths->name[i].paths = NULL; if(use_regex) { paths->name[i].preg = malloc(sizeof(regex_t)); if(paths->name[i].preg == NULL) EXIT_UNSQUASH("Out of memory in add_path\n"); error = regcomp(paths->name[i].preg, targname, REG_EXTENDED|REG_NOSUB); if(error) { char str[1024]; regerror(error, paths->name[i].preg, str, 1024); EXIT_UNSQUASH("invalid regex %s in export %s, " "because %s\n", targname, alltarget, str); } } else paths->name[i].preg = NULL; if(target[0] == '\0') /* * at leaf pathname component */ paths->name[i].paths = NULL; else /* * recurse adding child components */ paths->name[i].paths = add_path(NULL, target, alltarget); } else { /* * existing matching entry */ if(paths->name[i].paths == NULL) { /* * No sub-directory which means this is the leaf * component of a pre-existing extract which subsumes * the extract currently being added, in which case stop * adding components */ } else if(target[0] == '\0') { /* * at leaf pathname component and child components exist * from more specific extracts, delete as they're * subsumed by this extract */ free_path(paths->name[i].paths); paths->name[i].paths = NULL; } else /* * recurse adding child components */ add_path(paths->name[i].paths, target, alltarget); } return paths; } struct pathnames *init_subdir() { struct pathnames *new = malloc(sizeof(struct pathnames)); if(new == NULL) EXIT_UNSQUASH("Out of memory in init_subdir\n"); new->count = 0; return new; } struct pathnames *add_subdir(struct pathnames *paths, struct pathname *path) { if(paths->count % PATHS_ALLOC_SIZE == 0) { paths = realloc(paths, sizeof(struct pathnames *) + (paths->count + PATHS_ALLOC_SIZE) * sizeof(struct pathname *)); if(paths == NULL) EXIT_UNSQUASH("Out of memory in add_subdir\n"); } paths->path[paths->count++] = path; return paths; } void free_subdir(struct pathnames *paths) { free(paths); } int matches(struct pathnames *paths, char *name, struct pathnames **new) { int i, n; if(paths == NULL) { *new = NULL; return TRUE; } *new = init_subdir(); for(n = 0; n < paths->count; n++) { struct pathname *path = paths->path[n]; for(i = 0; i < path->names; i++) { int match = use_regex ? regexec(path->name[i].preg, name, (size_t) 0, NULL, 0) == 0 : fnmatch(path->name[i].name, name, FNM_PATHNAME|FNM_PERIOD|FNM_EXTMATCH) == 0; if(match && path->name[i].paths == NULL) /* * match on a leaf component, any subdirectories * will implicitly match, therefore return an * empty new search set */ goto empty_set; if(match) /* * match on a non-leaf component, add any * subdirectories to the new set of * subdirectories to scan for this name */ *new = add_subdir(*new, path->name[i].paths); } } if((*new)->count == 0) { /* * no matching names found, delete empty search set, and return * FALSE */ free_subdir(*new); *new = NULL; return FALSE; } /* * one or more matches with sub-directories found (no leaf matches), * return new search set and return TRUE */ return TRUE; empty_set: /* * found matching leaf exclude, return empty search set and return TRUE */ free_subdir(*new); *new = NULL; return TRUE; } void pre_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { struct inode *i; TRACE("pre_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) pre_scan(parent_name, start_block, offset, new); else if(new == NULL) { if(type == SQUASHFS_FILE_TYPE || type == SQUASHFS_LREG_TYPE) { i = s_ops.read_inode(start_block, offset); if(created_inode[i->inode_number - 1] == NULL) { created_inode[i->inode_number - 1] = (char *) i; total_blocks += (i->data + (block_size - 1)) >> block_log; } total_files ++; } total_inodes ++; } free_subdir(new); } squashfs_closedir(dir); } void dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, struct pathnames *paths) { unsigned int type; char *name, pathname[1024]; struct pathnames *new; struct inode *i; struct dir *dir = s_ops.squashfs_opendir(start_block, offset, &i); if(lsonly || info) print_filename(parent_name, i); if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && (!force || errno != EEXIST)) { ERROR("dir_scan: failed to make directory %s, because %s\n", parent_name, strerror(errno)); squashfs_closedir(dir); return; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); if(!matches(paths, name, &new)) continue; strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, new); else if(new == NULL) { i = s_ops.read_inode(start_block, offset); if(lsonly || info) print_filename(pathname, i); if(!lsonly) { create_inode(pathname, i); update_progress_bar(); } if(i->type == SQUASHFS_SYMLINK_TYPE || i->type == SQUASHFS_LSYMLINK_TYPE) free(i->symlink); } free_subdir(new); } if(!lsonly) set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, dir->xattr, force); squashfs_closedir(dir); dir_count ++; } void squashfs_stat(char *source) { time_t mkfs_time = (time_t) sBlk.s.mkfs_time; char *mkfs_str = ctime(&mkfs_time); #if __BYTE_ORDER == __BIG_ENDIAN printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s.s_major == 4 ? "" : swap ? "little endian " : "big endian ", sBlk.s.s_major, sBlk.s.s_minor, source); #else printf("Found a valid %sSQUASHFS %d:%d superblock on %s.\n", sBlk.s.s_major == 4 ? "" : swap ? "big endian " : "little endian ", sBlk.s.s_major, sBlk.s.s_minor, source); #endif printf("Creation or last append time %s", mkfs_str ? mkfs_str : "failed to get time\n"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk.s.bytes_used / 1024.0, sBlk.s.bytes_used / (1024.0 * 1024.0)); if(sBlk.s.s_major == 4) printf("Compression %s\n", comp->name); printf("Block size %d\n", sBlk.s.block_size); printf("Filesystem is %sexportable via NFS\n", SQUASHFS_EXPORTABLE(sBlk.s.flags) ? "" : "not "); printf("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk.s.flags) ? "un" : ""); printf("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk.s.flags) ? "un" : ""); if(sBlk.s.s_major > 1) { if(SQUASHFS_NO_FRAGMENTS(sBlk.s.flags)) printf("Fragments are not stored\n"); else { printf("Fragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.s.flags) ? "un" : ""); printf("Always_use_fragments option is %sspecified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk.s.flags) ? "" : "not "); } } if(sBlk.s.s_major == 4) { if(SQUASHFS_NO_XATTRS(sBlk.s.flags)) printf("Xattrs are not stored\n"); else printf("Xattrs are %scompressed\n", SQUASHFS_UNCOMPRESSED_XATTRS(sBlk.s.flags) ? "un" : ""); } if(sBlk.s.s_major < 4) printf("Check data is %spresent in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk.s.flags) ? "" : "not "); if(sBlk.s.s_major > 1) printf("Duplicates are %sremoved\n", SQUASHFS_DUPLICATES(sBlk.s.flags) ? "" : "not "); else printf("Duplicates are removed\n"); if(sBlk.s.s_major > 1) printf("Number of fragments %d\n", sBlk.s.fragments); printf("Number of inodes %d\n", sBlk.s.inodes); if(sBlk.s.s_major == 4) printf("Number of ids %d\n", sBlk.s.no_ids); else { printf("Number of uids %d\n", sBlk.no_uids); printf("Number of gids %d\n", sBlk.no_guids); } TRACE("sBlk.s.inode_table_start 0x%llx\n", sBlk.s.inode_table_start); TRACE("sBlk.s.directory_table_start 0x%llx\n", sBlk.s.directory_table_start); if(sBlk.s.s_major == 4) { TRACE("sBlk.s.id_table_start 0x%llx\n", sBlk.s.id_table_start); TRACE("sBlk.s.xattr_id_table_start 0x%llx\n", sBlk.s.xattr_id_table_start); } else { TRACE("sBlk.uid_start 0x%llx\n", sBlk.uid_start); TRACE("sBlk.guid_start 0x%llx\n", sBlk.guid_start); } if(sBlk.s.s_major > 1) TRACE("sBlk.s.fragment_table_start 0x%llx\n\n", sBlk.s.fragment_table_start); } int read_super(char *source) { squashfs_super_block_3 sBlk_3; struct squashfs_super_block sBlk_4; /* * Try to read a Squashfs 4 superblock */ read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block), &sBlk_4); swap = sBlk_4.s_magic != SQUASHFS_MAGIC; SQUASHFS_INSWAP_SUPER_BLOCK(&sBlk_4); if(sBlk_4.s_magic == SQUASHFS_MAGIC && sBlk_4.s_major == 4 && sBlk_4.s_minor == 0) { s_ops.squashfs_opendir = squashfs_opendir_4; s_ops.read_fragment = read_fragment_4; s_ops.read_fragment_table = read_fragment_table_4; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_4; s_ops.read_uids_guids = read_uids_guids_4; memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); /* * Check the compression type */ comp = lookup_compressor_id(sBlk.s.compression); return TRUE; } /* * Not a Squashfs 4 superblock, try to read a squashfs 3 superblock * (compatible with 1 and 2 filesystems) */ read_fs_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block_3), &sBlk_3); /* * Check it is a SQUASHFS superblock */ swap = 0; if(sBlk_3.s_magic != SQUASHFS_MAGIC) { if(sBlk_3.s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block_3 sblk; ERROR("Reading a different endian SQUASHFS filesystem " "on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK_3(&sblk, &sBlk_3); memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } sBlk.s.s_magic = sBlk_3.s_magic; sBlk.s.inodes = sBlk_3.inodes; sBlk.s.mkfs_time = sBlk_3.mkfs_time; sBlk.s.block_size = sBlk_3.block_size; sBlk.s.fragments = sBlk_3.fragments; sBlk.s.block_log = sBlk_3.block_log; sBlk.s.flags = sBlk_3.flags; sBlk.s.s_major = sBlk_3.s_major; sBlk.s.s_minor = sBlk_3.s_minor; sBlk.s.root_inode = sBlk_3.root_inode; sBlk.s.bytes_used = sBlk_3.bytes_used; sBlk.s.inode_table_start = sBlk_3.inode_table_start; sBlk.s.directory_table_start = sBlk_3.directory_table_start; sBlk.s.fragment_table_start = sBlk_3.fragment_table_start; sBlk.s.lookup_table_start = sBlk_3.lookup_table_start; sBlk.no_uids = sBlk_3.no_uids; sBlk.no_guids = sBlk_3.no_guids; sBlk.uid_start = sBlk_3.uid_start; sBlk.guid_start = sBlk_3.guid_start; sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; /* Check the MAJOR & MINOR versions */ if(sBlk.s.s_major == 1 || sBlk.s.s_major == 2) { sBlk.s.bytes_used = sBlk_3.bytes_used_2; sBlk.uid_start = sBlk_3.uid_start_2; sBlk.guid_start = sBlk_3.guid_start_2; sBlk.s.inode_table_start = sBlk_3.inode_table_start_2; sBlk.s.directory_table_start = sBlk_3.directory_table_start_2; if(sBlk.s.s_major == 1) { sBlk.s.block_size = sBlk_3.block_size_1; sBlk.s.fragment_table_start = sBlk.uid_start; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment_table = read_fragment_table_1; s_ops.read_block_list = read_block_list_1; s_ops.read_inode = read_inode_1; s_ops.read_uids_guids = read_uids_guids_1; } else { sBlk.s.fragment_table_start = sBlk_3.fragment_table_start_2; s_ops.squashfs_opendir = squashfs_opendir_1; s_ops.read_fragment = read_fragment_2; s_ops.read_fragment_table = read_fragment_table_2; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_2; s_ops.read_uids_guids = read_uids_guids_1; } } else if(sBlk.s.s_major == 3) { s_ops.squashfs_opendir = squashfs_opendir_3; s_ops.read_fragment = read_fragment_3; s_ops.read_fragment_table = read_fragment_table_3; s_ops.read_block_list = read_block_list_2; s_ops.read_inode = read_inode_3; s_ops.read_uids_guids = read_uids_guids_1; } else { ERROR("Filesystem on %s is (%d:%d), ", source, sBlk.s.s_major, sBlk.s.s_minor); ERROR("which is a later filesystem version than I support!\n"); goto failed_mount; } /* * 1.x, 2.x and 3.x filesystems use gzip compression. */ comp = lookup_compressor("gzip"); return TRUE; failed_mount: return FALSE; } struct pathname *process_extract_files(struct pathname *path, char *filename) { FILE *fd; char name[16384]; fd = fopen(filename, "r"); if(fd == NULL) EXIT_UNSQUASH("Could not open %s, because %s\n", filename, strerror(errno)); while(fscanf(fd, "%16384[^\n]\n", name) != EOF) path = add_path(path, name, name); fclose(fd); return path; } /* * reader thread. This thread processes read requests queued by the * cache_get() routine. */ void *reader(void *arg) { while(1) { struct cache_entry *entry = queue_get(to_reader); int res = read_fs_bytes(fd, entry->block, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), entry->data); if(res && SQUASHFS_COMPRESSED_BLOCK(entry->size)) /* * queue successfully read block to the deflate * thread(s) for further processing */ queue_put(to_deflate, entry); else /* * block has either been successfully read and is * uncompressed, or an error has occurred, clear pending * flag, set error appropriately, and wake up any * threads waiting on this buffer */ cache_block_ready(entry, !res); } } /* * writer thread. This processes file write requests queued by the * write_file() routine. */ void *writer(void *arg) { int i; while(1) { struct squashfs_file *file = queue_get(to_writer); int file_fd; long long hole = 0; int failed = FALSE; int error; if(file == NULL) { queue_put(from_writer, NULL); continue; } TRACE("writer: regular file, blocks %d\n", file->blocks); file_fd = file->fd; for(i = 0; i < file->blocks; i++, cur_blocks ++) { struct file_entry *block = queue_get(to_writer); if(block->buffer == 0) { /* sparse file */ hole += block->size; free(block); continue; } cache_block_wait(block->buffer); if(block->buffer->error) failed = TRUE; if(failed) continue; error = write_block(file_fd, block->buffer->data + block->offset, block->size, hole, file->sparse); if(error == FALSE) { ERROR("writer: failed to write data block %d\n", i); failed = TRUE; } hole = 0; cache_block_put(block->buffer); free(block); } if(hole && failed == FALSE) { /* * corner case for hole extending to end of file */ if(file->sparse == FALSE || lseek(file_fd, hole, SEEK_CUR) == -1) { /* * for files which we don't want to write * sparsely, or for broken lseeks which cannot * seek beyond end of file, write_block will do * the right thing */ hole --; if(write_block(file_fd, "\0", 1, hole, file->sparse) == FALSE) { ERROR("writer: failed to write sparse " "data block\n"); failed = TRUE; } } else if(ftruncate(file_fd, file->file_size) == -1) { ERROR("writer: failed to write sparse data " "block\n"); failed = TRUE; } } close(file_fd); if(failed == FALSE) set_attributes(file->pathname, file->mode, file->uid, file->gid, file->time, file->xattr, force); else { ERROR("Failed to write %s, skipping\n", file->pathname); unlink(file->pathname); } free(file->pathname); free(file); } } /* * decompress thread. This decompresses buffers queued by the read thread */ void *deflator(void *arg) { char tmp[block_size]; while(1) { struct cache_entry *entry = queue_get(to_deflate); int error, res; res = compressor_uncompress(comp, tmp, entry->data, SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, &error); if(res == -1) ERROR("%s uncompress failed with error code %d\n", comp->name, error); else memcpy(entry->data, tmp, res); /* * block has been either successfully decompressed, or an error * occurred, clear pending flag, set error appropriately and * wake up any threads waiting on this block */ cache_block_ready(entry, res == -1); } } void *progress_thread(void *arg) { struct timeval timeval; struct timespec timespec; struct itimerval itimerval; struct winsize winsize; if(ioctl(1, TIOCGWINSZ, &winsize) == -1) { if(isatty(STDOUT_FILENO)) ERROR("TIOCGWINSZ ioctl failed, defaulting to 80 " "columns\n"); columns = 80; } else columns = winsize.ws_col; signal(SIGWINCH, sigwinch_handler); signal(SIGALRM, sigalrm_handler); itimerval.it_value.tv_sec = 0; itimerval.it_value.tv_usec = 250000; itimerval.it_interval.tv_sec = 0; itimerval.it_interval.tv_usec = 250000; setitimer(ITIMER_REAL, &itimerval, NULL); pthread_cond_init(&progress_wait, NULL); pthread_mutex_lock(&screen_mutex); while(1) { gettimeofday(&timeval, NULL); timespec.tv_sec = timeval.tv_sec; if(timeval.tv_usec + 250000 > 999999) timespec.tv_sec++; timespec.tv_nsec = ((timeval.tv_usec + 250000) % 1000000) * 1000; pthread_cond_timedwait(&progress_wait, &screen_mutex, ×pec); if(progress_enabled) progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } } void initialise_threads(int fragment_buffer_size, int data_buffer_size) { int i; sigset_t sigmask, old_mask; int all_buffers_size = fragment_buffer_size + data_buffer_size; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGQUIT); if(sigprocmask(SIG_BLOCK, &sigmask, &old_mask) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); if(processors == -1) { #ifndef linux int mib[2]; size_t len = sizeof(processors); mib[0] = CTL_HW; #ifdef HW_AVAILCPU mib[1] = HW_AVAILCPU; #else mib[1] = HW_NCPU; #endif if(sysctl(mib, 2, &processors, &len, NULL, 0) == -1) { ERROR("Failed to get number of available processors. " "Defaulting to 1\n"); processors = 1; } #else processors = sysconf(_SC_NPROCESSORS_ONLN); #endif } thread = malloc((3 + processors) * sizeof(pthread_t)); if(thread == NULL) EXIT_UNSQUASH("Out of memory allocating thread descriptors\n"); deflator_thread = &thread[3]; to_reader = queue_init(all_buffers_size); to_deflate = queue_init(all_buffers_size); to_writer = queue_init(1000); from_writer = queue_init(1); fragment_cache = cache_init(block_size, fragment_buffer_size); data_cache = cache_init(block_size, data_buffer_size); pthread_create(&thread[0], NULL, reader, NULL); pthread_create(&thread[1], NULL, writer, NULL); pthread_create(&thread[2], NULL, progress_thread, NULL); pthread_mutex_init(&fragment_mutex, NULL); for(i = 0; i < processors; i++) { if(pthread_create(&deflator_thread[i], NULL, deflator, NULL) != 0) EXIT_UNSQUASH("Failed to create thread\n"); } printf("Parallel unsquashfs: Using %d processor%s\n", processors, processors == 1 ? "" : "s"); if(sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) EXIT_UNSQUASH("Failed to set signal mask in intialise_threads" "\n"); } void enable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = TRUE; pthread_mutex_unlock(&screen_mutex); } void disable_progress_bar() { pthread_mutex_lock(&screen_mutex); progress_enabled = FALSE; pthread_mutex_unlock(&screen_mutex); } void update_progress_bar() { pthread_mutex_lock(&screen_mutex); pthread_cond_signal(&progress_wait); pthread_mutex_unlock(&screen_mutex); } void progress_bar(long long current, long long max, int columns) { char rotate_list[] = { '|', '/', '-', '\\' }; int max_digits, used, hashes, spaces; static int tty = -1; if(max == 0) return; max_digits = floor(log10(max)) + 1; used = max_digits * 2 + 11; hashes = (current * (columns - used)) / max; spaces = columns - used - hashes; if((current > max) || (columns - used < 0)) return; if(tty == -1) tty = isatty(STDOUT_FILENO); if(!tty) { static long long previous = -1; /* * Updating much more frequently than this results in huge * log files. */ if((current % 100) != 0 && current != max) return; /* Don't update just to rotate the spinner. */ if(current == previous) return; previous = current; } printf("\r["); while (hashes --) putchar('='); putchar(rotate_list[rotate]); while(spaces --) putchar(' '); printf("] %*lld/%*lld", max_digits, current, max_digits, max); printf(" %3lld%%", current * 100 / max); fflush(stdout); } #define VERSION() \ printf("unsquashfs version 4.2 (2011/02/28)\n");\ printf("copyright (C) 2011 Phillip Lougher "\ "<phillip@lougher.demon.co.uk>\n\n");\ printf("This program is free software; you can redistribute it and/or"\ "\n");\ printf("modify it under the terms of the GNU General Public License"\ "\n");\ printf("as published by the Free Software Foundation; either version "\ "2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be "\ "useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of"\ "\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"\ "\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { char *dest = "squashfs-root"; int i, stat_sys = FALSE, version = FALSE; int n; struct pathnames *paths = NULL; struct pathname *path = NULL; int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; int data_buffer_size = DATA_BUFFER_DEFAULT; char *b; pthread_mutex_init(&screen_mutex, NULL); root_process = geteuid() == 0; if(root_process) umask(0); for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0 || strcmp(argv[i], "-i") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0 || strcmp(argv[i], "-l") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-no-progress") == 0 || strcmp(argv[i], "-n") == 0) progress = FALSE; else if(strcmp(argv[i], "-no-xattrs") == 0 || strcmp(argv[i], "-no") == 0) no_xattrs = TRUE; else if(strcmp(argv[i], "-xattrs") == 0 || strcmp(argv[i], "-x") == 0) no_xattrs = FALSE; else if(strcmp(argv[i], "-dest") == 0 || strcmp(argv[i], "-d") == 0) { if(++i == argc) { fprintf(stderr, "%s: -dest missing filename\n", argv[0]); exit(1); } dest = argv[i]; } else if(strcmp(argv[i], "-processors") == 0 || strcmp(argv[i], "-p") == 0) { if((++i == argc) || (processors = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -processors missing or invalid " "processor number\n", argv[0]); exit(1); } if(processors < 1) { ERROR("%s: -processors should be 1 or larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-data-queue") == 0 || strcmp(argv[i], "-da") == 0) { if((++i == argc) || (data_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -data-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(data_buffer_size < 1) { ERROR("%s: -data-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-frag-queue") == 0 || strcmp(argv[i], "-fr") == 0) { if((++i == argc) || (fragment_buffer_size = strtol(argv[i], &b, 10), *b != '\0')) { ERROR("%s: -frag-queue missing or invalid " "queue size\n", argv[0]); exit(1); } if(fragment_buffer_size < 1) { ERROR("%s: -frag-queue should be 1 Mbyte or " "larger\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-force") == 0 || strcmp(argv[i], "-f") == 0) force = TRUE; else if(strcmp(argv[i], "-stat") == 0 || strcmp(argv[i], "-s") == 0) stat_sys = TRUE; else if(strcmp(argv[i], "-lls") == 0 || strcmp(argv[i], "-ll") == 0) { lsonly = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-linfo") == 0 || strcmp(argv[i], "-li") == 0) { info = TRUE; short_ls = FALSE; } else if(strcmp(argv[i], "-ef") == 0 || strcmp(argv[i], "-e") == 0) { if(++i == argc) { fprintf(stderr, "%s: -ef missing filename\n", argv[0]); exit(1); } path = process_extract_files(path, argv[i]); } else if(strcmp(argv[i], "-regex") == 0 || strcmp(argv[i], "-r") == 0) use_regex = TRUE; else goto options; } if(lsonly || info) progress = FALSE; #ifdef SQUASHFS_TRACE progress = FALSE; #endif if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [options] filesystem [directories or " "files to extract]\n", argv[0]); ERROR("\t-v[ersion]\t\tprint version, licence and " "copyright information\n"); ERROR("\t-d[est] <pathname>\tunsquash to <pathname>, " "default \"squashfs-root\"\n"); ERROR("\t-n[o-progress]\t\tdon't display the progress " "bar\n"); ERROR("\t-no[-xattrs]\t\tdon't extract xattrs in file system" NOXOPT_STR"\n"); ERROR("\t-x[attrs]\t\textract xattrs in file system" XOPT_STR "\n"); ERROR("\t-p[rocessors] <number>\tuse <number> " "processors. By default will use\n"); ERROR("\t\t\t\tnumber of processors available\n"); ERROR("\t-i[nfo]\t\t\tprint files as they are " "unsquashed\n"); ERROR("\t-li[nfo]\t\tprint files as they are " "unsquashed with file\n"); ERROR("\t\t\t\tattributes (like ls -l output)\n"); ERROR("\t-l[s]\t\t\tlist filesystem, but don't unsquash" "\n"); ERROR("\t-ll[s]\t\t\tlist filesystem with file " "attributes (like\n"); ERROR("\t\t\t\tls -l output), but don't unsquash\n"); ERROR("\t-f[orce]\t\tif file already exists then " "overwrite\n"); ERROR("\t-s[tat]\t\t\tdisplay filesystem superblock " "information\n"); ERROR("\t-e[f] <extract file>\tlist of directories or " "files to extract.\n\t\t\t\tOne per line\n"); ERROR("\t-da[ta-queue] <size>\tSet data queue to " "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n", DATA_BUFFER_DEFAULT); ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to " "<size> Mbytes. Default\n\t\t\t\t%d Mbytes\n", FRAGMENT_BUFFER_DEFAULT); ERROR("\t-r[egex]\t\ttreat extract names as POSIX " "regular expressions\n"); ERROR("\t\t\t\trather than use the default shell " "wildcard\n\t\t\t\texpansion (globbing)\n"); ERROR("\nDecompressors available:\n"); display_compressors("", ""); } exit(1); } for(n = i + 1; n < argc; n++) path = add_path(path, argv[n], argv[n]); if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(argv[i]) == FALSE) exit(1); if(stat_sys) { squashfs_stat(argv[i]); exit(0); } if(!comp->supported) { ERROR("Filesystem uses %s compression, this is " "unsupported by this version\n", comp->name); ERROR("Decompressors available:\n"); display_compressors("", ""); exit(1); } block_size = sBlk.s.block_size; block_log = sBlk.s.block_log; fragment_buffer_size <<= 20 - block_log; data_buffer_size <<= 20 - block_log; initialise_threads(fragment_buffer_size, data_buffer_size); fragment_data = malloc(block_size); if(fragment_data == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); file_data = malloc(block_size); if(file_data == NULL) EXIT_UNSQUASH("failed to allocate file_data"); data = malloc(block_size); if(data == NULL) EXIT_UNSQUASH("failed to allocate data\n"); created_inode = malloc(sBlk.s.inodes * sizeof(char *)); if(created_inode == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); if(s_ops.read_uids_guids() == FALSE) EXIT_UNSQUASH("failed to uid/gid table\n"); if(s_ops.read_fragment_table() == FALSE) EXIT_UNSQUASH("failed to read fragment table\n"); uncompress_inode_table(sBlk.s.inode_table_start, sBlk.s.directory_table_start); uncompress_directory_table(sBlk.s.directory_table_start, sBlk.s.fragment_table_start); if(no_xattrs) sBlk.s.xattr_id_table_start = SQUASHFS_INVALID_BLK; if(read_xattrs_from_disk(fd, &sBlk.s) == 0) EXIT_UNSQUASH("failed to read the xattr table\n"); if(path) { paths = init_subdir(); paths = add_subdir(paths, path); } pre_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); memset(created_inode, 0, sBlk.s.inodes * sizeof(char *)); inode_number = 1; printf("%d inodes (%d blocks) to write\n\n", total_inodes, total_inodes - total_files + total_blocks); if(progress) enable_progress_bar(); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.s.root_inode), SQUASHFS_INODE_OFFSET(sBlk.s.root_inode), paths); queue_put(to_writer, NULL); queue_get(from_writer); if(progress) { disable_progress_bar(); progress_bar(sym_count + dev_count + fifo_count + cur_blocks, total_inodes - total_files + total_blocks, columns); } if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } return 0; } ================================================ FILE: src/others/squashfs-4.2-official/unsquashfs.h ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs.h */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #include <utime.h> #include <pwd.h> #include <grp.h> #include <time.h> #include <regex.h> #include <fnmatch.h> #include <signal.h> #include <pthread.h> #include <math.h> #include <sys/ioctl.h> #include <sys/time.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include "squashfs_fs.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ printf("\n"); \ printf("unsquashfs: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ if(progress_enabled) \ fprintf(stderr, "\n"); \ fprintf(stderr, s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ } while(0) #define EXIT_UNSQUASH(s, args...) \ do { \ pthread_mutex_lock(&screen_mutex); \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ pthread_mutex_unlock(&screen_mutex);\ exit(1); \ } while(0) #define CALCULATE_HASH(start) (start & 0xffff) /* * Unified superblock containing fields for all superblocks */ struct super_block { struct squashfs_super_block s; /* fields only used by squashfs 3 and earlier layouts */ unsigned int no_uids; unsigned int no_guids; long long uid_start; long long guid_start; }; struct hash_table_entry { long long start; int bytes; struct hash_table_entry *next; }; struct inode { int blocks; char *block_ptr; long long data; int fragment; int frag_bytes; gid_t gid; int inode_number; int mode; int offset; long long start; char *symlink; time_t time; int type; uid_t uid; char sparse; unsigned int xattr; }; typedef struct squashfs_operations { struct dir *(*squashfs_opendir)(unsigned int block_start, unsigned int offset, struct inode **i); void (*read_fragment)(unsigned int fragment, long long *start_block, int *size); int (*read_fragment_table)(); void (*read_block_list)(unsigned int *block_list, char *block_ptr, int blocks); struct inode *(*read_inode)(unsigned int start_block, unsigned int offset); int (*read_uids_guids)(); } squashfs_operations; struct test { int mask; int value; int position; char mode; }; /* Cache status struct. Caches are used to keep track of memory buffers passed between different threads */ struct cache { int max_buffers; int count; int buffer_size; int wait_free; int wait_pending; pthread_mutex_t mutex; pthread_cond_t wait_for_free; pthread_cond_t wait_for_pending; struct cache_entry *free_list; struct cache_entry *hash_table[65536]; }; /* struct describing a cache entry passed between threads */ struct cache_entry { struct cache *cache; long long block; int size; int used; int error; int pending; struct cache_entry *hash_next; struct cache_entry *hash_prev; struct cache_entry *free_next; struct cache_entry *free_prev; char *data; }; /* struct describing queues used to pass data between threads */ struct queue { int size; int readp; int writep; pthread_mutex_t mutex; pthread_cond_t empty; pthread_cond_t full; void **data; }; /* default size of fragment buffer in Mbytes */ #define FRAGMENT_BUFFER_DEFAULT 256 /* default size of data buffer in Mbytes */ #define DATA_BUFFER_DEFAULT 256 #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; uid_t uid; gid_t guid; unsigned int mtime; unsigned int xattr; struct dir_ent *dirs; }; struct file_entry { int offset; int size; struct cache_entry *buffer; }; struct squashfs_file { int fd; int blocks; long long file_size; int mode; uid_t uid; gid_t gid; time_t time; char *pathname; char sparse; unsigned int xattr; }; struct path_entry { char *name; regex_t *preg; struct pathname *paths; }; struct pathname { int names; struct path_entry *name; }; struct pathnames { int count; struct pathname *path[0]; }; #define PATHS_ALLOC_SIZE 10 /* globals */ extern struct super_block sBlk; extern squashfs_operations s_ops; extern int swap; extern char *inode_table, *directory_table; extern struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; extern unsigned int *uid_table, *guid_table; extern pthread_mutex_t screen_mutex; extern int progress_enabled; extern int inode_number; extern int lookup_type[]; extern int fd; /* unsquashfs.c */ extern int lookup_entry(struct hash_table_entry **, long long); extern int read_fs_bytes(int fd, long long, int, void *); extern int read_block(int, long long, long long *, void *); /* unsquash-1.c */ extern void read_block_list_1(unsigned int *, char *, int); extern int read_fragment_table_1(); extern struct inode *read_inode_1(unsigned int, unsigned int); extern struct dir *squashfs_opendir_1(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_1(); /* unsquash-2.c */ extern void read_block_list_2(unsigned int *, char *, int); extern int read_fragment_table_2(); extern void read_fragment_2(unsigned int, long long *, int *); extern struct inode *read_inode_2(unsigned int, unsigned int); /* unsquash-3.c */ extern int read_fragment_table_3(); extern void read_fragment_3(unsigned int, long long *, int *); extern struct inode *read_inode_3(unsigned int, unsigned int); extern struct dir *squashfs_opendir_3(unsigned int, unsigned int, struct inode **); /* unsquash-4.c */ extern int read_fragment_table_4(); extern void read_fragment_4(unsigned int, long long *, int *); extern struct inode *read_inode_4(unsigned int, unsigned int); extern struct dir *squashfs_opendir_4(unsigned int, unsigned int, struct inode **); extern int read_uids_guids_4(); ================================================ FILE: src/others/squashfs-4.2-official/unsquashfs_xattr.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquashfs_xattr.c */ #include "unsquashfs.h" #include "xattr.h" #include <sys/xattr.h> extern int root_process; void write_xattr(char *pathname, unsigned int xattr) { unsigned int count; struct xattr_list *xattr_list; int i; if(xattr == SQUASHFS_INVALID_XATTR || sBlk.s.xattr_id_table_start == SQUASHFS_INVALID_BLK) return; xattr_list = get_xattr(xattr, &count); if(xattr_list == NULL) { ERROR("Failed to read xattrs for file %s\n", pathname); return; } for(i = 0; i < count; i++) { int prefix = xattr_list[i].type & SQUASHFS_XATTR_PREFIX_MASK; if(root_process || prefix == SQUASHFS_XATTR_USER) { int res = lsetxattr(pathname, xattr_list[i].full_name, xattr_list[i].value, xattr_list[i].vsize, 0); if(res == -1) ERROR("write_xattr: failed to write xattr %s" " for file %s because %s\n", xattr_list[i].full_name, pathname, errno == ENOSPC || errno == EDQUOT ? "no extended attribute space remaining " "on destination filesystem" : errno == ENOTSUP ? "extended attributes are not supported " "by the destination filesystem" : "a weird error occurred"); } else ERROR("write_xattr: could not write xattr %s " "for file %s because you're not " "superuser!\n", xattr_list[i].full_name, pathname); } } ================================================ FILE: src/others/squashfs-4.2-official/xattr.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2008, 2009, 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xattr.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <sys/xattr.h> #include "squashfs_fs.h" #include "squashfs_swap.h" #include "mksquashfs.h" #include "xattr.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) \ do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) \ do { \ fprintf(stderr, s, ## args); \ } while(0) /* compressed xattr table */ static char *xattr_table = NULL; static unsigned int xattr_size = 0; /* cached uncompressed xattr data */ static char *data_cache = NULL; static int cache_bytes = 0, cache_size = 0; /* cached uncompressed xattr id table */ static struct squashfs_xattr_id *xattr_id_table = NULL; static int xattr_ids = 0; /* saved compressed xattr table */ unsigned int sxattr_bytes = 0, stotal_xattr_bytes = 0; /* saved cached uncompressed xattr data */ static char *sdata_cache = NULL; static int scache_bytes = 0; /* saved cached uncompressed xattr id table */ static int sxattr_ids = 0; /* xattr hash table for value duplicate detection */ static struct xattr_list *dupl[65536]; /* xattr hash table for id duplicate detection */ static struct dupl_id *dupl_id[65536]; /* file system globals from mksquashfs.c */ extern int no_xattrs, noX; extern long long bytes; extern int fd; extern unsigned int xattr_bytes, total_xattr_bytes; /* helper functions from mksquashfs.c */ extern unsigned short get_checksum(char *, int, unsigned short); extern void write_destination(int, long long, int, void *); extern long long generic_write_table(int, void *, int, void *, int); extern int mangle(char *, char *, int, int, int, int); /* helper functions and definitions from read_xattrs.c */ extern int read_xattrs_from_disk(int, struct squashfs_super_block *); extern struct xattr_list *get_xattr(int, unsigned int *); extern struct prefix prefix_table[]; static int get_prefix(struct xattr_list *xattr, char *name) { int i; xattr->full_name = strdup(name); for(i = 0; prefix_table[i].type != -1; i++) { struct prefix *p = &prefix_table[i]; if(strncmp(xattr->full_name, p->prefix, strlen(p->prefix)) == 0) break; } if(prefix_table[i].type != -1) { xattr->name = xattr->full_name + strlen(prefix_table[i].prefix); xattr->size = strlen(xattr->name); } return prefix_table[i].type; } static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) { ssize_t size, vsize; char *xattr_names, *p; int i; struct xattr_list *xattr_list = NULL; while(1) { size = llistxattr(filename, NULL, 0); if(size <= 0) { if(size < 0 && errno != ENOTSUP) ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } xattr_names = malloc(size); if(xattr_names == NULL) { ERROR("Out of memory in read_attrs\n"); return 0; } size = llistxattr(filename, xattr_names, size); if(size < 0) { free(xattr_names); if(errno == ERANGE) /* xattr list grew? Try again */ continue; else { ERROR("llistxattr for %s failed in read_attrs," " because %s\n", filename, strerror(errno)); return 0; } } break; } for(i = 0, p = xattr_names; p < xattr_names + size; i++) { struct xattr_list *x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list)); if(x == NULL) { ERROR("Out of memory in read_attrs\n"); goto failed; } else xattr_list = x; xattr_list[i].type = get_prefix(&xattr_list[i], p); p += strlen(p) + 1; if(xattr_list[i].type == -1) { ERROR("Unrecognised xattr prefix %s\n", xattr_list[i].full_name); free(xattr_list[i].full_name); i--; continue; } while(1) { vsize = lgetxattr(filename, xattr_list[i].full_name, NULL, 0); if(vsize < 0) { ERROR("lgetxattr failed for %s in read_attrs," " because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } xattr_list[i].value = malloc(vsize); if(xattr_list[i].value == NULL) { ERROR("Out of memory in read_attrs\n"); free(xattr_list[i].full_name); goto failed; } vsize = lgetxattr(filename, xattr_list[i].full_name, xattr_list[i].value, vsize); if(vsize < 0) { free(xattr_list[i].value); if(errno == ERANGE) /* xattr grew? Try again */ continue; else { ERROR("lgetxattr failed for %s in " "read_attrs, because %s\n", filename, strerror(errno)); free(xattr_list[i].full_name); goto failed; } } break; } xattr_list[i].vsize = vsize; TRACE("read_xattrs_from_system: filename %s, xattr name %s," " vsize %d\n", filename, xattr_list[i].full_name, xattr_list[i].vsize); } free(xattr_names); *xattrs = xattr_list; return i; failed: while(--i >= 0) { free(xattr_list[i].full_name); free(xattr_list[i].value); } free(xattr_list); free(xattr_names); return 0; } static int get_xattr_size(struct xattr_list *xattr) { int size = sizeof(struct squashfs_xattr_entry) + sizeof(struct squashfs_xattr_val) + xattr->size; if(xattr->type & XATTR_VALUE_OOL) size += XATTR_VALUE_OOL_SIZE; else size += xattr->vsize; return size; } static void *get_xattr_space(unsigned int req_size, long long *disk) { int data_space; unsigned short c_byte; /* * Move and compress cached uncompressed data into xattr table. */ while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { xattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(xattr_table == NULL) { goto failed; } xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noX, 0); TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; memmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } /* * Ensure there's enough space in the uncompressed data cache */ data_space = cache_size - cache_bytes; if(data_space < req_size) { int realloc_size = req_size - data_space; data_cache = realloc(data_cache, cache_size + realloc_size); if(data_cache == NULL) { goto failed; } cache_size += realloc_size; } if(disk) *disk = ((long long) xattr_bytes << 16) | cache_bytes; cache_bytes += req_size; return data_cache + cache_bytes - req_size; failed: ERROR("Out of memory in inode table reallocation!\n"); return NULL; } static struct dupl_id *check_id_dupl(struct xattr_list *xattr_list, int xattrs) { struct dupl_id *entry; int i; unsigned short checksum = 0; /* compute checksum over all xattrs */ for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; checksum = get_checksum(xattr->full_name, strlen(xattr->full_name), checksum); checksum = get_checksum(xattr->value, xattr->vsize, checksum); } for(entry = dupl_id[checksum]; entry; entry = entry->next) { if (entry->xattrs != xattrs) continue; for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; struct xattr_list *dup_xattr = &entry->xattr_list[i]; if(strcmp(xattr->full_name, dup_xattr->full_name)) break; if(memcmp(xattr->value, dup_xattr->value, xattr->vsize)) break; } if(i == xattrs) break; } if(entry == NULL) { /* no duplicate exists */ entry = malloc(sizeof(*entry)); if(entry == NULL) { ERROR("malloc failed in check_ip_dupl\n"); return NULL; } entry->xattrs = xattrs; entry->xattr_list = xattr_list; entry->xattr_id = SQUASHFS_INVALID_XATTR; entry->next = dupl_id[checksum]; dupl_id[checksum] = entry; } return entry; } static void check_value_dupl(struct xattr_list *xattr) { struct xattr_list *entry; if(xattr->vsize < XATTR_VALUE_OOL_SIZE) return; /* Check if this is a duplicate of an existing value */ xattr->vchecksum = get_checksum(xattr->value, xattr->vsize, 0); for(entry = dupl[xattr->vchecksum]; entry; entry = entry->vnext) { if(entry->vsize != xattr->vsize) continue; if(memcmp(entry->value, xattr->value, xattr->vsize) == 0) break; } if(entry == NULL) { /* * No duplicate exists, add to hash table, and mark as * requiring writing */ xattr->vnext = dupl[xattr->vchecksum]; dupl[xattr->vchecksum] = xattr; xattr->ool_value = SQUASHFS_INVALID_BLK; } else { /* * Duplicate exists, make type XATTR_VALUE_OOL, and * remember where the duplicate is */ xattr->type |= XATTR_VALUE_OOL; xattr->ool_value = entry->ool_value; /* on appending don't free duplicate values because the * duplicate value already points to the non-duplicate value */ if(xattr->value != entry->value) { free(xattr->value); xattr->value = entry->value; } } } static int get_xattr_id(int xattrs, struct xattr_list *xattr_list, long long xattr_disk, struct dupl_id *xattr_dupl) { int i, size = 0; struct squashfs_xattr_id *xattr_id; xattr_id_table = realloc(xattr_id_table, (xattr_ids + 1) * sizeof(struct squashfs_xattr_id)); if(xattr_id_table == NULL) { ERROR("Out of memory in xattr_id_table reallocation!\n"); return -1; } /* get total uncompressed size of xattr data, needed for stat */ for(i = 0; i < xattrs; i++) size += strlen(xattr_list[i].full_name) + 1 + xattr_list[i].vsize; xattr_id = &xattr_id_table[xattr_ids]; xattr_id->xattr = xattr_disk; xattr_id->count = xattrs; xattr_id->size = size; /* * keep track of total uncompressed xattr data, needed for mksquashfs * file system summary */ total_xattr_bytes += size; xattr_dupl->xattr_id = xattr_ids ++; return xattr_dupl->xattr_id; } long long write_xattrs() { unsigned short c_byte; int i, avail_bytes; char *datap = data_cache; long long start_bytes = bytes; struct squashfs_xattr_table header; if(xattr_ids == 0) return SQUASHFS_INVALID_BLK; /* * Move and compress cached uncompressed data into xattr table. */ while(cache_bytes) { if((xattr_size - xattr_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { xattr_table = realloc(xattr_table, xattr_size + (SQUASHFS_METADATA_SIZE << 1) + 2); if(xattr_table == NULL) { goto failed; } xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noX, 0); TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; datap += avail_bytes; cache_bytes -= avail_bytes; } /* * Write compressed xattr table to file system */ write_destination(fd, bytes, xattr_bytes, xattr_table); bytes += xattr_bytes; /* * Swap if necessary the xattr id table */ for(i = 0; i < xattr_ids; i++) SQUASHFS_INSWAP_XATTR_ID(&xattr_id_table[i]); header.xattr_ids = xattr_ids; header.xattr_table_start = start_bytes; SQUASHFS_INSWAP_XATTR_TABLE(&header); return generic_write_table(xattr_ids * sizeof(struct squashfs_xattr_id), xattr_id_table, sizeof(header), &header, noX); failed: ERROR("Out of memory in xattr_table reallocation!\n"); return -1; } int generate_xattrs(int xattrs, struct xattr_list *xattr_list) { int total_size, i; int xattr_value_max; void *xp; long long xattr_disk; struct dupl_id *xattr_dupl; /* * check if the file xattrs are a complete duplicate of a pre-existing * id */ xattr_dupl = check_id_dupl(xattr_list, xattrs); if (xattr_dupl == NULL) return SQUASHFS_INVALID_XATTR; if(xattr_dupl->xattr_id != SQUASHFS_INVALID_XATTR) return xattr_dupl->xattr_id; /* * Scan the xattr_list deciding which type to assign to each * xattr. The choice is fairly straightforward, and depends on the * size of each xattr name/value and the overall size of the * resultant xattr list stored in the xattr metadata table. * * Choices are whether to store data inline or out of line. * * The overall goal is to optimise xattr scanning and lookup, and * to enable the file system layout to scale from a couple of * small xattr name/values to a large number of large xattr * names/values without affecting performance. While hopefully * enabling the common case of a couple of small xattr name/values * to be stored efficiently * * Code repeatedly scans, doing the following * move xattr data out of line if it exceeds * xattr_value_max. Where xattr_value_max is * initially XATTR_INLINE_MAX. If the final uncompressed * xattr list is larger than XATTR_TARGET_MAX then more * aggressively move xattr data out of line by repeatedly * setting inline threshold to 1/2, then 1/4, 1/8 of * XATTR_INLINE_MAX until target achieved or there's * nothing left to move out of line */ xattr_value_max = XATTR_INLINE_MAX; while(1) { for(total_size = 0, i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; xattr->type &= XATTR_PREFIX_MASK; /* all inline */ if (xattr->vsize > xattr_value_max) xattr->type |= XATTR_VALUE_OOL; total_size += get_xattr_size(xattr); } /* * If the total size of the uncompressed xattr list is <= * XATTR_TARGET_MAX we're done */ if(total_size <= XATTR_TARGET_MAX) break; if(xattr_value_max == XATTR_VALUE_OOL_SIZE) break; /* * Inline target not yet at minimum and so reduce it, and * try again */ xattr_value_max /= 2; if(xattr_value_max < XATTR_VALUE_OOL_SIZE) xattr_value_max = XATTR_VALUE_OOL_SIZE; } /* * Check xattr values for duplicates */ for(i = 0; i < xattrs; i++) { check_value_dupl(&xattr_list[i]); } /* * Add each out of line value to the file system xattr table * if it doesn't already exist as a duplicate */ for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; if((xattr->type & XATTR_VALUE_OOL) && (xattr->ool_value == SQUASHFS_INVALID_BLK)) { struct squashfs_xattr_val val; int size = sizeof(val) + xattr->vsize; xp = get_xattr_space(size, &xattr->ool_value); val.vsize = xattr->vsize; SQUASHFS_SWAP_XATTR_VAL(&val, xp); memcpy(xp + sizeof(val), xattr->value, xattr->vsize); } } /* * Create xattr list and add to file system xattr table */ get_xattr_space(0, &xattr_disk); for(i = 0; i < xattrs; i++) { struct xattr_list *xattr = &xattr_list[i]; struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; xp = get_xattr_space(sizeof(entry) + xattr->size, NULL); entry.type = xattr->type; entry.size = xattr->size; SQUASHFS_SWAP_XATTR_ENTRY(&entry, xp); memcpy(xp + sizeof(entry), xattr->name, xattr->size); if(xattr->type & XATTR_VALUE_OOL) { int size = sizeof(val) + XATTR_VALUE_OOL_SIZE; xp = get_xattr_space(size, NULL); val.vsize = XATTR_VALUE_OOL_SIZE; SQUASHFS_SWAP_XATTR_VAL(&val, xp); SQUASHFS_SWAP_LONG_LONGS(&xattr->ool_value, xp + sizeof(val), 1); } else { int size = sizeof(val) + xattr->vsize; xp = get_xattr_space(size, &xattr->ool_value); val.vsize = xattr->vsize; SQUASHFS_SWAP_XATTR_VAL(&val, xp); memcpy(xp + sizeof(val), xattr->value, xattr->vsize); } } /* * Add to xattr id lookup table */ return get_xattr_id(xattrs, xattr_list, xattr_disk, xattr_dupl); } int read_xattrs(void *d) { struct dir_ent *dir_ent = d; struct inode_info *inode = dir_ent->inode; char *filename = dir_ent->pathname; struct xattr_list *xattr_list; int xattrs; if(no_xattrs || IS_PSEUDO(inode) || inode->root_entry) return SQUASHFS_INVALID_XATTR; xattrs = read_xattrs_from_system(filename, &xattr_list); if(xattrs == 0) return SQUASHFS_INVALID_XATTR; return generate_xattrs(xattrs, xattr_list); } /* * Add the existing xattr ids and xattr metadata in the file system being * appended to, to the in-memory xattr cache. This allows duplicate checking to * take place against the xattrs already in the file system being appended to, * and ensures the pre-existing xattrs are written out along with any new xattrs */ int get_xattrs(int fd, struct squashfs_super_block *sBlk) { int ids, res, i, id; unsigned int count; TRACE("get_xattrs\n"); res = read_xattrs_from_disk(fd, sBlk); if(res == SQUASHFS_INVALID_BLK || res == 0) goto done; ids = res; /* * for each xattr id read and construct its list of xattr * name:value pairs, and add them to the in-memory xattr cache */ for(i = 0; i < ids; i++) { struct xattr_list *xattr_list = get_xattr(i, &count); if(xattr_list == NULL) { res = 0; goto done; } id = generate_xattrs(count, xattr_list); /* * Sanity check, the new xattr id should be the same as the * xattr id in the original file system */ if(id != i) { ERROR("BUG, different xattr_id in get_xattrs\n"); res = 0; goto done; } } done: return res; } /* * Save current state of xattrs, needed for restoring state in the event of an * abort in appending */ int save_xattrs() { /* save the current state of the compressed xattr data */ sxattr_bytes = xattr_bytes; stotal_xattr_bytes = total_xattr_bytes; /* * save the current state of the cached uncompressed xattr data. * Note we have to save the contents of the data cache because future * operations will delete the current contents */ sdata_cache = malloc(cache_bytes); if(sdata_cache == NULL) goto failed; memcpy(sdata_cache, data_cache, cache_bytes); scache_bytes = cache_bytes; /* save the current state of the xattr id table */ sxattr_ids = xattr_ids; return TRUE; failed: ERROR("Out of memory in save_xattrs\n"); return FALSE; } /* * Restore xattrs in the event of an abort in appending */ void restore_xattrs() { /* restore the state of the compressed xattr data */ xattr_bytes = sxattr_bytes; total_xattr_bytes = stotal_xattr_bytes; /* restore the state of the uncomoressed xattr data */ memcpy(data_cache, sdata_cache, scache_bytes); cache_bytes = scache_bytes; /* restore the state of the xattr id table */ xattr_ids = sxattr_ids; } ================================================ FILE: src/others/squashfs-4.2-official/xattr.h ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only * filesystem. * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xattr.h */ #define XATTR_VALUE_OOL SQUASHFS_XATTR_VALUE_OOL #define XATTR_PREFIX_MASK SQUASHFS_XATTR_PREFIX_MASK #define XATTR_VALUE_OOL_SIZE sizeof(long long) /* maximum size of xattr value data that will be inlined */ #define XATTR_INLINE_MAX 128 /* the target size of an inode's xattr name:value list. If it * exceeds this, then xattr value data will be successively out of lined * until it meets the target */ #define XATTR_TARGET_MAX 65536 #define IS_XATTR(a) (a != SQUASHFS_INVALID_XATTR) struct xattr_list { char *name; char *full_name; int size; int vsize; void *value; int type; long long ool_value; unsigned short vchecksum; struct xattr_list *vnext; }; struct dupl_id { struct xattr_list *xattr_list; int xattrs; int xattr_id; struct dupl_id *next; }; struct prefix { char *prefix; int type; }; extern int generate_xattrs(int, struct xattr_list *); #ifdef XATTR_SUPPORT extern int get_xattrs(int, struct squashfs_super_block *); extern int read_xattrs(void *); extern long long write_xattrs(); extern int save_xattrs(); extern void restore_xattrs(); extern unsigned int xattr_bytes, total_xattr_bytes; extern void write_xattr(char *, unsigned int); extern int read_xattrs_from_disk(int, struct squashfs_super_block *); extern struct xattr_list *get_xattr(int, unsigned int *); #else static inline int get_xattrs(int fd, struct squashfs_super_block *sBlk) { if(sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) { fprintf(stderr, "Xattrs in filesystem! These are not " "supported on this version of Squashfs\n"); return 0; } else return SQUASHFS_INVALID_BLK; } static inline int read_xattrs(void *dir_ent) { return SQUASHFS_INVALID_XATTR; } static inline long long write_xattrs() { return SQUASHFS_INVALID_BLK; } static inline int save_xattrs() { return 1; } static inline void restore_xattrs() { } static inline void write_xattr(char *pathname, unsigned int xattr) { } static inline int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) { if(sBlk->xattr_id_table_start != SQUASHFS_INVALID_BLK) { fprintf(stderr, "Xattrs in filesystem! These are not " "supported on this version of Squashfs\n"); return 0; } else return SQUASHFS_INVALID_BLK; } static inline struct xattr_list *get_xattr(int i, unsigned int *count) { return NULL; } #endif #ifdef XATTR_SUPPORT #ifdef XATTR_DEFAULT #define NOXOPT_STR #define XOPT_STR " (default)" #define XATTR_DEF 0 #else #define NOXOPT_STR " (default)" #define XOPT_STR #define XATTR_DEF 1 #endif #else #define NOXOPT_STR " (default)" #define XOPT_STR " (unsupported)" #define XATTR_DEF 1 #endif ================================================ FILE: src/others/squashfs-4.2-official/xz_wrapper.c ================================================ /* * Copyright (c) 2010, 2011 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xz_wrapper.c * * Support for XZ (LZMA2) compression using XZ Utils liblzma * http://tukaani.org/xz/ */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <lzma.h> #include "squashfs_fs.h" #include "xz_wrapper.h" #include "compressor.h" static struct bcj bcj[] = { { "x86", LZMA_FILTER_X86, 0 }, { "powerpc", LZMA_FILTER_POWERPC, 0 }, { "ia64", LZMA_FILTER_IA64, 0 }, { "arm", LZMA_FILTER_ARM, 0 }, { "armthumb", LZMA_FILTER_ARMTHUMB, 0 }, { "sparc", LZMA_FILTER_SPARC, 0 }, { NULL, LZMA_VLI_UNKNOWN, 0 } }; static struct comp_opts comp_opts; static int filter_count = 1; static int dictionary_size = 0; static float dictionary_percent = 0; static int xz_options(char *argv[], int argc) { int i; char *name; if(strcmp(argv[0], "-Xbcj") == 0) { if(argc < 2) { fprintf(stderr, "xz: -Xbcj missing filter\n"); goto failed; } name = argv[1]; while(name[0] != '\0') { for(i = 0; bcj[i].name; i++) { int n = strlen(bcj[i].name); if((strncmp(name, bcj[i].name, n) == 0) && (name[n] == '\0' || name[n] == ',')) { if(bcj[i].selected == 0) { bcj[i].selected = 1; filter_count++; } name += name[n] == ',' ? n + 1 : n; break; } } if(bcj[i].name == NULL) { fprintf(stderr, "xz: -Xbcj unrecognised " "filter\n"); goto failed; } } return 1; } else if(strcmp(argv[0], "-Xdict-size") == 0) { char *b; float size; if(argc < 2) { fprintf(stderr, "xz: -Xdict-size missing dict-size\n"); goto failed; } size = strtof(argv[1], &b); if(*b == '%') { if(size <= 0 || size > 100) { fprintf(stderr, "xz: -Xdict-size percentage " "should be 0 < dict-size <= 100\n"); goto failed; } dictionary_percent = size; dictionary_size = 0; } else { if((float) ((int) size) != size) { fprintf(stderr, "xz: -Xdict-size can't be " "fractional unless a percentage of the" " block size\n"); goto failed; } dictionary_percent = 0; dictionary_size = (int) size; if(*b == 'k' || *b == 'K') dictionary_size *= 1024; else if(*b == 'm' || *b == 'M') dictionary_size *= 1024 * 1024; else if(*b != '\0') { fprintf(stderr, "xz: -Xdict-size invalid " "dict-size\n"); goto failed; } } return 1; } return -1; failed: return -2; } static int xz_options_post(int block_size) { /* * if -Xdict-size has been specified use this to compute the datablock * dictionary size */ if(dictionary_size || dictionary_percent) { int n; if(dictionary_size) { if(dictionary_size > block_size) { fprintf(stderr, "xz: -Xdict-size is larger than" " block_size\n"); goto failed; } } else dictionary_size = block_size * dictionary_percent / 100; if(dictionary_size < 8192) { fprintf(stderr, "xz: -Xdict-size should be 8192 bytes " "or larger\n"); goto failed; } /* * dictionary_size must be storable in xz header as either * 2^n or as 2^n+2^(n+1) */ n = ffs(dictionary_size) - 1; if(dictionary_size != (1 << n) && dictionary_size != ((1 << n) + (1 << (n + 1)))) { fprintf(stderr, "xz: -Xdict-size is an unsupported " "value, dict-size must be storable in xz " "header\n"); fprintf(stderr, "as either 2^n or as 2^n+2^(n+1). " "Example dict-sizes are 75%%, 50%%, 37.5%%, " "25%%,\n"); fprintf(stderr, "or 32K, 16K, 8K etc.\n"); goto failed; } } else /* No -Xdict-size specified, use defaults */ dictionary_size = block_size; return 0; failed: return -1; } static void *xz_dump_options(int block_size, int *size) { int flags = 0, i; /* * don't store compressor specific options in file system if the * default options are being used - no compressor options in the * file system means the default options are always assumed * * Defaults are: * metadata dictionary size: SQUASHFS_METADATA_SIZE * datablock dictionary size: block_size * 1 filter */ if(dictionary_size == block_size && filter_count == 1) return NULL; for(i = 0; bcj[i].name; i++) flags |= bcj[i].selected << i; comp_opts.dictionary_size = dictionary_size; comp_opts.flags = flags; SQUASHFS_INSWAP_COMP_OPTS(&comp_opts); *size = sizeof(comp_opts); return &comp_opts; } static int xz_extract_options(int block_size, void *buffer, int size) { struct comp_opts *comp_opts = buffer; int flags, i, n; if(size == 0) { /* set defaults */ dictionary_size = block_size; flags = 0; } else { /* check passed comp opts struct is of the correct length */ if(size != sizeof(struct comp_opts)) goto failed; SQUASHFS_INSWAP_COMP_OPTS(comp_opts); dictionary_size = comp_opts->dictionary_size; flags = comp_opts->flags; /* * check that the dictionary size seems correct - the dictionary * size should 2^n or 2^n+2^(n+1) */ n = ffs(dictionary_size) - 1; if(dictionary_size != (1 << n) && dictionary_size != ((1 << n) + (1 << (n + 1)))) goto failed; } filter_count = 1; for(i = 0; bcj[i].name; i++) { if((flags >> i) & 1) { bcj[i].selected = 1; filter_count ++; } else bcj[i].selected = 0; } return 0; failed: fprintf(stderr, "xz: error reading stored compressor options from " "filesystem!\n"); return -1; } static int xz_init(void **strm, int block_size, int datablock) { int i, j, filters = datablock ? filter_count : 1; struct filter *filter = malloc(filters * sizeof(struct filter)); struct xz_stream *stream; if(filter == NULL) goto failed; stream = *strm = malloc(sizeof(struct xz_stream)); if(stream == NULL) goto failed2; stream->filter = filter; stream->filters = filters; memset(filter, 0, filters * sizeof(struct filter)); stream->dictionary_size = datablock ? dictionary_size : SQUASHFS_METADATA_SIZE; filter[0].filter[0].id = LZMA_FILTER_LZMA2; filter[0].filter[0].options = &stream->opt; filter[0].filter[1].id = LZMA_VLI_UNKNOWN; for(i = 0, j = 1; datablock && bcj[i].name; i++) { if(bcj[i].selected) { filter[j].buffer = malloc(block_size); if(filter[j].buffer == NULL) goto failed3; filter[j].filter[0].id = bcj[i].id; filter[j].filter[1].id = LZMA_FILTER_LZMA2; filter[j].filter[1].options = &stream->opt; filter[j].filter[2].id = LZMA_VLI_UNKNOWN; j++; } } return 0; failed3: for(i = 1; i < filters; i++) free(filter[i].buffer); free(stream); failed2: free(filter); failed: return -1; } static int xz_compress(void *strm, void *dest, void *src, int size, int block_size, int *error) { int i; lzma_ret res = 0; struct xz_stream *stream = strm; struct filter *selected = NULL; stream->filter[0].buffer = dest; for(i = 0; i < stream->filters; i++) { struct filter *filter = &stream->filter[i]; if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT)) goto failed; stream->opt.dict_size = stream->dictionary_size; filter->length = 0; res = lzma_stream_buffer_encode(filter->filter, LZMA_CHECK_CRC32, NULL, src, size, filter->buffer, &filter->length, block_size); if(res == LZMA_OK) { if(!selected || selected->length > filter->length) selected = filter; } else if(res != LZMA_BUF_ERROR) goto failed; } if(!selected) /* * Output buffer overflow. Return out of buffer space */ return 0; if(selected->buffer != dest) memcpy(dest, selected->buffer, selected->length); return (int) selected->length; failed: /* * All other errors return failure, with the compressor * specific error code in *error */ *error = res; return -1; } static int xz_uncompress(void *dest, void *src, int size, int block_size, int *error) { size_t src_pos = 0; size_t dest_pos = 0; uint64_t memlimit = MEMLIMIT; lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL, src, &src_pos, size, dest, &dest_pos, block_size); *error = res; return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1; } void xz_usage() { fprintf(stderr, "\t -Xbcj filter1,filter2,...,filterN\n"); fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in"); fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose"); fprintf(stderr, " the best compression.\n"); fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,"); fprintf(stderr, " powerpc, sparc, ia64\n"); fprintf(stderr, "\t -Xdict-size <dict-size>\n"); fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size. The"); fprintf(stderr, " dictionary size\n\t\tcan be specified as a"); fprintf(stderr, " percentage of the block size, or as an\n\t\t"); fprintf(stderr, "absolute value. The dictionary size must be less"); fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes"); fprintf(stderr, " or larger. It must also be\n\t\tstorable in the xz"); fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t"); fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or"); fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n"); } struct compressor xz_comp_ops = { .init = xz_init, .compress = xz_compress, .uncompress = xz_uncompress, .options = xz_options, .options_post = xz_options_post, .dump_options = xz_dump_options, .extract_options = xz_extract_options, .usage = xz_usage, .id = XZ_COMPRESSION, .name = "xz", .supported = 1 }; ================================================ FILE: src/others/squashfs-4.2-official/xz_wrapper.h ================================================ #ifndef XZ_WRAPPER_H #define XZ_WRAPPER_H /* * Squashfs * * Copyright (c) 2010 * Phillip Lougher <phillip@lougher.demon.co.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * xz_wrapper.h * */ #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #if __BYTE_ORDER == __BIG_ENDIAN extern unsigned int inswap_le32(unsigned int); #define SQUASHFS_INSWAP_COMP_OPTS(s) { \ (s)->dictionary_size = inswap_le32((s)->dictionary_size); \ (s)->flags = inswap_le32((s)->flags); \ } #else #define SQUASHFS_INSWAP_COMP_OPTS(s) #endif #define MEMLIMIT (32 * 1024 * 1024) struct bcj { char *name; lzma_vli id; int selected; }; struct filter { void *buffer; lzma_filter filter[3]; size_t length; }; struct xz_stream { struct filter *filter; int filters; int dictionary_size; lzma_options_lzma opt; }; struct comp_opts { int dictionary_size; int flags; }; #endif ================================================ FILE: src/others/squashfs-hg55x-bin/README ================================================ This is a binary grabbed from the internet with no source code. It appears OK, but no guaruntees. For most systems, the squashfs-2.0-nb4 tools should be a suitable substitute for this binary. Use them instead. ================================================ FILE: src/splitter3.cc ================================================ /* splitter3.cc * Copyright (C) 2010 Jeremy Collake <jeremy.collake@gmail.com> * A product of Bitsum Technologies * http://www.bitsum.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ********************************************************************************** * * This little utility patches a specific type of simple OpenWrt (embedded linux) * based firmware found on a particular manufacturer's router. * */ #define _VERSION_ "0.10 beta" #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <sys/types.h> #include <endian.h> #include <byteswap.h> #include <sys/types.h> #include "untrx.h" /************************************************************************* * IdentifySegment * * identifies segments (i.e. squashfs, cramfs) and their version numbers * **************************************************************************/ SEGMENT_TYPE IdentifySegment(unsigned char *pData, unsigned int nLength) { squashfs_super_block *sqblock=(squashfs_super_block *)pData; cramfs_super *crblock=(cramfs_super *)pData; if(sqblock->s_magic==SQUASHFS_MAGIC || sqblock->s_magic==SQUASHFS_MAGIC_SWAP || sqblock->s_magic==SQUASHFS_MAGIC_ALT || sqblock->s_magic==SQUASHFS_MAGIC_ALT_SWAP) { fprintf(stderr, " SQUASHFS magic: 0x%x\n", sqblock->s_magic); short major = READ16_LE(sqblock->s_major); short minor = READ16_LE(sqblock->s_minor); fprintf(stderr, " SQUASHFS version: %d.%d\n", major, minor); switch(major) { case 3: switch (minor) { case 0: return SEGMENT_TYPE_SQUASHFS_3_0; case 1: return SEGMENT_TYPE_SQUASHFS_3_1; case 2: return SEGMENT_TYPE_SQUASHFS_3_2; default: return SEGMENT_TYPE_SQUASHFS_3_x; } case 2: switch (minor) { case 0: return SEGMENT_TYPE_SQUASHFS_2_0; case 1: return SEGMENT_TYPE_SQUASHFS_2_1; default: return SEGMENT_TYPE_SQUASHFS_2_x; } default: return SEGMENT_TYPE_SQUASHFS_OTHER; } } else if(crblock->magic==CRAMFS_MAGIC || crblock->magic==CRAMFS_MAGIC_SWAP) { return SEGMENT_TYPE_CRAMFS_x_x; } return SEGMENT_TYPE_UNTYPED; } /************************************************************************* * EmitSquashfsMagic * * writes the squashfs root block signature to a file, as a fix for * Brainslayer of DD-WRT deciding to change it to some arbitrary value * to break compatibility with this kit. * **************************************************************************/ int EmitSquashfsMagic(squashfs_super_block *pSuper, char *pszOutFile) { fprintf(stderr, " Writing %s\n", pszOutFile); FILE *fOut=fopen(pszOutFile,"wb"); if(!fOut) return 0; if(fwrite(pSuper,1,4,fOut)!=4) { fclose(fOut); return 0; } fclose(fOut); return 1; } /************************************************************************* * ShowUsage * * **************************************************************************/ void ShowUsage() { fprintf(stderr, " ERROR: Invalid usage.\n" " USAGE: splitter3 binfile outfolder\n"); exit(9); } /************************************************************************* * main * * **************************************************************************/ int main(int argc, char **argv) { fprintf(stderr, " splitter3 " _VERSION_ " - (c)2010 Jeremy Collake\n"); if(argc<3) { ShowUsage(); } fprintf(stderr, " Opening %s\n", argv[1]); FILE *fIn=fopen(argv[1],"rb"); if(!fIn) { fprintf(stderr, " ERROR opening %s\n", argv[1]); exit(1); } char *pszOutFolder=(char *)malloc(strlen(argv[2])+sizeof(char)); strcpy(pszOutFolder,argv[2]); if(pszOutFolder[strlen(pszOutFolder)-1]=='/') { pszOutFolder[strlen(pszOutFolder)-1]=0; } fseek(fIn,0,SEEK_END); size_t nFilesize=ftell(fIn); fseek(fIn,0,SEEK_SET); unsigned char *pData=(unsigned char *)malloc(nFilesize); unsigned char *pDataOrg=pData; if(fread(pData,1,nFilesize,fIn)!=nFilesize) { fprintf(stderr," ERROR reading %s\n", argv[1]); fclose(fIn); free(pDataOrg); free(pszOutFolder); exit(1); } fclose(fIn); fprintf(stderr, " read %u bytes\n", nFilesize); /* Extract the segments */ unsigned int nKernelLength=0; // do stupid linear search for 'sqsh' (yes, I'm that lazy) for(unsigned int nI=0;nI<(nFilesize-4);nI++) { // TODO: add extra bounds check to IdentifySegment SEGMENT_TYPE segType=IdentifySegment(pDataOrg+nI,4); if(segType!=SEGMENT_TYPE_UNTYPED) { fprintf(stderr, " Found segment type 0x%x", segType); nKernelLength=nI; break; } } if(!nKernelLength) { fprintf(stderr, " ERROR: Could not locate any file system in image. Perhaps obfuscated or unknown FS"); free(pDataOrg); exit(2); } // now go to last 4096 block of file, as the FS will end on this and trailer begin // alternate way nTrailerOffset&0xfffff000 but may not be great for platform compatibility unsigned int nTrailerOffset=(nFilesize/4096)*4096; // do safe method, 32-bit, 64-bit, any size ints unsigned int nTrailerLength=nFilesize-nTrailerOffset; unsigned int nFilesystemLength=nTrailerOffset-nKernelLength; fprintf(stderr, " Kernel length is %x\n File system length is %x\n Trailer is %x bytes\n", nKernelLength, nFilesystemLength, nTrailerLength); // allocate filename buffer char *pszTemp=(char *) malloc((strlen(pszOutFolder)*sizeof(char))+(128*sizeof(char))); for(unsigned int nI=0;nI<3;nI++) { FILE *fOut; unsigned int nOffset,nLength; switch(nI) { case 0: nOffset=0; nLength=nKernelLength; break; case 1: nOffset=nKernelLength; nLength=nFilesystemLength; break; case 2: nOffset=nTrailerOffset; nLength=nTrailerLength; break; default: // assert here break; } switch(IdentifySegment(pDataOrg+nOffset,nLength)) { case SEGMENT_TYPE_SQUASHFS_3_0: fprintf(stderr, " SQUASHFS v3.0 image detected\n"); sprintf(pszTemp,"%s/squashfs_magic",pszOutFolder); if(!EmitSquashfsMagic((squashfs_super_block *)pData,pszTemp)) { fprintf(stderr," ERROR - writing %s\n", pszTemp); free(pDataOrg); free(pszOutFolder); free(pszTemp); exit(3); } sprintf(pszTemp,"%s/squashfs-lzma-image-3_0",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_3_1: fprintf(stderr, " SQUASHFS v3.1 image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-3_1",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_3_2: fprintf(stderr, " SQUASHFS v3.2 image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-3_2",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_3_x: fprintf(stderr, " SQUASHFS v3.x (>3.2) image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-3_x",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_2_0: fprintf(stderr, " SQUASHFS v2.0 image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-2_0",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_2_1: fprintf(stderr, " SQUASHFS v2.1 image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-2_1",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_2_x: fprintf(stderr, " SQUASHFS v2.x image detected\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-2_x",pszOutFolder); break; case SEGMENT_TYPE_SQUASHFS_OTHER: fprintf(stderr, " ! WARNING: Unknown squashfs version.\n"); sprintf(pszTemp,"%s/squashfs-lzma-image-x_x",pszOutFolder); break; case SEGMENT_TYPE_CRAMFS_x_x: fprintf(stderr, " CRAMFS v? image detected\n"); sprintf(pszTemp,"%s/cramfs-image-x_x",pszOutFolder); break; default: if(!nI) { sprintf(pszTemp,"%s/vmlinuz",pszOutFolder); } else if(nI==2) { sprintf(pszTemp,"%s/hwid.txt",pszOutFolder); } else { // should add assertion sprintf(pszTemp,"%s/part%d.bin",pszOutFolder,nI); } break; } fprintf(stderr," Writing %s\n size %d from offset %d ...\n", pszTemp, nLength, pData-pDataOrg); fOut=fopen(pszTemp,"wb"); if(!fOut) { fprintf(stderr," ERROR could not open %s\n", pszTemp); free(pDataOrg); free(pszOutFolder); free(pszTemp); exit(3); } if(!fwrite(pData,1,nLength,fOut)) { fprintf(stderr," ERROR could not write %s\n", pszTemp); fclose(fOut); free(pDataOrg); free(pszOutFolder); free(pszTemp); exit(4); } fclose(fOut); pData+=nLength; } free(pDataOrg); free(pszOutFolder); free(pszTemp); printf(" Done!\n"); exit(0); } ================================================ FILE: src/squashfs-2.1-r2/Makefile ================================================ CC := gcc CXX := g++ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 LZMAPATH = ../lzma/C/7zip/Compress/LZMA_Lib all: mksquashfs-lzma mksquashfs unsquashfs-lzma unsquashfs mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@ mksquashfs-lzma: mksquashfs.o read_fs.o sort.o make -C $(LZMAPATH) $(CXX) -O3 mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -llzma -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h sort.o: sort.c squashfs_fs.h unsquashfs-lzma: unsquashfs.o make -C $(LZMAPATH) $(CXX) -O3 unsquashfs.o -L$(LZMAPATH) -llzma -o $@ unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h clean: rm -f *.o rm -f mksquashfs rm -f unsquashfs rm -f mksquashfs-lzma rm -f unsquashfs-lzma rm -f mksquashfs.exe rm -f unsquashfs.exe rm -f mksquashfs-lzma.exe rm -f unsquashfs-lzma.exe make -C $(LZMAPATH) clean ================================================ FILE: src/squashfs-2.1-r2/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <endian.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/mman.h> #include "mksquashfs.h" #include <squashfs_fs.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { if(!silent) printf("mksquashfs: "s, ## args); } while(0) #define ERROR(s, args...) do { fprintf(stderr, s, ## args); } while(0) #define EXIT_MKSQUASHFS() do { if(restore)\ restorefs();\ exit(1); } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int total_compressed = 0, total_uncompressed = 0; int fd; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; int filesystem_minor_version = SQUASHFS_MINOR; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ unsigned int bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* in memory directory data */ #define I_COUNT_SIZE 128 struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; struct dir_ent **list; char *pathname; unsigned int count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; unsigned char *index_count_p; }; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536], *frag_dups[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; char fragment_data[SQUASHFS_FILE_SIZE]; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { unsigned int bytes; unsigned short checksum; unsigned int start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; unsigned short fragment_checksum; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; unsigned int sbytes, sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_bytes, stotal_inode_bytes, stotal_directory_bytes, sinode_count, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* structure to used to pass in a pointer or an integer * to duplicate buffer read helper functions. */ struct duplicate_buffer_handle { unsigned char *ptr; unsigned int start; }; void add_old_root_entry(char *name, squashfs_inode inode, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table); squashfs_inode get_sorted_inode(struct stat *buf); int read_sort_file(char *filename, int source, char *source_path[]); void sort_files_and_write(int source, char *source_path[]); struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes); #define FALSE 0 #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) void restorefs() { ERROR("Exiting - restoring original filesystem!\n\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(interrupted == 1) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); interrupted ++; } } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte = block_size << 1; unsigned int res; if(!uncompressed && (res = compress2(d, &c_byte, s, size, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); return 0; } if(uncompressed || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, unsigned int byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } } void write_bytes(int fd, unsigned int byte, int bytes, char *buff) { off_t off = byte; if(off + bytes > ((long long)1<<32) - 1 ) BAD_ERROR("Filesystem greater than maximum size 2^32 - 1\n"); if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } } unsigned int write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; unsigned int start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } unsigned int write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; unsigned int start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, char *filename, int type, int byte_size, squashfs_block start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct cached_dir_index *index, unsigned int i_count, unsigned int i_size) { struct stat buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; if(filename[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO; buf.st_uid = getuid(); buf.st_gid = getgid(); buf.st_mtime = time(NULL); } else if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); return FALSE; } base->mode = SQUASHFS_MODE(buf.st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf.st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf.st_gid : global_gid); if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->mtime = buf.st_mtime; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %x, blocks %d, fragment %d, offset %d, size %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->mtime = buf.st_mtime; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %x, offset %x\n", byte_size, start_block, offset); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->mtime = buf.st_mtime; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %x, offset %x\n", byte_size, start_block, offset); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->rdev = (unsigned short) ((major(buf.st_rdev) << 8) | (minor(buf.st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x\n", dev->rdev); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d\n", byte); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket"); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%Lx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void init_dir(struct directory *dir) { if((dir->buff = (char *)malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->list = NULL; dir->pathname = NULL; dir->count = dir->current_count = dir->i_count = dir->byte_count = dir->i_size = 0; dir->dir_is_ldir = TRUE; } void add_dir(squashfs_inode inode, char *name, int type, struct directory *dir) { char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + 6 >= dir->buff + dir->size) { if((buff = (char *) realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE))) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, char *filename, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir->dir_is_ldir) { if(create_inode(inode, filename, SQUASHFS_LDIR_TYPE, dir_size, directory_block, directory_offset, NULL, NULL, dir->index, dir->i_count, dir->i_size) == FALSE) return FALSE; } else { if(create_inode(inode, filename, SQUASHFS_DIR_TYPE, dir_size, directory_block, directory_offset, NULL, NULL, NULL, 0, 0) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%Lx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment) { squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index]; int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress(buffer, &bytes, (const char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); return buffer + fragment->offset; } void write_fragment() { int compressed_size; unsigned char buffer[block_size << 1]; if(fragment_size == 0) return; if(fragments % FRAG_SIZE == 0) if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) BAD_ERROR("Out of memory in fragment table\n"); fragment_table[fragments].size = mangle(buffer, fragment_data, fragment_size, block_size, noF, 1); fragment_table[fragments].start_block = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[fragments].size); write_bytes(fd, bytes, compressed_size, buffer); bytes += compressed_size; total_uncompressed += fragment_size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n",fragments, fragment_size, compressed_size); fragments ++; fragment_size = 0; } static struct fragment empty_fragment = {SQUASHFS_INVALID_BLK, 0, 0}; struct fragment *get_and_fill_fragment(char *buff, int size) { struct fragment *ffrg; if(size == 0) return &empty_fragment; if(fragment_size + size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = size; memcpy(fragment_data + fragment_size, buff, size); fragment_size += size; return ffrg; } unsigned int write_fragment_table() { unsigned int start_bytes, frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments), meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; unsigned short c_byte; int i, compressed_size; squashfs_fragment_index list[meta_blocks]; TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %x, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } for(i = 0; i < meta_blocks; i++) { int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { squashfs_fragment_index slist[meta_blocks]; SQUASHFS_SWAP_FRAGMENT_INDEXES(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); return start_bytes; } unsigned char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { unsigned char *v = handle->ptr; handle->ptr += avail_bytes; return v; } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; unsigned char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer); handle->start += avail_bytes; return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, int l) { unsigned short chksum = 0; unsigned int bytes = 0; unsigned char *b; struct duplicate_buffer_handle position = *handle; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; b = get_next_file_block(&position, bytes); while(bytes--) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } } return chksum; } int cached_frag = -1; void add_file(int start, int file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; struct file_info *dupl_ptr; char *datap; struct duplicate_buffer_handle handle; if(!duplicate_checking) return; if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; if(fragment == cached_frag || fragment == SQUASHFS_INVALID_BLK) datap = fragment_data + offset; else datap = get_fragment(fragment_data, frg); handle.start = start; if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL) dupl_ptr->fragment = frg; cached_frag = fragment; } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; struct file_info *duplicate(unsigned char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, int bytes, unsigned int **block_list, int *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes) { unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes); struct duplicate_buffer_handle handle = { frag_data, 0 }; unsigned short fragment_checksum = get_checksum(read_from_buffer, &handle, frag_bytes); struct file_info *dupl_ptr = bytes ? dupl[checksum] : frag_dups[fragment_checksum]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) { unsigned char buffer1[SQUASHFS_FILE_MAX_SIZE]; unsigned int dup_bytes = dupl_ptr->bytes, dup_start = dupl_ptr->start; struct duplicate_buffer_handle position = *file_start; unsigned char *buffer; while(dup_bytes) { int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes; buffer = get_next_file_block(&position, avail_bytes); read_bytes(fd, dup_start, avail_bytes, buffer1); if(memcmp(buffer, buffer1, avail_bytes) != 0) break; dup_bytes -= avail_bytes; dup_start += avail_bytes; } if(dup_bytes == 0) { char *fragment_buffer1; if(dupl_ptr->fragment->index == fragments || dupl_ptr->fragment->index == SQUASHFS_INVALID_BLK) fragment_buffer1 = fragment_data + dupl_ptr->fragment->offset; else if(dupl_ptr->fragment->index == cached_frag1) fragment_buffer1 = cached_fragment + dupl_ptr->fragment->offset; else { fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment); cached_frag1 = dupl_ptr->fragment->index; } if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%x, size %d, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->bytes = bytes; dupl_ptr->checksum = checksum; dupl_ptr->start = *start; dupl_ptr->fragment_checksum = fragment_checksum; if((dupl_ptr->block_list = (unsigned int *) malloc(blocks * sizeof(unsigned int))) == NULL) { BAD_ERROR("Out of memory allocating block_list\n"); } memcpy(dupl_ptr->block_list, *block_list, blocks * sizeof(unsigned int)); dup_files ++; if(bytes) { dupl_ptr->next = dupl[checksum]; dupl[checksum] = dupl_ptr; } else { dupl_ptr->next = frag_dups[fragment_checksum]; frag_dups[fragment_checksum] = dupl_ptr; } return dupl_ptr; } #define MINALLOCBYTES (1024 * 1024) int write_file(squashfs_inode *inode, char *filename, long long size, int *duplicate_file) { unsigned int frag_bytes, file, start, file_bytes = 0, block = 0; unsigned int c_byte; long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; unsigned int blocks = (read_size + block_size - 1) >> block_log; unsigned int block_list[blocks], *block_listp = block_list; char buff[block_size], *c_buffer; int allocated_blocks = blocks, i, bbytes, whole_file = 1; struct fragment *fragment; struct file_info *dupl_ptr = NULL; struct duplicate_buffer_handle handle; if(!no_fragments && (read_size < block_size || always_use_fragments)) { allocated_blocks = blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if(size > read_size) ERROR("file %s truncated to %Ld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE); total_bytes += read_size; if((file = open(filename, O_RDONLY)) == -1) { perror("Error in opening file, skipping..."); return FALSE; } do { if((c_buffer = (char *) malloc((allocated_blocks + 1) << block_log)) == NULL) { TRACE("Out of memory allocating write_file buffer, allocated_blocks %d, blocks %d\n", allocated_blocks, blocks); whole_file = 0; if((allocated_blocks << (block_log - 1)) < MINALLOCBYTES) BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %d blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10)); allocated_blocks >>= 1; } } while(!c_buffer); for(start = bytes; block < blocks; file_bytes += bbytes) { for(i = 0, bbytes = 0; (i < allocated_blocks) && (block < blocks); i++) { int available_bytes = read_size - (block * block_size) > block_size ? block_size : read_size - (block * block_size); if(read(file, buff, available_bytes) == -1) goto read_err; c_byte = mangle(c_buffer + bbytes, buff, available_bytes, block_size, noD, 1); block_list[block ++] = c_byte; bbytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); } if(!whole_file) { write_bytes(fd, bytes, bbytes, c_buffer); bytes += bbytes; } } if(frag_bytes != 0) if(read(file, buff, frag_bytes) == -1) goto read_err; close(file); if(whole_file) { handle.ptr = c_buffer; if(duplicate_checking && (dupl_ptr = duplicate(read_from_buffer, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { *duplicate_file = TRUE; goto wr_inode; } write_bytes(fd, bytes, file_bytes, c_buffer); bytes += file_bytes; } else { handle.start = start; if(duplicate_checking && (dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { bytes = start; if(!block_device) ftruncate(fd, bytes); *duplicate_file = TRUE; goto wr_inode; } } fragment = get_and_fill_fragment(buff, frag_bytes); if(duplicate_checking) dupl_ptr->fragment = fragment; *duplicate_file = FALSE; wr_inode: free(c_buffer); file_count ++; return create_inode(inode, filename, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL, 0, 0); read_err: perror("Error in reading file, skipping..."); free(c_buffer); return FALSE; } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } #define DIR_ENTRIES 256 struct dir_ent { char *name; char *pathname; struct old_root_entry_info *data; }; void inline add_dir_entry(char *name, char *pathname, void *data, struct directory *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count ++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct directory *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if(filesystem_minor_version == 0 || (dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } int linux_opendir(char *pathname, struct directory *dir) { DIR *linuxdir; struct dirent *d_name; dir->pathname = strdup(pathname); if((linuxdir = opendir(pathname)) == NULL) return 0; while((d_name = readdir(linuxdir)) != NULL) { if(strcmp(d_name->d_name, ".") != 0 && strcmp(d_name->d_name, "..") != 0) add_dir_entry(d_name->d_name, NULL, NULL, dir); } closedir(linuxdir); sort_directory(dir); return 1; } int encomp_opendir(char *pathname, struct directory *dir) { int i, n, pass; char *basename, dir_name[8192]; for(i = 0; i < old_root_entries; i++) add_dir_entry(old_root_entry[i].name, "", &old_root_entry[i], dir); for(i = 0; i < source; i++) { if((basename = getbase(source_path[i])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[i]); continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } add_dir_entry(dir_name, source_path[i], NULL, dir); } sort_directory(dir); return 1; } int single_opendir(char *pathname, struct directory *dir) { DIR *linuxdir; struct dirent *d_name; int i, pass; char dir_name[1024], filename[8192]; for(i = 0; i < old_root_entries; i++) add_dir_entry(old_root_entry[i].name, "", &old_root_entry[i], dir); if((linuxdir = opendir(pathname)) == NULL) return 0; while((d_name = readdir(linuxdir)) != NULL) { if(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0) continue; strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(filename, pathname), "/"), d_name->d_name); add_dir_entry(dir_name, filename, NULL, dir); } closedir(linuxdir); sort_directory(dir); return 1; } int linux_readdir(struct directory *dir, char **filename, char **dir_name) { int current_count; while((current_count = dir->current_count++) < dir->count) if(dir->list[current_count]->data) add_dir(dir->list[current_count]->data->inode, dir->list[current_count]->name, dir->list[current_count]->data->type, dir); else { if(dir->list[current_count]->pathname) *filename = dir->list[current_count]->pathname; else strcat(strcat(strcpy(*filename, dir->pathname), "/"), dir->list[current_count]->name); *dir_name = dir->list[current_count]->name; return 1; } return FALSE; } void linux_freedir(struct directory *dir) { int i; for(i = 0; i < dir->count; i++) { if(dir->list[i]->pathname) free(dir->list[i]->pathname); free(dir->list[i]->name); free(dir->list[i]); } if(dir->index) free(dir->index); if(dir->list) free(dir->list); free(dir->buff); } int dir_scan(squashfs_inode *inode, char *pathname, int (_opendir)(char *, struct directory *)) { struct stat buf; char filename2[8192], *filename = filename2, *dir_name; int squashfs_type; struct directory dir; int result = FALSE; init_dir(&dir); if(_opendir(pathname, &dir) == 0) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(linux_readdir(&dir, &filename, &dir_name) != FALSE) { if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; switch(buf.st_mode & S_IFMT) { case S_IFREG: { int duplicate_file; squashfs_type = SQUASHFS_FILE_TYPE; if(!sorted) { result = write_file(inode, filename, buf.st_size, &duplicate_file); INFO("file %s, uncompressed size %Ld bytes, %s\n", filename, buf.st_size, duplicate_file ? "DUPLICATE" : ""); } else *inode = get_sorted_inode(&buf); break; } case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan(inode, filename, linux_opendir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, filename, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0, 0); INFO("symbolic link %s inode 0x%Lx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, filename, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0, 0); INFO("character device %s inode 0x%Lx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, filename, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0, 0); INFO("block device %s inode 0x%Lx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, filename, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0, 0); INFO("fifo %s inode 0x%Lx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, filename, squashfs_type, 0, 0, 0, NULL, NULL, NULL, 0, 0); INFO("unix domain socket %s inode 0x%Lx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf.st_mode); continue; } if(result) add_dir(*inode, dir_name, squashfs_type, &dir); } result = write_dir(inode, pathname, &dir); INFO("directory %s inode 0x%Lx\n", pathname, *inode); error: linux_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 9; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries++].type = type; } #define VERSION() \ printf("mksquashfs version 2.1\n");\ printf("copyright (C) 2004 Phillip Lougher (plougher@users.sourceforge.net)\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, delete = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 512 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-2.0") == 0) filesystem_minor_version = 0; else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-2.0\t\t\tcreate a 2.0 filesystem\n"); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); exit(1); } } if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { if(S_ISREG(buf.st_mode)) { /* reopen truncating file */ close(fd); if((fd = open(argv[source + 1], O_TRUNC | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } delete = TRUE; } } } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); exit(1); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); exit(1); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, filesystem_minor_version, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data; unsigned root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); filesystem_minor_version = sBlk.s_minor; if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, add_old_root_entry, &fragment_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); exit(1); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, filesystem_minor_version, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -2.0 options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + (inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1)); uncompressed_data = inode_dir_offset + (inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1)); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(stat(source_path[0], &buf) == -1) { perror("Cannot stat source directory"); EXIT_MKSQUASHFS(); } if(sorted) sort_files_and_write(source, source_path); if(delete && !keep_as_directory && source == 1 && S_ISDIR(buf.st_mode)) dir_scan(&inode, source_path[0], linux_opendir); else if(!keep_as_directory && source == 1 && S_ISDIR(buf.st_mode)) dir_scan(&inode, source_path[0], single_opendir); else dir_scan(&inode, "", encomp_opendir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = filesystem_minor_version; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); TRACE("sBlk->inode_table_start 0x%x\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%x\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%x\n", sBlk.fragment_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { unsigned char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/squashfs-2.1-r2/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/squashfs-2.1-r2/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, unsigned int, int, char *); extern int add_file(int, int, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <endian.h> #include "read_fs.h" #include <squashfs_fs.h> #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) fprintf(stderr, s, ## args) int swap; int read_block(int fd, int start, int *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { unsigned char buffer[SQUASHFS_METADATA_SIZE]; int res; long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, int start, int end, int root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, unsigned int *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%x, end 0x%x, root_inode_start 0x%x\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%x containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%x\n", start); if((bytes += read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_BLK ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_BLK ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; int file_bytes = 0, i, start = inode.start_block; unsigned int block_list[blocks]; TRACE("scan_inode_table: regular file, file_size %d, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); free(*inode_table); return FALSE; } } return files; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major == 1) ERROR("Filesystem on %s is a SQUASHFS 1.x filesystem. Appending\nto SQUASHFS 1.x filesystems is not supported. Please convert it to a SQUASHFS 2.1 filesystem...n", source); else ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d), I support (%d: <= %d)\n", source, sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid SQUASHFS superblock on %s.\n", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); printf("\tFilesystem size %d bytes\n", sBlk->bytes_used); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %x\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, int start, int offset, int size, int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int bytes = 0, dir_count; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%x, bytes read so far %d\n", start, bytes); *last_directory_block = start; if((bytes += read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->type); bytes += dire->size + 1; } } all_done: return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%x\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%x, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } int read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, unsigned int *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, void (push_directory_entry)(char *, squashfs_inode, int), squashfs_fragment_entry **fragment_table) { unsigned char *inode_table = NULL, *directory_table; unsigned int start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size; } if((directory_table = squashfs_readdir(fd, !root_name, sBlk->directory_table_start + *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); *last_directory_block -= sBlk->directory_table_start; if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/squashfs-2.1-r2/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/squashfs-2.1-r2/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) printf("mksquashfs: "s, ## args) #else #define TRACE(s, args...) #endif #define INFO(s, args...) if(!silent) printf("mksquashfs: "s, ## args) #define ERROR(s, args...) fprintf(stderr, s, ## args) #define EXIT_MKSQUASHFS() exit(1) #define BAD_ERROR(s, args...) {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry { char *filename; long long size; ino_t st_ino; dev_t st_dev; struct priority_entry *next; }; struct priority_entry *priority_list[65536]; struct sorted_inode_entry { squashfs_inode inode; ino_t st_ino; dev_t st_dev; struct sorted_inode_entry *next; }; struct sorted_inode_entry *sorted_inode_list[65536]; extern int silent; extern int excluded(char *filename, struct stat *buf); extern squashfs_inode write_file(char *filename, long long size, int *c_size); int add_to_sorted_inode_list(squashfs_inode inode, dev_t st_dev, ino_t st_ino) { int hash = st_ino & 0xffff; struct sorted_inode_entry *new_sorted_inode_entry; if((new_sorted_inode_entry = malloc(sizeof(struct sorted_inode_entry))) == NULL) { ERROR("Out of memory allocating sorted inode entry\n"); return FALSE; } new_sorted_inode_entry->inode = inode; new_sorted_inode_entry->st_ino = st_ino; new_sorted_inode_entry->st_dev = st_dev; new_sorted_inode_entry->next = sorted_inode_list[hash]; sorted_inode_list[hash] = new_sorted_inode_entry; return TRUE; } squashfs_inode get_sorted_inode(struct stat *buf) { int hash = buf->st_ino & 0xffff; struct sorted_inode_entry *sorted_inode_entry; for(sorted_inode_entry = sorted_inode_list[hash]; sorted_inode_entry; sorted_inode_entry = sorted_inode_entry->next) if(buf->st_ino == sorted_inode_entry->st_ino && buf->st_dev == sorted_inode_entry->st_dev) break; if(sorted_inode_entry) return sorted_inode_entry->inode; else return (squashfs_inode) 0; } int add_priority_list(char *filename, struct stat *buf, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->filename = strdup(filename); new_priority_entry->size = buf->st_size; new_priority_entry->st_dev = buf->st_dev; new_priority_entry->st_ino = buf->st_ino; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i; char buffer[4096], filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", path); perror(buffer); return TRUE; } TRACE("adding filename %s, priority %d, st_dev %Lx, st_ino %Lx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat sort_list dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf, priority); } return TRUE; } void generate_file_priorities(char *pathname, int priority, struct stat *buf) { char filename[8192]; DIR *linuxdir; struct dirent *d_name; priority = get_priority(pathname, buf, priority); if((linuxdir = opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); return; } while((d_name = readdir(linuxdir)) != NULL) { if(strcmp(d_name->d_name, ".") == 0 || strcmp(d_name->d_name, "..") == 0) continue; strcat(strcat(strcpy(filename, pathname), "/"), d_name->d_name); if(lstat(filename, buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, buf)) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(filename, buf, get_priority(filename, buf, priority)); break; case S_IFDIR: generate_file_priorities(filename, priority, buf); break; } } closedir(linuxdir); } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(int source, char *source_path[]) { struct stat buf; int i, c_size; struct priority_entry *entry; squashfs_inode inode; for(i = 0; i < source; i++) { if(lstat(source_path[i], &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", source_path[i]); perror(buffer); continue; } if(excluded(source_path[i], &buf)) continue; switch(buf.st_mode & S_IFMT) { case S_IFREG: add_priority_list(source_path[i], &buf, get_priority(source_path[i], &buf, 0)); break; case S_IFDIR: generate_file_priorities(source_path[i], 0, &buf); break; } } for(i = 0; i < 65536; i++) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->filename); inode = write_file(entry->filename, entry->size, &c_size); INFO("file %s, size %d bytes, inode 0x%Lx\n", entry->filename, c_size, inode); INFO("\t%.2f%% of uncompressed file size (%Ld bytes)\n", ((float) c_size / entry->size) * 100.0, entry->size); add_to_sorted_inode_list(inode, entry->st_dev, entry->st_ino); } } ================================================ FILE: src/squashfs-2.1-r2/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_MAJOR 2 #define SQUASHFS_MINOR 1 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_BLK ((long long) 0xffffffff) #define SQUASHFS_USED_BLK ((long long) 0xfffffffe) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking) (noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an uncompressed * offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A) << 16)\ + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + ((b) >> 2) + 1)) /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ typedef unsigned int squashfs_fragment_index; #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index)) #define SQUASHFS_CACHED_FRAGMENTS 3 /* from squashfs 3.0 */ #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 32 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1)) #define SQUASHFS_MARKER_BYTE 0xff /* * definitions for structures on disk */ typedef unsigned int squashfs_block; typedef long long squashfs_inode; typedef unsigned int squashfs_uid; typedef struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used; unsigned int uid_start; unsigned int guid_start; unsigned int inode_table_start; unsigned int directory_table_start; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start; } __attribute__ ((packed)) squashfs_super_block; typedef struct { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)) squashfs_dir_index; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)) squashfs_base_inode_header; typedef squashfs_base_inode_header squashfs_ipc_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)) squashfs_dev_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)) squashfs_symlink_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; squashfs_block start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; unsigned short block_list[0]; } __attribute__ ((packed)) squashfs_reg_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_inode_header; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; squashfs_dir_index index[0]; } __attribute__ ((packed)) squashfs_ldir_inode_header; typedef union { squashfs_base_inode_header base; squashfs_dev_inode_header dev; squashfs_symlink_inode_header symlink; squashfs_reg_inode_header reg; squashfs_dir_inode_header dir; squashfs_ldir_inode_header ldir; squashfs_ipc_inode_header ipc; } squashfs_inode_header; typedef struct { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)) squashfs_dir_entry; typedef struct { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_header; typedef struct { unsigned int start_block; unsigned int size; } __attribute__ ((packed)) squashfs_fragment_entry; extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem on a * machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\ } #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header)) #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) #ifdef SQUASHFS_1_0_COMPATIBILITY typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)) squashfs_base_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)) squashfs_ipc_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)) squashfs_dev_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)) squashfs_symlink_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; squashfs_block start_block; unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG; unsigned short block_list[0]; } __attribute__ ((packed)) squashfs_reg_inode_header_1; typedef struct { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)) squashfs_dir_inode_header_1; #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4);\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/squashfs-2.1-r2/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 08/11/06: this copy modified to handle DD-WRT images with changed * superblock signature. * * unsquash.c */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" /*#include "global.h"*/ #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE; char **created_inode; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(set_mode && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } return TRUE; } void read_uids_guids(squashfs_super_block *sBlk) { if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk->no_uids; if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table(squashfs_super_block *sBlk) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { long long start = sBlk->inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); /* if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } */ switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } /* case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } */ case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(geteuid() == 0) { if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, 0/*inodep->mtime todo: fix proper*/, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, 0 /* header.base.mtime todo */, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } /*created_inode[header.base.inode_number - 1] = strdup(pathname);*/ return TRUE; } void uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk->inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk->directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { struct dir *dir = squashfs_openddir(start_block, offset, sBlk); unsigned int type; char *name, pathname[1024]; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, sBlk); else if(!lsonly) create_inode(pathname, start_block, offset, sBlk); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(squashfs_super_block *sBlk, char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk->s_major, sBlk->s_minor); ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source); #else TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk->block_size); TRACE("\tNumber of fragments %d\n", sBlk->fragments); TRACE("\tNumber of inodes %d\n", sBlk->inodes); TRACE("\tNumber of uids %d\n", sBlk->no_uids); TRACE("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start); TRACE("\n"); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.0 for suqashfs 2.x images \n");\ printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { squashfs_super_block sBlk; char *dest = "squashfs-root"; int i, version = FALSE; int retval = EXIT_FAILURE; for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0) { if(++i == argc) goto options; dest = argv[i]; } } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [-ls | -dest] filesystem\n", argv[0]); ERROR("\t-version\t\tprint version, licence and copyright information\n"); ERROR("\t-info\t\t\tprint files as they are unsquashed\n"); ERROR("\t-ls\t\t\tlist filesystem only\n"); ERROR("\t-dest <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); } exit(1); } if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(&sBlk, argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(&sBlk); read_fragment_table(&sBlk); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } if(file_count > 0) { retval = EXIT_SUCCESS; } return retval; } ================================================ FILE: src/squashfs-3.0/Makefile ================================================ CC := gcc CXX := g++ INCLUDEDIR = . CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -O2 LZMAPATH = ../lzma/C/7zip/Compress/LZMA_Lib all: unsquashfs mksquashfs unsquashfs-lzma mksquashfs-lzma mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@ mksquashfs-lzma: mksquashfs.o read_fs.o sort.o make -C $(LZMAPATH) $(CXX) -O3 mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -llzma -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs-lzma: unsquashfs.o make -C $(LZMAPATH) $(CXX) -O3 unsquashfs.o -L$(LZMAPATH) -llzma -o $@ unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h clean: rm -f *.o rm -f mksquashfs rm -f unsquashfs rm -f mksquashfs-lzma rm -f unsquashfs-lzma rm -f mksquashfs.exe rm -f unsquashfs.exe rm -f mksquashfs-lzma.exe rm -f unsquashfs-lzma.exe make -C $(LZMAPATH) clean ================================================ FILE: src/squashfs-3.0/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/squashfs-3.0/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk>no * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.c */ /* jc: This build tweaked to add -magic [file] parameter to fix brainslayer's mod of 08/10/06 firmware squashfs image signature change. */ #define FALSE 0 #define TRUE 1 #include <pwd.h> #include <grp.h> #include <time.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <zlib.h> #include <stdlib.h> #include <signal.h> #include <setjmp.h> #include <sys/mman.h> /* jc */ //#define SQUASHFS_TRACE #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN /* jc debugging */ #warning "mksquashfs: (jc) building on non-linux system." #else #include <endian.h> #endif #include <squashfs_fs.h> #include "mksquashfs.h" #include "global.h" #include "sort.h" /*********************************************************/ /* jc */ u_int32_t g_nMagic=SQUASHFS_MAGIC; // always flip, regardless of endianness of machine u_int32_t flip_endian(u_int32_t nValue) { // my crappy endian switch u_int32_t nR; u_int32_t nByte1=(nValue&0xff000000)>>24; u_int32_t nByte2=(nValue&0x00ff0000)>>16; u_int32_t nByte3=(nValue&0x0000ff00)>>8; u_int32_t nByte4=nValue&0x0ff; nR=nByte4<<24; nR|=(nByte3<<16); nR|=(nByte2<<8); nR|=nByte1; return nR; } /*********************************************************/ #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536], *frag_dups[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; char fragment_data[SQUASHFS_FILE_SIZE]; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long bytes; unsigned short checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; unsigned short fragment_checksum; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* structure to used to pass in a pointer or an integer * to duplicate buffer read helper functions. */ struct duplicate_buffer_handle { char *ptr; long long start; }; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table); int get_sorted_inode(squashfs_inode *inode, struct stat *buf); int read_sort_file(char *filename, int source, char *source_path[]); void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) void restorefs() { ERROR("Exiting - restoring original filesystem!\n\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(interrupted == 1) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); interrupted ++; } } void sighandler2() { EXIT_MKSQUASHFS(); } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte = block_size << 1; unsigned int res; if(!uncompressed && (res = compress2((unsigned char *) d, &c_byte, (unsigned char *) s, size, 9)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); return 0; } if(uncompressed || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment) { squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index]; int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); return buffer + fragment->offset; } void write_fragment() { int compressed_size; char buffer[block_size << 1]; if(fragment_size == 0) return; if(fragments % FRAG_SIZE == 0) if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) BAD_ERROR("Out of memory in fragment table\n"); fragment_table[fragments].size = mangle(buffer, fragment_data, fragment_size, block_size, noF, 1); fragment_table[fragments].start_block = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[fragments].size); write_bytes(fd, bytes, compressed_size, buffer); bytes += compressed_size; total_uncompressed += fragment_size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n",fragments, fragment_size, compressed_size); fragments ++; fragment_size = 0; } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(char *buff, int size) { struct fragment *ffrg; if(size == 0) return &empty_fragment; if(fragment_size + size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = size; memcpy(fragment_data + fragment_size, buff, size); fragment_size += size; return ffrg; } long long write_fragment_table() { long long start_bytes; unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments), meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; unsigned short c_byte; int i, compressed_size; squashfs_fragment_index list[meta_blocks]; TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } for(i = 0; i < meta_blocks; i++) { int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { squashfs_fragment_index slist[meta_blocks]; SQUASHFS_SWAP_FRAGMENT_INDEXES(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); return start_bytes; } char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { char *v = handle->ptr; handle->ptr += avail_bytes; return v; } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer); handle->start += avail_bytes; return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, long long l) { unsigned short chksum = 0; unsigned int bytes = 0; unsigned char *b; struct duplicate_buffer_handle position = *handle; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; b = (unsigned char *) get_next_file_block(&position, bytes); while(bytes--) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } } return chksum; } int cached_frag = -1; void add_file(long long start, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; struct file_info *dupl_ptr; char *datap; struct duplicate_buffer_handle handle; unsigned int *block_list = block_listp; if(!duplicate_checking) return; if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; if(fragment == cached_frag || fragment == SQUASHFS_INVALID_FRAG) datap = fragment_data + offset; else datap = get_fragment(fragment_data, frg); handle.start = start; if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL) dupl_ptr->fragment = frg; else free(block_list); cached_frag = fragment; } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes) { unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes); struct duplicate_buffer_handle handle = { frag_data, 0 }; unsigned short fragment_checksum = get_checksum(read_from_buffer, &handle, frag_bytes); struct file_info *dupl_ptr = bytes ? dupl[checksum] : frag_dups[fragment_checksum]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) { char buffer1[SQUASHFS_FILE_MAX_SIZE]; long long dup_bytes = dupl_ptr->bytes; long long dup_start = dupl_ptr->start; struct duplicate_buffer_handle position = *file_start; char *buffer; while(dup_bytes) { int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes; buffer = get_next_file_block(&position, avail_bytes); read_bytes(fd, dup_start, avail_bytes, buffer1); if(memcmp(buffer, buffer1, avail_bytes) != 0) break; dup_bytes -= avail_bytes; dup_start += avail_bytes; } if(dup_bytes == 0) { char *fragment_buffer1; if(dupl_ptr->fragment->index == fragments || dupl_ptr->fragment->index == SQUASHFS_INVALID_FRAG) fragment_buffer1 = fragment_data + dupl_ptr->fragment->offset; else if(dupl_ptr->fragment->index == cached_frag1) fragment_buffer1 = cached_fragment + dupl_ptr->fragment->offset; else { fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment); cached_frag1 = dupl_ptr->fragment->index; } if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->bytes = bytes; dupl_ptr->checksum = checksum; dupl_ptr->start = *start; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->block_list = *block_list; dup_files ++; if(bytes) { dupl_ptr->next = dupl[checksum]; dupl[checksum] = dupl_ptr; } else { dupl_ptr->next = frag_dups[fragment_checksum]; frag_dups[fragment_checksum] = dupl_ptr; } return dupl_ptr; } #define MINALLOCBYTES (1024 * 1024) int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { int block = 0, i, file, whole_file = 1, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes = 0, start; char buff[block_size], *c_buffer = NULL, *filename = dir_ent->pathname; struct fragment *fragment; struct file_info *dupl_ptr = NULL; struct duplicate_buffer_handle handle; long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; int blocks = (read_size + block_size - 1) >> block_log, allocated_blocks = blocks; unsigned int *block_list, *block_listp; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if(!no_fragments && (read_size < block_size || always_use_fragments)) { allocated_blocks = blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE); total_bytes += read_size; if((file = open(filename, O_RDONLY)) == -1) goto read_err; do { long long bytes = (((long long) allocated_blocks) + 1) << block_log; if(bytes != ((size_t) bytes) || (c_buffer = (char *) malloc(bytes)) == NULL) { TRACE("Out of memory allocating write_file buffer, allocated_blocks %ld, blocks %d\n", allocated_blocks, blocks); whole_file = 0; if(bytes < MINALLOCBYTES) BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %ld blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10)); allocated_blocks >>= 1; } } while(!c_buffer); for(start = bytes; block < blocks; file_bytes += bbytes) { for(i = 0, bbytes = 0; (i < allocated_blocks) && (block < blocks); i++) { int available_bytes = read_size - (block * block_size) > block_size ? block_size : read_size - (block * block_size); if(read(file, buff, available_bytes) == -1) goto read_err; c_byte = mangle(c_buffer + bbytes, buff, available_bytes, block_size, noD, 1); block_list[block ++] = c_byte; bbytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); } if(!whole_file) { write_bytes(fd, bytes, bbytes, c_buffer); bytes += bbytes; } } if(frag_bytes != 0) if(read(file, buff, frag_bytes) == -1) goto read_err; close(file); if(whole_file) { handle.ptr = c_buffer; if(duplicate_checking && (dupl_ptr = duplicate(read_from_buffer, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { *duplicate_file = TRUE; goto wr_inode; } write_bytes(fd, bytes, file_bytes, c_buffer); bytes += file_bytes; } else { handle.start = start; if(duplicate_checking && (dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { bytes = start; if(!block_device) ftruncate(fd, bytes); *duplicate_file = TRUE; goto wr_inode; } } fragment = get_and_fill_fragment(buff, frag_bytes); if(duplicate_checking) dupl_ptr->fragment = fragment; *duplicate_file = FALSE; wr_inode: free(c_buffer); file_count ++; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(duplicate_checking == FALSE || *duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); free(c_buffer); free(block_list); return FALSE; } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; struct inode_info *inode_info; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if((inode_info = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->inode = inode_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; inode_info->nlink = 1; inode_info->inode_number = root_inode_number ? root_inode_number : dir_inode_no++; dir_info->dir_ent = dir_ent; if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ inode_info->buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO; inode_info->buf.st_uid = getuid(); inode_info->buf.st_gid = getgid(); inode_info->buf.st_mtime = time(NULL); } else if(lstat(pathname, &inode_info->buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; caseSQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 16; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } #define VERSION() \ printf("mksquashfs version 3.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } /* jc: new -magic param */ else if(strcmp(argv[i], "-magic") == 0) { if(++i == argc) { ERROR("%s: -magic missing signature file\n", argv[0]); exit(1); } TRACE(" debug.mksquashfs-magic: reading %s\n", argv[i]); FILE *fMagic=fopen(argv[i],"rb"); if(!fMagic) { ERROR("cannot open %s\n", argv[i]); fclose(fMagic); exit(1); } if(fread(&g_nMagic,1,sizeof(u_int32_t),fMagic)!=sizeof(u_int32_t)) { ERROR("cannot read %s\n", argv[i]); fclose(fMagic); exit(1); } fclose(fMagic); /* lame fix for big endiannes problem with new signatures */ /* am I sure this isn't actually a problem with dd-wrt kernel */ /* changes were he didn't also update the _ALT endian-flipped */ /* version of the signature? doesn't matter, I fix it here. */ #if __BYTE_ORDER == __BIG_ENDIAN TRACE(" debug.mksquashfs-magic: flipping endian\n"); g_nMagic=flip_endian(g_nMagic); #endif TRACE(" debug.mksquashfs-magic: signature is 0x%x\n", g_nMagic); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-b <block_size>\t\tset data block to <block_size>. Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes <name>\twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled <name>, rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort <sort_file>\tsort files according to priorities in <sort_file>. One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef <exclude_file>\tlist of exclude dirs/files. One per line\n"); exit(1); } } for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -2.0 options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = g_nMagic; //jc TRACE(" stored superblock signature of 0x%x\n", sBlk.s_magic); //sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); TRACE("sBlk->inode_table_start 0x%x\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%x\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%x\n", sBlk.fragment_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; sBlk.unused = SQUASHFS_INVALID_BLK; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/squashfs-3.0/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.demon.co.uK> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/squashfs-3.0/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i, start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i, start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid SQUASHFS superblock on %s.\n", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/squashfs-3.0/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/squashfs-3.0/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #include <squashfs_fs.h> #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; generate_file_priorities(dir, 0, &dir->dir_ent->inode->buf); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/squashfs-3.0/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; struct inode_info *next; }; #endif ================================================ FILE: src/squashfs-3.0/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x73717368 #define SQUASHFS_MAGIC_SWAP 0x68737173 // jc: for dd-wrt build as of 09/10/06 #define SQUASHFS_MAGIC_ALT 0x74717368 #define SQUASHFS_MAGIC_ALT_SWAP 0x68737174 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) #define SQUASHFS_CACHED_FRAGMENTS 3 /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long unused; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->unused, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include <asm/byteorder.h> #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/squashfs-3.0/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 08/11/06: this copy modified to handle DD-WRT images with changed * superblock signature. * * unsquash.c */ #define TRUE 1 #define FALSE 0 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <zlib.h> #include <sys/mman.h> #include <utime.h> #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include <endian.h> #endif #include <squashfs_fs.h> #include "read_fs.h" #include "global.h" #include <stdlib.h> #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE; char **created_inode; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else { ERROR("zlib::uncompress failed, unknown error %d\n", res); exit(1); } goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else { ERROR("zlib::uncompress failed, unknown error %d\n", res); exit(1); } return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(set_mode && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } return TRUE; } void read_uids_guids(squashfs_super_block *sBlk) { if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk->no_uids; if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table(squashfs_super_block *sBlk) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { long long start = sBlk->inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(geteuid() == 0) { if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0) { EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); exit(1); } bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk->inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk->directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { struct dir *dir = squashfs_openddir(start_block, offset, sBlk); unsigned int type; char *name, pathname[1024]; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, sBlk); else if(!lsonly) create_inode(pathname, start_block, offset, sBlk); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(squashfs_super_block *sBlk, char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC && sBlk->s_magic != SQUASHFS_MAGIC_ALT) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP || sBlk->s_magic == SQUASHFS_MAGIC_ALT_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk->s_major, sBlk->s_minor); ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source); #else TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk->block_size); TRACE("\tNumber of fragments %d\n", sBlk->fragments); TRACE("\tNumber of inodes %d\n", sBlk->inodes); TRACE("\tNumber of uids %d\n", sBlk->no_uids); TRACE("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start); TRACE("\n"); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher <phillip@lougher.org.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { squashfs_super_block sBlk; char *dest = "squashfs-root"; int i, version = FALSE; for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0) { if(++i == argc) goto options; dest = argv[i]; } } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [-ls | -dest] filesystem\n", argv[0]); ERROR("\t-version\t\tprint version, licence and copyright information\n"); ERROR("\t-info\t\t\tprint files as they are unsquashed\n"); ERROR("\t-ls\t\t\tlist filesystem only\n"); ERROR("\t-dest <pathname>\tunsquash to <pathname>, default \"squashfs-root\"\n"); } exit(1); } if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(&sBlk, argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(&sBlk); read_fragment_table(&sBlk); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/Makefile ================================================ INCLUDEDIR = . LZMAPATH = ./lzma/C/7zip/Compress/LZMA_Lib CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -funroll-loops -mtune=opteron -march=opteron -mfpmath=sse -m3dnow -msse2 -O3 -D_LZMA_PARAMS all: mksquashfs-lzma unsquashfs-lzma mksquashfs: mksquashfs.o read_fs.o sort.o $(CC) mksquashfs.o read_fs.o sort.o -lz -o $@ mksquashfs-lzma: mksquashfs.o read_fs.o sort.o make -C $(LZMAPATH) $(CXX) mksquashfs.o read_fs.o sort.o -L$(LZMAPATH) -llzma -lpthread -o $@ mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h sort.o: sort.c squashfs_fs.h global.h sort.h unsquashfs: unsquashfs.o $(CC) unsquashfs.o -lz -o $@ unsquashfs-lzma: unsquashfs.o $(CXX) $(CFLAGS) unsquashfs.o -L$(LZMAPATH) -llzma -lpthread -o $@ unsquashfs.o: unsquashfs.c squashfs_fs.h read_fs.h global.h clean: make -C $(LZMAPATH) clean rm -f *.o rm -f mksquashfs-lzma rm -f unsquashfs-lzma ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/global.h ================================================ #ifndef GLOBAL_H #define GLOBAL_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher <phillip@lougher.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * global.h */ typedef struct squashfs_super_block squashfs_super_block; typedef struct squashfs_dir_index squashfs_dir_index; typedef struct squashfs_base_inode_header squashfs_base_inode_header; typedef struct squashfs_ipc_inode_header squashfs_ipc_inode_header; typedef struct squashfs_dev_inode_header squashfs_dev_inode_header; typedef struct squashfs_symlink_inode_header squashfs_symlink_inode_header; typedef struct squashfs_reg_inode_header squashfs_reg_inode_header; typedef struct squashfs_lreg_inode_header squashfs_lreg_inode_header; typedef struct squashfs_dir_inode_header squashfs_dir_inode_header; typedef struct squashfs_ldir_inode_header squashfs_ldir_inode_header; typedef struct squashfs_dir_entry squashfs_dir_entry; typedef struct squashfs_dir_header squashfs_dir_header; typedef struct squashfs_fragment_entry squashfs_fragment_entry; typedef union squashfs_inode_header squashfs_inode_header; typedef unsigned int squashfs_uid; typedef long long squashfs_fragment_index; typedef squashfs_inode_t squashfs_inode; typedef squashfs_block_t squashfs_block; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/.built ================================================ ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/.unpacked ================================================ ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/7zC.txt ================================================ 7z ANSI-C Decoder 4.23 ---------------------- 7z ANSI-C Decoder 4.23 Copyright (C) 1999-2005 Igor Pavlov 7z ANSI-C provides 7z/LZMA decoding. 7z ANSI-C version is simplified version ported from C++ code. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LICENSE ------- Read lzma.txt for information about license. Files --------------------- 7zAlloc.* - Allocate and Free 7zBuffer.* - Buffer structure 7zCrc.* - CRC32 code 7zDecode.* - Low level memory->memory decoding 7zExtract.* - High level stream->memory decoding 7zHeader.* - .7z format constants 7zIn.* - .7z archive opening 7zItem.* - .7z structures 7zMain.c - Test application 7zMethodID.* - MethodID structure 7zTypes.h - Base types and constants How To Use ---------- You must download 7-Zip program from www.7-zip.org. You can create .7z archive with 7z.exe or 7za.exe: 7za.exe a archive.7z *.htm -r -mx -m0fb=255 If you have big number of files in archive, and you need fast extracting, you can use partly-solid archives: 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only 512KB for extracting one file from such archive. Limitations of current version of 7z ANSI-C Decoder --------------------------------------------------- - It reads only "FileName", "Size", and "CRC" information for each file in archive. - It supports only LZMA and Copy (no compression) methods. - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. These limitations will be fixed in future versions. Using 7z ANSI-C Decoder Test application: ----------------------------------------- Usage: 7zDec <command> <archive_name> <Command>: e: Extract files from archive l: List contents of archive t: Test integrity of archive Example: 7zDec l archive.7z lists contents of archive.7z 7zDec e archive.7z extracts files from archive.7z to current folder. How to use .7z Decoder ---------------------- .7z Decoder can be compiled in one of two modes: 1) Default mode. In that mode 7z Decoder will read full compressed block to RAM before decompressing. 2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read compressed block by parts. And you can specify desired buffer size. So memory requirements can be reduced. But decompressing speed will be 5-10% lower and code size is slightly larger. Memory allocation ~~~~~~~~~~~~~~~~~ 7z Decoder uses two memory pools: 1) Temporary pool 2) Main pool Such scheme can allow you to avoid fragmentation of allocated blocks. Steps for using 7z decoder -------------------------- Use code at 7zMain.c as example. 1) Declare variables: inStream /* implements ISzInStream interface */ CArchiveDatabaseEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ 2) call InitCrcTable(); function to initialize CRC structures. 3) call SzArDbExInit(&db); function to initialize db structures. 4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive This function opens archive "inStream" and reads headers to "db". All items in "db" will be allocated with "allocMain" functions. SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions. 5) List items or Extract items Listing code: ~~~~~~~~~~~~~ { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } Extracting code: ~~~~~~~~~~~~~~~~ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); If you need to decompress more than one file, you can send these values from previous call: blockIndex, outBuffer, outBufferSize, You can consider "outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. After decompressing you must free "outBuffer": allocImp.Free(outBuffer); 6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db". Memory requirements for .7z decoding ------------------------------------ Memory usage for Archive opening: - Temporary pool: - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined) - Memory for uncompressed .7z headers - some other temporary blocks - Main pool: - Memory for database: Estimated size of one file structures in solid archive: - Size (4 or 8 Bytes) - CRC32 (4 bytes) - Some file information (4 bytes) - File Name (variable length) + pointer + allocation structures Memory usage for archive Decompressing: - Temporary pool: - Memory for compressed solid block (if _LZMA_IN_CB is not defined) - Memory for LZMA decompressing structures - Main pool: - Memory for decompressed solid block If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for compressed blocks. Instead of this, you must allocate buffer with desired size before calling 7z Decoder. Use 7zMain.c as example. EXIT codes ----------- 7z Decoder functions can return one of the following codes: #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) LZMA Defines ------------ _LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements _SZ_FILE_SIZE_64 - define it if you need support for files larger than 4 GB _SZ_NO_INT_64 - define it if your compiler doesn't support long long int _LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs. _SZ_ONE_DIRECTORY - define it if you want to locate all source files to one directory _SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/7zFormat.txt ================================================ 7z Format description (2.30 Beta 25) ----------------------------------- This file contains description of 7z archive format. 7z archive can contain files compressed with any method. See "Methods.txt" for description for defined compressing methods. Format structure Overview ------------------------- Some fields can be optional. Archive structure ~~~~~~~~~~~~~~~~~ SignatureHeader [PackedStreams] [PackedStreamsForHeaders] [ Header or { Packed Header HeaderInfo } ] Header structure ~~~~~~~~~~~~~~~~ { ArchiveProperties AdditionalStreams { PackInfo { PackPos NumPackStreams Sizes[NumPackStreams] CRCs[NumPackStreams] } CodersInfo { NumFolders Folders[NumFolders] { NumCoders CodersInfo[NumCoders] { ID NumInStreams; NumOutStreams; PropertiesSize Properties[PropertiesSize] } NumBindPairs BindPairsInfo[NumBindPairs] { InIndex; OutIndex; } PackedIndices } UnPackSize[Folders][Folders.NumOutstreams] CRCs[NumFolders] } SubStreamsInfo { NumUnPackStreamsInFolders[NumFolders]; UnPackSizes[] CRCs[] } } MainStreamsInfo { (Same as in AdditionalStreams) } FilesInfo { NumFiles Properties[] { ID Size Data } } } HeaderInfo structure ~~~~~~~~~~~~~~~~~~~~ { (Same as in AdditionalStreams) } Notes about Notation and encoding --------------------------------- 7z uses little endian encoding. 7z archive format has optional headers that are marked as [] Header [] REAL_UINT64 means real UINT64. UINT64 means real UINT64 encoded with the following scheme: Size of encoding sequence depends from first byte: First_Byte Extra_Bytes Value (binary) 0xxxxxxx : ( xxxxxxx ) 10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y 110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y ... 1111110x BYTE y[6] : ( x << (8 * 6)) + y 11111110 BYTE y[7] : y 11111111 BYTE y[8] : y Property IDs ------------ 0x00 = kEnd, 0x01 = kHeader, 0x02 = kArchiveProperties, 0x03 = kAdditionalStreamsInfo, 0x04 = kMainStreamsInfo, 0x05 = kFilesInfo, 0x06 = kPackInfo, 0x07 = kUnPackInfo, 0x08 = kSubStreamsInfo, 0x09 = kSize, 0x0A = kCRC, 0x0B = kFolder, 0x0C = kCodersUnPackSize, 0x0D = kNumUnPackStream, 0x0E = kEmptyStream, 0x0F = kEmptyFile, 0x10 = kAnti, 0x11 = kName, 0x12 = kCreationTime, 0x13 = kLastAccessTime, 0x14 = kLastWriteTime, 0x15 = kWinAttributes, 0x16 = kComment, 0x17 = kEncodedHeader, 7z format headers ----------------- SignatureHeader ~~~~~~~~~~~~~~~ BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ArchiveVersion { BYTE Major; // now = 0 BYTE Minor; // now = 2 }; UINT32 StartHeaderCRC; StartHeader { REAL_UINT64 NextHeaderOffset REAL_UINT64 NextHeaderSize UINT32 NextHeaderCRC } ........................... ArchiveProperties ~~~~~~~~~~~~~~~~~ BYTE NID::kArchiveProperties (0x02) while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 PropertySize; BYTE PropertyData[PropertySize]; } Digests (NumStreams) ~~~~~~~~~~~~~~~~~~~~~ BYTE AllAreDefined if (AllAreDefined == 0) { for(NumStreams) BIT Defined } UINT32 CRCs[NumDefined] PackInfo ~~~~~~~~~~~~ BYTE NID::kPackInfo (0x06) UINT64 PackPos UINT64 NumPackStreams [] BYTE NID::kSize (0x09) UINT64 PackSizes[NumPackStreams] [] [] BYTE NID::kCRC (0x0A) PackStreamDigests[NumPackStreams] [] BYTE NID::kEnd Folder ~~~~~~ UINT64 NumCoders; for (NumCoders) { BYTE { 0:3 DecompressionMethod.IDSize 4: 0 - IsSimple 1 - Is not simple 5: 0 - No Attributes 1 - There Are Attributes 7: 0 - Last Method in Alternative_Method_List 1 - There are more alternative methods } BYTE DecompressionMethod.ID[DecompressionMethod.IDSize] if (!IsSimple) { UINT64 NumInStreams; UINT64 NumOutStreams; } if (DecompressionMethod[0] != 0) { UINT64 PropertiesSize BYTE Properties[PropertiesSize] } } NumBindPairs = NumOutStreamsTotal - 1; for (NumBindPairs) { UINT64 InIndex; UINT64 OutIndex; } NumPackedStreams = NumInStreamsTotal - NumBindPairs; if (NumPackedStreams > 1) for(NumPackedStreams) { UINT64 Index; }; Coders Info ~~~~~~~~~~~ BYTE NID::kUnPackInfo (0x07) BYTE NID::kFolder (0x0B) UINT64 NumFolders BYTE External switch(External) { case 0: Folders[NumFolders] case 1: UINT64 DataStreamIndex } BYTE ID::kCodersUnPackSize (0x0C) for(Folders) for(Folder.NumOutStreams) UINT64 UnPackSize; [] BYTE NID::kCRC (0x0A) UnPackDigests[NumFolders] [] BYTE NID::kEnd SubStreams Info ~~~~~~~~~~~~~~ BYTE NID::kSubStreamsInfo; (0x08) [] BYTE NID::kNumUnPackStream; (0x0D) UINT64 NumUnPackStreamsInFolders[NumFolders]; [] [] BYTE NID::kSize (0x09) UINT64 UnPackSizes[] [] [] BYTE NID::kCRC (0x0A) Digests[Number of streams with unknown CRC] [] BYTE NID::kEnd Streams Info ~~~~~~~~~~~~ [] PackInfo [] [] CodersInfo [] [] SubStreamsInfo [] BYTE NID::kEnd FilesInfo ~~~~~~~~~ BYTE NID::kFilesInfo; (0x05) UINT64 NumFiles while(true) { BYTE PropertyType; if (aType == 0) break; UINT64 Size; switch(PropertyType) { kEmptyStream: (0x0E) for(NumFiles) BIT IsEmptyStream kEmptyFile: (0x0F) for(EmptyStreams) BIT IsEmptyFile kAnti: (0x10) for(EmptyStreams) BIT IsAntiFile case kCreationTime: (0x12) case kLastAccessTime: (0x13) case kLastWriteTime: (0x14) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT TimeDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Items) UINT32 Time [] kNames: (0x11) BYTE External; if(External != 0) UINT64 DataIndex [] for(Files) { wchar_t Names[NameSize]; wchar_t 0; } [] kAttributes: (0x15) BYTE AllAreDefined if (AllAreDefined == 0) { for(NumFiles) BIT AttributesAreDefined } BYTE External; if(External != 0) UINT64 DataIndex [] for(Definded Attributes) UINT32 Attributes [] } } Header ~~~~~~ BYTE NID::kHeader (0x01) [] ArchiveProperties [] [] BYTE NID::kAdditionalStreamsInfo; (0x03) StreamsInfo [] [] BYTE NID::kMainStreamsInfo; (0x04) StreamsInfo [] [] FilesInfo [] BYTE NID::kEnd HeaderInfo ~~~~~~~~~~ [] BYTE NID::kEncodedHeader; (0x17) StreamsInfo for Encoded Header [] --- End of document ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zAlloc.c ================================================ /* 7zAlloc.c */ #include <stdlib.h> #include "7zAlloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #ifdef _WIN32 #include <windows.h> #endif #include <stdio.h> int g_allocCount = 0; int g_allocCountTemp = 0; #endif void *SzAlloc(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); g_allocCount++; #endif return malloc(size); } void SzFree(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCount--; fprintf(stderr, "\nFree; count = %10d", g_allocCount); } #endif free(address); } void *SzAllocTemp(size_t size) { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); g_allocCountTemp++; #ifdef _WIN32 return HeapAlloc(GetProcessHeap(), 0, size); #endif #endif return malloc(size); } void SzFreeTemp(void *address) { #ifdef _SZ_ALLOC_DEBUG if (address != 0) { g_allocCountTemp--; fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); } #ifdef _WIN32 HeapFree(GetProcessHeap(), 0, address); return; #endif #endif free(address); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zAlloc.h ================================================ /* 7zAlloc.h */ #ifndef __7Z_ALLOC_H #define __7Z_ALLOC_H #include <stddef.h> typedef struct _ISzAlloc { void *(*Alloc)(size_t size); void (*Free)(void *address); /* address can be 0 */ } ISzAlloc; void *SzAlloc(size_t size); void SzFree(void *address); void *SzAllocTemp(size_t size); void SzFreeTemp(void *address); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zBuffer.c ================================================ /* 7zBuffer.c */ #include "7zBuffer.h" #include "7zAlloc.h" void SzByteBufferInit(CSzByteBuffer *buffer) { buffer->Capacity = 0; buffer->Items = 0; } int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) { buffer->Capacity = newCapacity; if (newCapacity == 0) { buffer->Items = 0; return 1; } buffer->Items = (Byte *)allocFunc(newCapacity); return (buffer->Items != 0); } void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) { freeFunc(buffer->Items); buffer->Items = 0; buffer->Capacity = 0; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zBuffer.h ================================================ /* 7zBuffer.h */ #ifndef __7Z_BUFFER_H #define __7Z_BUFFER_H #include <stddef.h> #include "7zTypes.h" typedef struct _CSzByteBuffer { size_t Capacity; Byte *Items; }CSzByteBuffer; void SzByteBufferInit(CSzByteBuffer *buffer); int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zCrc.c ================================================ /* 7zCrc.c */ #include "7zCrc.h" #define kCrcPoly 0xEDB88320 UInt32 g_CrcTable[256]; void InitCrcTable() { UInt32 i; for (i = 0; i < 256; i++) { UInt32 r = i; int j; for (j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCrcPoly; else r >>= 1; g_CrcTable[i] = r; } } void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } void CrcUpdateByte(UInt32 *crc, Byte b) { *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); } void CrcUpdateUInt16(UInt32 *crc, UInt16 v) { CrcUpdateByte(crc, (Byte)v); CrcUpdateByte(crc, (Byte)(v >> 8)); } void CrcUpdateUInt32(UInt32 *crc, UInt32 v) { int i; for (i = 0; i < 4; i++) CrcUpdateByte(crc, (Byte)(v >> (8 * i))); } void CrcUpdateUInt64(UInt32 *crc, UInt64 v) { int i; for (i = 0; i < 8; i++) { CrcUpdateByte(crc, (Byte)(v)); v >>= 8; } } void CrcUpdate(UInt32 *crc, const void *data, size_t size) { UInt32 v = *crc; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); *crc = v; } UInt32 CrcCalculateDigest(const void *data, size_t size) { UInt32 crc; CrcInit(&crc); CrcUpdate(&crc, data, size); return CrcGetDigest(&crc); } int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) { return (CrcCalculateDigest(data, size) == digest); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zCrc.h ================================================ /* 7zCrc.h */ #ifndef __7Z_CRC_H #define __7Z_CRC_H #include <stddef.h> #include "7zTypes.h" extern UInt32 g_CrcTable[256]; void InitCrcTable(); void CrcInit(UInt32 *crc); UInt32 CrcGetDigest(UInt32 *crc); void CrcUpdateByte(UInt32 *crc, Byte v); void CrcUpdateUInt16(UInt32 *crc, UInt16 v); void CrcUpdateUInt32(UInt32 *crc, UInt32 v); void CrcUpdateUInt64(UInt32 *crc, UInt64 v); void CrcUpdate(UInt32 *crc, const void *data, size_t size); UInt32 CrcCalculateDigest(const void *data, size_t size); int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zDecode.c ================================================ /* 7zDecode.c */ #include "7zDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #else #include "../../Compress/LZMA_C/LzmaDecode.h" #endif CMethodID k_Copy = { { 0x0 }, 1 }; CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; #ifdef _LZMA_IN_CB typedef struct _CLzmaInCallbackImp { ILzmaInCallback InCallback; ISzInStream *InStream; size_t Size; } CLzmaInCallbackImp; int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) { CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; size_t processedSize; SZ_RESULT res; *size = 0; res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); *size = (SizeT)processedSize; if (processedSize > cb->Size) return (int)SZE_FAIL; cb->Size -= processedSize; if (res == SZ_OK) return 0; return (int)res; } #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *inStream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; size_t inSize = 0; CCoderInfo *coder; if (folder->NumPackStreams != 1) return SZE_NOTIMPL; if (folder->NumCoders != 1) return SZE_NOTIMPL; coder = folder->Coders; *outSizeProcessed = 0; for (si = 0; si < folder->NumPackStreams; si++) inSize += (size_t)packSizes[si]; if (AreMethodsEqual(&coder->MethodID, &k_Copy)) { size_t i; if (inSize != outSize) return SZE_DATA_ERROR; #ifdef _LZMA_IN_CB for (i = 0; i < inSize;) { size_t j; Byte *inBuffer; size_t bufferSize; RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); if (bufferSize == 0) return SZE_DATA_ERROR; if (bufferSize > inSize - i) return SZE_FAIL; *outSizeProcessed += bufferSize; for (j = 0; j < bufferSize && i < inSize; j++, i++) outBuffer[i] = inBuffer[j]; } #else for (i = 0; i < inSize; i++) outBuffer[i] = inBuffer[i]; *outSizeProcessed = inSize; #endif return SZ_OK; } if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) { #ifdef _LZMA_IN_CB CLzmaInCallbackImp lzmaCallback; #else SizeT inProcessed; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; #ifdef _LZMA_IN_CB lzmaCallback.Size = inSize; lzmaCallback.InStream = inStream; lzmaCallback.InCallback.Read = LzmaReadImp; #endif if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { allocMain->Free(state.Probs); return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); #endif result = LzmaDecode(&state, #ifdef _LZMA_IN_CB &lzmaCallback.InCallback, #else inBuffer, (SizeT)inSize, &inProcessed, #endif outBuffer, (SizeT)outSize, &outSizeProcessedLoc); *outSizeProcessed = (size_t)outSizeProcessedLoc; allocMain->Free(state.Probs); #ifdef _LZMA_OUT_READ allocMain->Free(state.Dictionary); #endif if (result == LZMA_RESULT_DATA_ERROR) return SZE_DATA_ERROR; if (result != LZMA_RESULT_OK) return SZE_FAIL; return SZ_OK; } return SZE_NOTIMPL; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zDecode.h ================================================ /* 7zDecode.h */ #ifndef __7Z_DECODE_H #define __7Z_DECODE_H #include "7zItem.h" #include "7zAlloc.h" #ifdef _LZMA_IN_CB #include "7zIn.h" #endif SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #ifdef _LZMA_IN_CB ISzInStream *stream, #else const Byte *inBuffer, #endif Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zExtract.c ================================================ /* 7zExtract.c */ #include "7zExtract.h" #include "7zDecode.h" #include "7zCrc.h" SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; SZ_RESULT res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { allocMain->Free(*outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CFolder *folder = db->Database.Folders + folderIndex; CFileSize unPackSize = SzFolderGetUnPackSize(folder); #ifndef _LZMA_IN_CB CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); Byte *inBuffer = 0; size_t processedSize; #endif *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); #ifndef _LZMA_IN_CB if (packSize != 0) { inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); if (inBuffer == 0) return SZE_OUTOFMEMORY; } res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); if (res == SZ_OK && processedSize != (size_t)packSize) res = SZE_FAIL; #endif if (res == SZ_OK) { *outBufferSize = (size_t)unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); if (*outBuffer == 0) res = SZE_OUTOFMEMORY; } if (res == SZ_OK) { size_t outRealSize; res = SzDecode(db->Database.PackSizes + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) { if (outRealSize == (size_t)unPackSize) { if (folder->UnPackCRCDefined) { if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) res = SZE_FAIL; } } else res = SZE_FAIL; } } } #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif } if (res == SZ_OK) { UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZE_FAIL; { if (fileItem->IsFileCRCDefined) { if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) res = SZE_FAIL; } } } return res; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zExtract.h ================================================ /* 7zExtract.h */ #ifndef __7Z_EXTRACT_H #define __7Z_EXTRACT_H #include "7zIn.h" /* SzExtract extracts file from archive *outBuffer must be 0 before first call for each new archive. Extracting cache: If you need to decompress more than one file, you can send these values from previous call: *blockIndex, *outBuffer, *outBufferSize You can consider "*outBuffer" as cache of solid block. If your archive is solid, it will increase decompression speed. If you use external function, you can declare these 3 cache variables (blockIndex, outBuffer, outBufferSize) as static in that external function. Free *outBuffer and set *outBuffer to 0, if you want to flush cache. */ SZ_RESULT SzExtract( ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, /* index of file */ UInt32 *blockIndex, /* index of solid block */ Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ size_t *outBufferSize, /* buffer size for output buffer */ size_t *offset, /* offset of stream for required file in *outBuffer */ size_t *outSizeProcessed, /* size of file in *outBuffer */ ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zHeader.c ================================================ /* 7zHeader.c */ #include "7zHeader.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zHeader.h ================================================ /* 7zHeader.h */ #ifndef __7Z_HEADER_H #define __7Z_HEADER_H #include "7zTypes.h" #define k7zSignatureSize 6 extern Byte k7zSignature[k7zSignatureSize]; #define k7zMajorVersion 0 #define k7zStartHeaderSize 0x20 enum EIdEnum { k7zIdEnd, k7zIdHeader, k7zIdArchiveProperties, k7zIdAdditionalStreamsInfo, k7zIdMainStreamsInfo, k7zIdFilesInfo, k7zIdPackInfo, k7zIdUnPackInfo, k7zIdSubStreamsInfo, k7zIdSize, k7zIdCRC, k7zIdFolder, k7zIdCodersUnPackSize, k7zIdNumUnPackStream, k7zIdEmptyStream, k7zIdEmptyFile, k7zIdAnti, k7zIdName, k7zIdCreationTime, k7zIdLastAccessTime, k7zIdLastWriteTime, k7zIdWinAttributes, k7zIdComment, k7zIdEncodedHeader, k7zIdStartPos }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zIn.c ================================================ /* 7zIn.c */ #include "7zIn.h" #include "7zCrc.h" #include "7zDecode.h" #define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } void SzArDbExInit(CArchiveDatabaseEx *db) { SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0; } void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) { freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db); } /* CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; } CFileSize GetFilePackSize(int fileIndex) const { int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0; } */ SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size)) { if (size == 0) *p = 0; else { *p = allocFunc(size); RINOM(*p); } return SZ_OK; } SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) { UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc)); RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc)); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ while(1) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK; } CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) { return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; } CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) { UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) size += db->Database.PackSizes[packStreamIndex + i]; return size; } /* SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt64 type) { CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK; } */ SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) { #ifdef _LZMA_IN_CB while (size > 0) { Byte *inBuffer; size_t processedSize; RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK; } SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) { return SafeReadDirect(inStream, data, 1); } SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) { int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK; } int TestSignatureCandidate(Byte *testBytes) { size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1; } typedef struct _CSzState { Byte *Data; size_t Size; }CSzData; SZ_RESULT SzReadByte(CSzData *sd, Byte *b) { if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK; } SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) { size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK; } SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) { int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK; } SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) { Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK; } SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) { UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK; } SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); } SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) { if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK; } SZ_RESULT SzSkeepData(CSzData *sd) { UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size); } SZ_RESULT SzReadArchiveProperties(CSzData *sd) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK; } SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte b = 0; Byte mask = 0; size_t i; RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK; } SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) { Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc)); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK; } SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)) { size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc)); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK; } SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined, UInt32 **packCRCs, void * (*allocFunc)(size_t size)) { UInt32 i; RINOK(SzReadSize(sd, dataOffset)); RINOK(SzReadNumber32(sd, numPackStreams)); RINOK(SzWaitAttribute(sd, k7zIdSize)); RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc)); for(i = 0; i < *numPackStreams; i++) { RINOK(SzReadSize(sd, (*packSizes) + i)); } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; if (type == k7zIdCRC) { RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); continue; } RINOK(SzSkeepData(sd)); } if (*packCRCsDefined == 0) { RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc)); RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc)); for(i = 0; i < *numPackStreams; i++) { (*packCRCsDefined)[i] = 0; (*packCRCs)[i] = 0; } } return SZ_OK; } SZ_RESULT SzReadSwitch(CSzData *sd) { Byte external; RINOK(SzReadByte(sd, &external)); return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; } SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) { UInt32 numCoders; UInt32 numBindPairs; UInt32 numPackedStreams; UInt32 i; UInt32 numInStreams = 0; UInt32 numOutStreams = 0; RINOK(SzReadNumber32(sd, &numCoders)); folder->NumCoders = numCoders; RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc)); for (i = 0; i < numCoders; i++) SzCoderInfoInit(folder->Coders + i); for (i = 0; i < numCoders; i++) { Byte mainByte; CCoderInfo *coder = folder->Coders + i; { RINOK(SzReadByte(sd, &mainByte)); coder->MethodID.IDSize = (Byte)(mainByte & 0xF); RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); if ((mainByte & 0x10) != 0) { RINOK(SzReadNumber32(sd, &coder->NumInStreams)); RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); } else { coder->NumInStreams = 1; coder->NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) return SZE_OUTOFMEMORY; RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); } } while ((mainByte & 0x80) != 0) { RINOK(SzReadByte(sd, &mainByte)); RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); if ((mainByte & 0x10) != 0) { UInt32 n; RINOK(SzReadNumber32(sd, &n)); RINOK(SzReadNumber32(sd, &n)); } if ((mainByte & 0x20) != 0) { UInt64 propertiesSize = 0; RINOK(SzReadNumber(sd, &propertiesSize)); RINOK(SzSkeepDataSize(sd, propertiesSize)); } } numInStreams += (UInt32)coder->NumInStreams; numOutStreams += (UInt32)coder->NumOutStreams; } numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs; RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc)); for (i = 0; i < numBindPairs; i++) { CBindPair *bindPair = folder->BindPairs + i;; RINOK(SzReadNumber32(sd, &bindPair->InIndex)); RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); } numPackedStreams = numInStreams - (UInt32)numBindPairs; folder->NumPackStreams = numPackedStreams; RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc)); if (numPackedStreams == 1) { UInt32 j; UInt32 pi = 0; for (j = 0; j < numInStreams; j++) if (SzFolderFindBindPairForInStream(folder, j) < 0) { folder->PackStreams[pi++] = j; break; } } else for(i = 0; i < numPackedStreams; i++) { RINOK(SzReadNumber32(sd, folder->PackStreams + i)); } return SZ_OK; } SZ_RESULT SzReadUnPackInfo( CSzData *sd, UInt32 *numFolders, CFolder **folders, /* for allocFunc */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { UInt32 i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc)); for(i = 0; i < *numFolders; i++) SzFolderInit((*folders) + i); for(i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); for(i = 0; i < *numFolders; i++) { UInt32 j; CFolder *folder = (*folders) + i; UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc)); for(j = 0; j < numOutStreams; j++) { RINOK(SzReadSize(sd, folder->UnPackSizes + j)); } } while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SZ_RESULT res; Byte *crcsDefined = 0; UInt32 *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); if (res == SZ_OK) { for(i = 0; i < *numFolders; i++) { CFolder *folder = (*folders) + i; folder->UnPackCRCDefined = crcsDefined[i]; folder->UnPackCRC = crcs[i]; } } allocTemp->Free(crcs); allocTemp->Free(crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } } SZ_RESULT SzReadSubStreamsInfo( CSzData *sd, UInt32 numFolders, CFolder *folders, UInt32 *numUnPackStreams, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, ISzAlloc *allocTemp) { UInt64 type = 0; UInt32 i; UInt32 si = 0; UInt32 numDigests = 0; for(i = 0; i < numFolders; i++) folders[i].NumUnPackStreams = 1; *numUnPackStreams = numFolders; while(1) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnPackStream) { *numUnPackStreams = 0; for(i = 0; i < numFolders; i++) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnPackStreams = numStreams; *numUnPackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnPackStreams == 0) { *unPackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); RINOM(*unPackSizes); *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); RINOM(*digestsDefined); *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); RINOM(*digests); } for(i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ CFileSize sum = 0; UInt32 j; UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { CFileSize size; RINOK(SzReadSize(sd, &size)); (*unPackSizes)[si++] = size; sum += size; } (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for(i = 0; i < *numUnPackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for(i = 0; i < numFolders; i++) { UInt32 numSubstreams = folders[i].NumUnPackStreams; if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) numDigests += numSubstreams; } si = 0; while(1) { if (type == k7zIdCRC) { int digestIndex = 0; Byte *digestsDefined2 = 0; UInt32 *digests2 = 0; SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CFolder *folder = folders + i; UInt32 numSubstreams = folder->NumUnPackStreams; if (numSubstreams == 1 && folder->UnPackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnPackCRC; si++; } else { UInt32 j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } allocTemp->Free(digestsDefined2); allocTemp->Free(digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } } SZ_RESULT SzReadStreamsInfo( CSzData *sd, CFileSize *dataOffset, CArchiveDatabase *db, UInt32 *numUnPackStreams, CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ void * (*allocFunc)(size_t size), ISzAlloc *allocTemp) { while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if ((UInt64)(int)type != type) return SZE_FAIL; switch((int)type) { case k7zIdEnd: return SZ_OK; case k7zIdPackInfo: { RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); break; } case k7zIdUnPackInfo: { RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); break; } case k7zIdSubStreamsInfo: { RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); break; } default: return SZE_FAIL; } } } Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, void * (*allocFunc)(size_t size)) { UInt32 i; for(i = 0; i < numFiles; i++) { UInt32 len = 0; UInt32 pos = 0; CFileItem *file = files + i; while(pos + 2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { UInt32 c2; if (value >= 0xDC00) return SZE_ARCHIVE_ERROR; if (pos + 2 > sd->Size) return SZE_ARCHIVE_ERROR; c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) return SZE_ARCHIVE_ERROR; value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; len += numAdds; } RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc)); len = 0; while(2 <= sd->Size) { int numAdds; UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); if (value < 0x80) { file->Name[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); SzSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((UInt32)1) << (numAdds * 5 + 6))) break; file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while(numAdds > 0); len += numAdds; } } return SZ_OK; } SZ_RESULT SzReadHeader2( CSzData *sd, CArchiveDatabaseEx *db, /* allocMain */ CFileSize **unPackSizes, /* allocTemp */ Byte **digestsDefined, /* allocTemp */ UInt32 **digests, /* allocTemp */ Byte **emptyStreamVector, /* allocTemp */ Byte **emptyFileVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt64 type; UInt32 numUnPackStreams = 0; UInt32 numFiles = 0; CFileItem *files = 0; UInt32 numEmptyStreams = 0; UInt32 i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &db->ArchiveInfo.DataStartPosition, &db->Database, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocMain->Alloc, allocTemp)); db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZE_ARCHIVE_ERROR; RINOK(SzReadNumber32(sd, &numFiles)); db->Database.NumFiles = numFiles; RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc)); db->Database.Files = files; for(i = 0; i < numFiles; i++) SzFileInit(files + i); while(1) { UInt64 type; UInt64 size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if ((UInt64)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { RINOK(SzReadSwitch(sd)); RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { UInt32 emptyFileIndex = 0; UInt32 sizeIndex = 0; for(i = 0; i < numFiles; i++) { CFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); if(file->HasStream) { file->IsDirectory = 0; file->Size = (*unPackSizes)[sizeIndex]; file->FileCRC = (*digests)[sizeIndex]; file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDirectory = 1; else file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->IsFileCRCDefined = 0; } } } return SzArDbExFill(db, allocMain->Alloc); } SZ_RESULT SzReadHeader( CSzData *sd, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; Byte *emptyStreamVector = 0; Byte *emptyFileVector = 0; SZ_RESULT res = SzReadHeader2(sd, db, &unPackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, allocMain, allocTemp); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); allocTemp->Free(emptyStreamVector); allocTemp->Free(emptyFileVector); return res; } SZ_RESULT SzReadAndDecodePackedStreams2( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, CArchiveDatabase *db, CFileSize **unPackSizes, Byte **digestsDefined, UInt32 **digests, #ifndef _LZMA_IN_CB Byte **inBuffer, #endif ISzAlloc *allocTemp) { UInt32 numUnPackStreams = 0; CFileSize dataStartPos; CFolder *folder; #ifndef _LZMA_IN_CB CFileSize packSize = 0; UInt32 i = 0; #endif CFileSize unPackSize; size_t outRealSize; SZ_RESULT res; RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, &numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp->Alloc, allocTemp)); dataStartPos += baseOffset; if (db->NumFolders != 1) return SZE_ARCHIVE_ERROR; folder = db->Folders; unPackSize = SzFolderGetUnPackSize(folder); RINOK(inStream->Seek(inStream, dataStartPos)); #ifndef _LZMA_IN_CB for (i = 0; i < db->NumPackStreams; i++) packSize += db->PackSizes[i]; RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc)); RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); #endif if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SzDecode(db->PackSizes, folder, #ifdef _LZMA_IN_CB inStream, #else *inBuffer, #endif outBuffer->Items, (size_t)unPackSize, &outRealSize, allocTemp); RINOK(res) if (outRealSize != (UInt32)unPackSize) return SZE_FAIL; if (folder->UnPackCRCDefined) if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) return SZE_FAIL; return SZ_OK; } SZ_RESULT SzReadAndDecodePackedStreams( ISzInStream *inStream, CSzData *sd, CSzByteBuffer *outBuffer, CFileSize baseOffset, ISzAlloc *allocTemp) { CArchiveDatabase db; CFileSize *unPackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; #ifndef _LZMA_IN_CB Byte *inBuffer = 0; #endif SZ_RESULT res; SzArchiveDatabaseInit(&db); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &db, &unPackSizes, &digestsDefined, &digests, #ifndef _LZMA_IN_CB &inBuffer, #endif allocTemp); SzArchiveDatabaseFree(&db, allocTemp->Free); allocTemp->Free(unPackSizes); allocTemp->Free(digestsDefined); allocTemp->Free(digests); #ifndef _LZMA_IN_CB allocTemp->Free(inBuffer); #endif return res; } SZ_RESULT SzArchiveOpen2( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte signature[k7zSignatureSize]; Byte version; UInt32 crcFromArchive; UInt64 nextHeaderOffset; UInt64 nextHeaderSize; UInt32 nextHeaderCRC; UInt32 crc; CFileSize pos = 0; CSzByteBuffer buffer; CSzData sd; SZ_RESULT res; RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); if (!TestSignatureCandidate(signature)) return SZE_ARCHIVE_ERROR; /* db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; */ RINOK(SafeReadDirectByte(inStream, &version)); if (version != k7zMajorVersion) return SZE_ARCHIVE_ERROR; RINOK(SafeReadDirectByte(inStream, &version)); RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); CrcInit(&crc); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); CrcUpdateUInt64(&crc, nextHeaderOffset); RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); CrcUpdateUInt64(&crc, nextHeaderSize); RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); CrcUpdateUInt32(&crc, nextHeaderCRC); pos = k7zStartHeaderSize; db->ArchiveInfo.StartPositionAfterHeader = pos; if (CrcGetDigest(&crc) != crcFromArchive) return SZE_ARCHIVE_ERROR; if (nextHeaderSize == 0) return SZ_OK; RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) return SZE_OUTOFMEMORY; res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); if (res == SZ_OK) { if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) { while (1) { UInt64 type; sd.Data = buffer.Items; sd.Size = buffer.Capacity; res = SzReadID(&sd, &type); if (res != SZ_OK) break; if (type == k7zIdHeader) { res = SzReadHeader(&sd, db, allocMain, allocTemp); break; } if (type != k7zIdEncodedHeader) { res = SZE_ARCHIVE_ERROR; break; } { CSzByteBuffer outBuffer; res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, db->ArchiveInfo.StartPositionAfterHeader, allocTemp); if (res != SZ_OK) { SzByteBufferFree(&outBuffer, allocTemp->Free); break; } SzByteBufferFree(&buffer, allocTemp->Free); buffer.Items = outBuffer.Items; buffer.Capacity = outBuffer.Capacity; } } } } SzByteBufferFree(&buffer, allocTemp->Free); return res; } SZ_RESULT SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp) { SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); if (res != SZ_OK) SzArDbExFree(db, allocMain->Free); return res; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zIn.h ================================================ /* 7zIn.h */ #ifndef __7Z_IN_H #define __7Z_IN_H #include "7zHeader.h" #include "7zItem.h" #include "7zAlloc.h" typedef struct _CInArchiveInfo { CFileSize StartPositionAfterHeader; CFileSize DataStartPosition; }CInArchiveInfo; typedef struct _CArchiveDatabaseEx { CArchiveDatabase Database; CInArchiveInfo ArchiveInfo; UInt32 *FolderStartPackStreamIndex; CFileSize *PackStreamStartPositions; UInt32 *FolderStartFileIndex; UInt32 *FileIndexToFolderIndexMap; }CArchiveDatabaseEx; void SzArDbExInit(CArchiveDatabaseEx *db); void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); typedef struct _ISzInStream { #ifdef _LZMA_IN_CB SZ_RESULT (*Read)( void *object, /* pointer to ISzInStream itself */ void **buffer, /* out: pointer to buffer with data */ size_t maxRequiredSize, /* max required size to read */ size_t *processedSize); /* real processed size. processedSize can be less than maxRequiredSize. If processedSize == 0, then there are no more bytes in stream. */ #else SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); #endif SZ_RESULT (*Seek)(void *object, CFileSize pos); } ISzInStream; int SzArchiveOpen( ISzInStream *inStream, CArchiveDatabaseEx *db, ISzAlloc *allocMain, ISzAlloc *allocTemp); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zItem.c ================================================ /* 7zItem.c */ #include "7zItem.h" #include "7zAlloc.h" void SzCoderInfoInit(CCoderInfo *coder) { SzByteBufferInit(&coder->Properties); } void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) { SzByteBufferFree(&coder->Properties, freeFunc); SzCoderInfoInit(coder); } void SzFolderInit(CFolder *folder) { folder->NumCoders = 0; folder->Coders = 0; folder->NumBindPairs = 0; folder->BindPairs = 0; folder->NumPackStreams = 0; folder->PackStreams = 0; folder->UnPackSizes = 0; folder->UnPackCRCDefined = 0; folder->UnPackCRC = 0; folder->NumUnPackStreams = 0; } void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) { UInt32 i; for (i = 0; i < folder->NumCoders; i++) SzCoderInfoFree(&folder->Coders[i], freeFunc); freeFunc(folder->Coders); freeFunc(folder->BindPairs); freeFunc(folder->PackStreams); freeFunc(folder->UnPackSizes); SzFolderInit(folder); } UInt32 SzFolderGetNumOutStreams(CFolder *folder) { UInt32 result = 0; UInt32 i; for (i = 0; i < folder->NumCoders; i++) result += folder->Coders[i].NumOutStreams; return result; } int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].InIndex == inStreamIndex) return i; return -1; } int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) { UInt32 i; for(i = 0; i < folder->NumBindPairs; i++) if (folder->BindPairs[i].OutIndex == outStreamIndex) return i; return -1; } CFileSize SzFolderGetUnPackSize(CFolder *folder) { int i = (int)SzFolderGetNumOutStreams(folder); if (i == 0) return 0; for (i--; i >= 0; i--) if (SzFolderFindBindPairForOutStream(folder, i) < 0) return folder->UnPackSizes[i]; /* throw 1; */ return 0; } /* int FindPackStreamArrayIndex(int inStreamIndex) const { for(int i = 0; i < PackStreams.Size(); i++) if (PackStreams[i] == inStreamIndex) return i; return -1; } */ void SzFileInit(CFileItem *fileItem) { fileItem->IsFileCRCDefined = 0; fileItem->HasStream = 1; fileItem->IsDirectory = 0; fileItem->IsAnti = 0; fileItem->Name = 0; } void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) { freeFunc(fileItem->Name); SzFileInit(fileItem); } void SzArchiveDatabaseInit(CArchiveDatabase *db) { db->NumPackStreams = 0; db->PackSizes = 0; db->PackCRCsDefined = 0; db->PackCRCs = 0; db->NumFolders = 0; db->Folders = 0; db->NumFiles = 0; db->Files = 0; } void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) { UInt32 i; for (i = 0; i < db->NumFolders; i++) SzFolderFree(&db->Folders[i], freeFunc); for (i = 0; i < db->NumFiles; i++) SzFileFree(&db->Files[i], freeFunc); freeFunc(db->PackSizes); freeFunc(db->PackCRCsDefined); freeFunc(db->PackCRCs); freeFunc(db->Folders); freeFunc(db->Files); SzArchiveDatabaseInit(db); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zItem.h ================================================ /* 7zItem.h */ #ifndef __7Z_ITEM_H #define __7Z_ITEM_H #include "7zMethodID.h" #include "7zHeader.h" #include "7zBuffer.h" typedef struct _CCoderInfo { UInt32 NumInStreams; UInt32 NumOutStreams; CMethodID MethodID; CSzByteBuffer Properties; }CCoderInfo; void SzCoderInfoInit(CCoderInfo *coder); void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); typedef struct _CBindPair { UInt32 InIndex; UInt32 OutIndex; }CBindPair; typedef struct _CFolder { UInt32 NumCoders; CCoderInfo *Coders; UInt32 NumBindPairs; CBindPair *BindPairs; UInt32 NumPackStreams; UInt32 *PackStreams; CFileSize *UnPackSizes; int UnPackCRCDefined; UInt32 UnPackCRC; UInt32 NumUnPackStreams; }CFolder; void SzFolderInit(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); UInt32 SzFolderGetNumOutStreams(CFolder *folder); CFileSize SzFolderGetUnPackSize(CFolder *folder); /* #define CArchiveFileTime UInt64 */ typedef struct _CFileItem { /* CArchiveFileTime LastWriteTime; CFileSize StartPos; UInt32 Attributes; */ CFileSize Size; UInt32 FileCRC; char *Name; Byte IsFileCRCDefined; Byte HasStream; Byte IsDirectory; Byte IsAnti; /* int AreAttributesDefined; int IsLastWriteTimeDefined; int IsStartPosDefined; */ }CFileItem; void SzFileInit(CFileItem *fileItem); typedef struct _CArchiveDatabase { UInt32 NumPackStreams; CFileSize *PackSizes; Byte *PackCRCsDefined; UInt32 *PackCRCs; UInt32 NumFolders; CFolder *Folders; UInt32 NumFiles; CFileItem *Files; }CArchiveDatabase; void SzArchiveDatabaseInit(CArchiveDatabase *db); void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zMain.c ================================================ /* 7zMain.c Test application for 7z Decoder LZMA SDK 4.26 Copyright (c) 1999-2005 Igor Pavlov (2005-08-02) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "7zCrc.h" #include "7zIn.h" #include "7zExtract.h" typedef struct _CFileInStream { ISzInStream InStream; FILE *File; } CFileInStream; #ifdef _LZMA_IN_CB #define kBufferSize (1 << 12) Byte g_Buffer[kBufferSize]; SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc; if (maxRequiredSize > kBufferSize) maxRequiredSize = kBufferSize; processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File); *buffer = g_Buffer; if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #else SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) { CFileInStream *s = (CFileInStream *)object; size_t processedSizeLoc = fread(buffer, 1, size, s->File); if (processedSize != 0) *processedSize = processedSizeLoc; return SZ_OK; } #endif SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) { CFileInStream *s = (CFileInStream *)object; int res = fseek(s->File, (long)pos, SEEK_SET); if (res == 0) return SZ_OK; return SZE_FAIL; } void PrintError(char *sz) { printf("\nERROR: %s\n", sz); } int main(int numargs, char *args[]) { CFileInStream archiveStream; CArchiveDatabaseEx db; SZ_RESULT res; ISzAlloc allocImp; ISzAlloc allocTempImp; printf("\n7z ANSI-C Decoder 4.30 Copyright (c) 1999-2005 Igor Pavlov 2005-11-20\n"); if (numargs == 1) { printf( "\nUsage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive\n" " l: List contents of archive\n" " t: Test integrity of archive\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } archiveStream.File = fopen(args[2], "rb"); if (archiveStream.File == 0) { PrintError("can not open input file"); return 1; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; InitCrcTable(); SzArDbExInit(&db); res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0; int testCommand = 0; int extractCommand = 0; if (strcmp(command, "l") == 0) listCommand = 1; if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) extractCommand = 1; if (listCommand) { UInt32 i; for (i = 0; i < db.Database.NumFiles; i++) { CFileItem *f = db.Database.Files + i; printf("%10d %s\n", (int)f->Size, f->Name); } } else if (testCommand || extractCommand) { UInt32 i; // if you need cache, use these 3 variables. // if you use external function, you can make these variable as static. UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0) Byte *outBuffer = 0; // it must be 0 before first call for each new archive. size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0) printf("\n"); for (i = 0; i < db.Database.NumFiles; i++) { size_t offset; size_t outSizeProcessed; CFileItem *f = db.Database.Files + i; if (f->IsDirectory) printf("Directory "); else printf(testCommand ? "Testing ": "Extracting"); printf(" %s", f->Name); if (f->IsDirectory) { printf("\n"); continue; } res = SzExtract(&archiveStream.InStream, &db, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; if (!testCommand) { FILE *outputHandle; UInt32 processedSize; char *fileName = f->Name; size_t nameLen = strlen(f->Name); for (; nameLen > 0; nameLen--) if (f->Name[nameLen - 1] == '/') { fileName = f->Name + nameLen; break; } outputHandle = fopen(fileName, "wb+"); if (outputHandle == 0) { PrintError("can not open output file"); res = SZE_FAIL; break; } processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); if (processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZE_FAIL; break; } if (fclose(outputHandle)) { PrintError("can not close output file"); res = SZE_FAIL; break; } } printf("\n"); } allocImp.Free(outBuffer); } else { PrintError("incorrect command"); res = SZE_FAIL; } } SzArDbExFree(&db, allocImp.Free); fclose(archiveStream.File); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZE_OUTOFMEMORY) PrintError("can not allocate memory"); else printf("\nERROR #%d\n", res); return 1; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zMethodID.c ================================================ /* 7zMethodID.c */ #include "7zMethodID.h" int AreMethodsEqual(CMethodID *a1, CMethodID *a2) { int i; if (a1->IDSize != a2->IDSize) return 0; for (i = 0; i < a1->IDSize; i++) if (a1->ID[i] != a2->ID[i]) return 0; return 1; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zMethodID.h ================================================ /* 7zMethodID.h */ #ifndef __7Z_METHOD_ID_H #define __7Z_METHOD_ID_H #include "7zTypes.h" #define kMethodIDSize 15 typedef struct _CMethodID { Byte ID[kMethodIDSize]; Byte IDSize; } CMethodID; int AreMethodsEqual(CMethodID *a1, CMethodID *a2); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7zTypes.h ================================================ /* 7zTypes.h */ #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H #ifndef UInt32 #ifdef _LZMA_UINT32_IS_ULONG #define UInt32 unsigned long #else #define UInt32 unsigned int #endif #endif #ifndef Byte #define Byte unsigned char #endif #ifndef UInt16 #define UInt16 unsigned short #endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ #ifdef _SZ_NO_INT_64 #define UInt64 unsigned long #else #ifdef _MSC_VER #define UInt64 unsigned __int64 #else #define UInt64 unsigned long long int #endif #endif /* #define _SZ_FILE_SIZE_64 */ /* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ #ifndef CFileSize #ifdef _SZ_FILE_SIZE_64 #define CFileSize UInt64 #else #define CFileSize UInt32 #endif #endif #define SZ_RESULT int #define SZ_OK (0) #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) #define SZE_CRC_ERROR (3) #define SZE_NOTIMPL (4) #define SZE_FAIL (5) #define SZE_ARCHIVE_ERROR (6) #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7z_C.dsp ================================================ # Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=7z_C - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "7z_C.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "7z_C - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" !ELSEIF "$(CFG)" == "7z_C - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept !ENDIF # Begin Target # Name "7z_C - Win32 Release" # Name "7z_C - Win32 Debug" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c # End Source File # Begin Source File SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h # End Source File # End Group # Begin Source File SOURCE=.\7zAlloc.c # End Source File # Begin Source File SOURCE=.\7zAlloc.h # End Source File # Begin Source File SOURCE=.\7zBuffer.c # End Source File # Begin Source File SOURCE=.\7zBuffer.h # End Source File # Begin Source File SOURCE=.\7zCrc.c # End Source File # Begin Source File SOURCE=.\7zCrc.h # End Source File # Begin Source File SOURCE=.\7zDecode.c # End Source File # Begin Source File SOURCE=.\7zDecode.h # End Source File # Begin Source File SOURCE=.\7zExtract.c # End Source File # Begin Source File SOURCE=.\7zExtract.h # End Source File # Begin Source File SOURCE=.\7zHeader.c # End Source File # Begin Source File SOURCE=.\7zHeader.h # End Source File # Begin Source File SOURCE=.\7zIn.c # End Source File # Begin Source File SOURCE=.\7zIn.h # End Source File # Begin Source File SOURCE=.\7zItem.c # End Source File # Begin Source File SOURCE=.\7zItem.h # End Source File # Begin Source File SOURCE=.\7zMain.c # End Source File # Begin Source File SOURCE=.\7zMethodID.c # End Source File # Begin Source File SOURCE=.\7zMethodID.h # End Source File # Begin Source File SOURCE=.\7zTypes.h # End Source File # End Target # End Project ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/7z_C.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/makefile ================================================ PROG = 7zDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** 7Z_OBJS = \ $O\7zAlloc.obj \ $O\7zBuffer.obj \ $O\7zCrc.obj \ $O\7zDecode.obj \ $O\7zExtract.obj \ $O\7zHeader.obj \ $O\7zIn.obj \ $O\7zItem.obj \ $O\7zMain.obj \ $O\7zMethodID.obj \ OBJS = \ $(7Z_OBJS) \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(7Z_OBJS): $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Archive/7z_C/makefile.gcc ================================================ PROG = 7zDec CXX = g++ LIB = RM = rm -f CFLAGS = -c -O2 -Wall OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) 7zAlloc.o: 7zAlloc.c $(CXX) $(CFLAGS) 7zAlloc.c 7zBuffer.o: 7zBuffer.c $(CXX) $(CFLAGS) 7zBuffer.c 7zCrc.o: 7zCrc.c $(CXX) $(CFLAGS) 7zCrc.c 7zDecode.o: 7zDecode.c $(CXX) $(CFLAGS) 7zDecode.c 7zExtract.o: 7zExtract.c $(CXX) $(CFLAGS) 7zExtract.c 7zHeader.o: 7zHeader.c $(CXX) $(CFLAGS) 7zHeader.c 7zIn.o: 7zIn.c $(CXX) $(CFLAGS) 7zIn.c 7zItem.o: 7zItem.c $(CXX) $(CFLAGS) 7zItem.c 7zMain.o: 7zMain.c $(CXX) $(CFLAGS) 7zMain.c 7zMethodID.o: 7zMethodID.c $(CXX) $(CFLAGS) 7zMethodID.c LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/FileStreams.cpp ================================================ // FileStreams.cpp #include "StdAfx.h" #ifndef _WIN32 #include <fcntl.h> #include <unistd.h> #include <errno.h> #endif #include "FileStreams.h" static inline HRESULT ConvertBoolToHRESULT(bool result) { // return result ? S_OK: E_FAIL; #ifdef _WIN32 return result ? S_OK: (::GetLastError()); #else return result ? S_OK: E_FAIL; #endif } bool CInFileStream::Open(LPCTSTR fileName) { return File.Open(fileName); } #ifdef _WIN32 #ifndef _UNICODE bool CInFileStream::Open(LPCWSTR fileName) { return File.Open(fileName); } #endif #endif STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Read(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, size, (DWORD *)&realProcessedSize, NULL); if(processedSize != NULL) *processedSize = realProcessedSize; if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) return S_OK; return ConvertBoolToHRESULT(res != FALSE); #else if(processedSize != NULL) *processedSize = 0; ssize_t res; do { res = read(0, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } #endif STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP CInFileStream::GetSize(UInt64 *size) { return ConvertBoolToHRESULT(File.GetLength(*size)); } ////////////////////////// // COutFileStream bool COutFileStream::Create(LPCTSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #ifdef _WIN32 #ifndef _UNICODE bool COutFileStream::Create(LPCWSTR fileName, bool createAlways) { return File.Create(fileName, createAlways); } #endif #endif STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { #ifdef _WIN32 UInt32 realProcessedSize; bool result = File.WritePart(data, size, realProcessedSize); if(processedSize != NULL) *processedSize = realProcessedSize; return ConvertBoolToHRESULT(result); #else if(processedSize != NULL) *processedSize = 0; ssize_t res = File.Write(data, (size_t)size); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; #endif } STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; #ifdef _WIN32 UInt64 realNewPosition; bool result = File.Seek(offset, seekOrigin, realNewPosition); if(newPosition != NULL) *newPosition = realNewPosition; return ConvertBoolToHRESULT(result); #else off_t res = File.Seek(offset, seekOrigin); if (res == -1) return E_FAIL; if(newPosition != NULL) *newPosition = (UInt64)res; return S_OK; #endif } STDMETHODIMP COutFileStream::SetSize(Int64 newSize) { #ifdef _WIN32 UInt64 currentPos; if(!File.Seek(0, FILE_CURRENT, currentPos)) return E_FAIL; bool result = File.SetLength(newSize); UInt64 currentPos2; result = result && File.Seek(currentPos, currentPos2); return result ? S_OK : E_FAIL; #else return E_FAIL; #endif } #ifndef _WIN32_WCE STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if(processedSize != NULL) *processedSize = 0; #ifdef _WIN32 UInt32 realProcessedSize; BOOL res = TRUE; if (size > 0) { // Seems that Windows doesn't like big amounts writing to stdout. // So we limit portions by 32KB. UInt32 sizeTemp = (1 << 15); if (sizeTemp > size) sizeTemp = size; res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), data, sizeTemp, (DWORD *)&realProcessedSize, NULL); size -= realProcessedSize; data = (const void *)((const Byte *)data + realProcessedSize); if(processedSize != NULL) *processedSize += realProcessedSize; } return ConvertBoolToHRESULT(res != FALSE); #else ssize_t res; do { res = write(1, data, (size_t)size); } while (res < 0 && (errno == EINTR)); if (res == -1) return E_FAIL; if(processedSize != NULL) *processedSize = (UInt32)res; return S_OK; return S_OK; #endif } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/FileStreams.h ================================================ // FileStreams.h #ifndef __FILESTREAMS_H #define __FILESTREAMS_H #ifdef _WIN32 #include "../../Windows/FileIO.h" #else #include "../../Common/C_FileIO.h" #endif #include "../IStream.h" #include "../../Common/MyCom.h" class CInFileStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::CInFile File; #else NC::NFile::NIO::CInFile File; #endif CInFileStream() {} virtual ~CInFileStream() {} bool Open(LPCTSTR fileName); #ifdef _WIN32 #ifndef _UNICODE bool Open(LPCWSTR fileName); #endif #endif MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); }; #ifndef _WIN32_WCE class CStdInFileStream: public ISequentialInStream, public CMyUnknownImp { public: // HANDLE File; // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; MY_UNKNOWN_IMP virtual ~CStdInFileStream() {} STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; #endif class COutFileStream: public IOutStream, public CMyUnknownImp { public: #ifdef _WIN32 NWindows::NFile::NIO::COutFile File; #else NC::NFile::NIO::COutFile File; #endif virtual ~COutFileStream() {} bool Create(LPCTSTR fileName, bool createAlways); #ifdef _WIN32 #ifndef _UNICODE bool Create(LPCWSTR fileName, bool createAlways); #endif #endif MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize); }; #ifndef _WIN32_WCE class CStdOutFileStream: public ISequentialOutStream, public CMyUnknownImp { public: MY_UNKNOWN_IMP virtual ~CStdOutFileStream() {} STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/InBuffer.cpp ================================================ // InBuffer.cpp #include "StdAfx.h" #include "InBuffer.h" #include "../../Common/Alloc.h" CInBuffer::CInBuffer(): _buffer(0), _bufferLimit(0), _bufferBase(0), _stream(0), _bufferSize(0) {} bool CInBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_bufferBase != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _bufferBase = (Byte *)::MidAlloc(bufferSize); return (_bufferBase != 0); } void CInBuffer::Free() { ::MidFree(_bufferBase); _bufferBase = 0; } void CInBuffer::SetStream(ISequentialInStream *stream) { _stream = stream; } void CInBuffer::Init() { _processedSize = 0; _buffer = _bufferBase; _bufferLimit = _buffer; _wasFinished = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } bool CInBuffer::ReadBlock() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return false; #endif if (_wasFinished) return false; _processedSize += (_buffer - _bufferBase); UInt32 numProcessedBytes; HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw CInBufferException(result); #endif _buffer = _bufferBase; _bufferLimit = _buffer + numProcessedBytes; _wasFinished = (numProcessedBytes == 0); return (!_wasFinished); } Byte CInBuffer::ReadBlock2() { if(!ReadBlock()) return 0xFF; return *_buffer++; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/InBuffer.h ================================================ // InBuffer.h #ifndef __INBUFFER_H #define __INBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS class CInBufferException { public: HRESULT ErrorCode; CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class CInBuffer { Byte *_buffer; Byte *_bufferLimit; Byte *_bufferBase; CMyComPtr<ISequentialInStream> _stream; UInt64 _processedSize; UInt32 _bufferSize; bool _wasFinished; bool ReadBlock(); Byte ReadBlock2(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif CInBuffer(); ~CInBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetStream(ISequentialInStream *stream); void Init(); void ReleaseStream() { _stream.Release(); } bool ReadByte(Byte &b) { if(_buffer >= _bufferLimit) if(!ReadBlock()) return false; b = *_buffer++; return true; } Byte ReadByte() { if(_buffer >= _bufferLimit) return ReadBlock2(); return *_buffer++; } void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) { for(processedSize = 0; processedSize < size; processedSize++) if (!ReadByte(((Byte *)data)[processedSize])) return; } bool ReadBytes(void *data, UInt32 size) { UInt32 processedSize; ReadBytes(data, size, processedSize); return (processedSize == size); } UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } bool WasFinished() const { return _wasFinished; } }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/OutBuffer.cpp ================================================ // OutByte.cpp #include "StdAfx.h" #include "OutBuffer.h" #include "../../Common/Alloc.h" bool COutBuffer::Create(UInt32 bufferSize) { const UInt32 kMinBlockSize = 1; if (bufferSize < kMinBlockSize) bufferSize = kMinBlockSize; if (_buffer != 0 && _bufferSize == bufferSize) return true; Free(); _bufferSize = bufferSize; _buffer = (Byte *)::MidAlloc(bufferSize); return (_buffer != 0); } void COutBuffer::Free() { ::MidFree(_buffer); _buffer = 0; } void COutBuffer::SetStream(ISequentialOutStream *stream) { _stream = stream; } void COutBuffer::Init() { _streamPos = 0; _limitPos = _bufferSize; _pos = 0; _processedSize = 0; _overDict = false; #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } UInt64 COutBuffer::GetProcessedSize() const { UInt64 res = _processedSize + _pos - _streamPos; if (_streamPos > _pos) res += _bufferSize; return res; } HRESULT COutBuffer::FlushPart() { // _streamPos < _bufferSize UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); HRESULT result = S_OK; #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) result = ErrorCode; #endif if (_buffer2 != 0) { memmove(_buffer2, _buffer + _streamPos, size); _buffer2 += size; } if (_stream != 0 #ifdef _NO_EXCEPTIONS && (ErrorCode != S_OK) #endif ) { UInt32 processedSize = 0; result = _stream->Write(_buffer + _streamPos, size, &processedSize); size = processedSize; } _streamPos += size; if (_streamPos == _bufferSize) _streamPos = 0; if (_pos == _bufferSize) { _overDict = true; _pos = 0; } _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; _processedSize += size; return result; } HRESULT COutBuffer::Flush() { #ifdef _NO_EXCEPTIONS if (ErrorCode != S_OK) return ErrorCode; #endif while(_streamPos != _pos) { HRESULT result = FlushPart(); if (result != S_OK) return result; } return S_OK; } void COutBuffer::FlushWithCheck() { HRESULT result = FlushPart(); #ifdef _NO_EXCEPTIONS ErrorCode = result; #else if (result != S_OK) throw COutBufferException(result); #endif } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/OutBuffer.h ================================================ // OutBuffer.h #ifndef __OUTBUFFER_H #define __OUTBUFFER_H #include "../IStream.h" #include "../../Common/MyCom.h" #ifndef _NO_EXCEPTIONS struct COutBufferException { HRESULT ErrorCode; COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif class COutBuffer { protected: Byte *_buffer; UInt32 _pos; UInt32 _limitPos; UInt32 _streamPos; UInt32 _bufferSize; CMyComPtr<ISequentialOutStream> _stream; UInt64 _processedSize; Byte *_buffer2; bool _overDict; HRESULT FlushPart(); void FlushWithCheck(); public: #ifdef _NO_EXCEPTIONS HRESULT ErrorCode; #endif COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} ~COutBuffer() { Free(); } bool Create(UInt32 bufferSize); void Free(); void SetMemStream(Byte *buffer) { _buffer2 = buffer; } void SetStream(ISequentialOutStream *stream); void Init(); HRESULT Flush(); void ReleaseStream() { _stream.Release(); } void WriteByte(Byte b) { _buffer[_pos++] = b; if(_pos == _limitPos) FlushWithCheck(); } void WriteBytes(const void *data, size_t size) { for (size_t i = 0; i < size; i++) WriteByte(((const Byte *)data)[i]); } UInt64 GetProcessedSize() const; }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../Common/MyWindows.h" #include "../../Common/NewHandler.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/StreamUtils.cpp ================================================ // StreamUtils.cpp #include "StdAfx.h" #include "../../Common/MyCom.h" #include "StreamUtils.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Read(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (Byte *)((Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) return S_OK; } return S_OK; } HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize != 0) *processedSize = 0; while(size != 0) { UInt32 processedSizeLoc; HRESULT res = stream->Write(data, size, &processedSizeLoc); if (processedSize != 0) *processedSize += processedSizeLoc; data = (const void *)((const Byte *)data + processedSizeLoc); size -= processedSizeLoc; RINOK(res); if (processedSizeLoc == 0) break; } return S_OK; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Common/StreamUtils.h ================================================ // StreamUtils.h #ifndef __STREAMUTILS_H #define __STREAMUTILS_H #include "../IStream.h" HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/ARM.cpp ================================================ // ARM.cpp #include "StdAfx.h" #include "ARM.h" #include "BranchARM.c" UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARM_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/ARM.h ================================================ // ARM.h #ifndef __ARM_H #define __ARM_H #include "BranchCoder.h" MyClassA(BC_ARM, 0x05, 1) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/ARMThumb.cpp ================================================ // ARMThumb.cpp #include "StdAfx.h" #include "ARMThumb.h" #include "BranchARMThumb.c" UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 1); } UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) { return ::ARMThumb_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/ARMThumb.h ================================================ // ARMThumb.h #ifndef __ARMTHUMB_H #define __ARMTHUMB_H #include "BranchCoder.h" MyClassA(BC_ARMThumb, 0x07, 1) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchARM.c ================================================ // BranchARM.c #include "BranchARM.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i + 3] == 0xEB) { UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + 8 + src; else dest = src - (nowPos + i + 8); dest >>= 2; data[i + 2] = (dest >> 16); data[i + 1] = (dest >> 8); data[i + 0] = dest; } } return i; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchARM.h ================================================ // BranchARM.h #ifndef __BRANCH_ARM_H #define __BRANCH_ARM_H #include "Common/Types.h" UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchARMThumb.c ================================================ // BranchARMThumb.c #include "BranchARMThumb.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 2) { if ((data[i + 1] & 0xF8) == 0xF0 && (data[i + 3] & 0xF8) == 0xF8) { UInt32 src = ((data[i + 1] & 0x7) << 19) | (data[i + 0] << 11) | ((data[i + 3] & 0x7) << 8) | (data[i + 2]); src <<= 1; UInt32 dest; if (encoding) dest = nowPos + i + 4 + src; else dest = src - (nowPos + i + 4); dest >>= 1; data[i + 1] = 0xF0 | ((dest >> 19) & 0x7); data[i + 0] = (dest >> 11); data[i + 3] = 0xF8 | ((dest >> 8) & 0x7); data[i + 2] = (dest); i += 2; } } return i; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchARMThumb.h ================================================ // BranchARMThumb.h #ifndef __BRANCH_ARM_THUMB_H #define __BRANCH_ARM_THUMB_H #include "Common/Types.h" UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchCoder.cpp ================================================ // BranchCoder.cpp #include "StdAfx.h" #include "BranchCoder.h" STDMETHODIMP CBranchConverter::Init() { _bufferPos = 0; SubInit(); return S_OK; } STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) { UInt32 processedSize = SubFilter(data, size); _bufferPos += processedSize; return processedSize; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchCoder.h ================================================ // BranchCoder.h #ifndef __BRANCH_CODER_H #define __BRANCH_CODER_H #include "Common/MyCom.h" #include "Common/Types.h" #include "Common/Alloc.h" #include "../../ICoder.h" class CBranchConverter: public ICompressFilter, public CMyUnknownImp { protected: UInt32 _bufferPos; virtual void SubInit() {} virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; public: MY_UNKNOWN_IMP; STDMETHOD(Init)(); STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); }; #define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ { public: UInt32 SubFilter(Byte *data, UInt32 size); }; #define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; #define MyClass2b(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClassA(Name, id, subId) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderA(Name ## _Encoder) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderA(Name ## _Decoder) #define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Encoder, id, subId, 0x01) \ MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ MyClass2b(Name ## _Decoder, id, subId, 0x00) \ MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchIA64.c ================================================ // BranchIA64.c #include "BranchIA64.h" const Byte kBranchTable[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0 }; UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 16 <= size; i += 16) { UInt32 instrTemplate = data[i] & 0x1F; UInt32 mask = kBranchTable[instrTemplate]; UInt32 bitPos = 5; for (int slot = 0; slot < 3; slot++, bitPos += 41) { if (((mask >> slot) & 1) == 0) continue; UInt32 bytePos = (bitPos >> 3); UInt32 bitRes = bitPos & 0x7; // UInt64 instruction = *(UInt64 *)(data + i + bytePos); UInt64 instruction = 0; int j; for (j = 0; j < 6; j++) instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); UInt64 instNorm = instruction >> bitRes; if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0 // && (instNorm & 0x3F)== 0 ) { UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF); src |= ((instNorm >> 36) & 1) << 20; src <<= 4; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 4; instNorm &= ~(UInt64(0x8FFFFF) << 13); instNorm |= (UInt64(dest & 0xFFFFF) << 13); instNorm |= (UInt64(dest & 0x100000) << (36 - 20)); instruction &= (1 << bitRes) - 1; instruction |= (instNorm << bitRes); // *(UInt64 *)(data + i + bytePos) = instruction; for (j = 0; j < 6; j++) data[i + j + bytePos] = Byte(instruction >> (8 * j)); } } } return i; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchIA64.h ================================================ // BranchIA64.h #ifndef __BRANCH_IA64_H #define __BRANCH_IA64_H #include "Common/Types.h" UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchPPC.c ================================================ // BranchPPC.c #include "BranchPPC.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { // PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) if ((data[i] >> 2) == 0x12 && ( (data[i + 3] & 3) == 1 // || (data[i+3] & 3) == 3 ) ) { UInt32 src = ((data[i + 0] & 3) << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3] & (~3)); UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); data[i + 0] = 0x48 | ((dest >> 24) & 0x3); data[i + 1] = (dest >> 16); data[i + 2] = (dest >> 8); data[i + 3] &= 0x3; data[i + 3] |= dest; } } return i; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchPPC.h ================================================ // BranchPPC.h #ifndef __BRANCH_PPC_H #define __BRANCH_PPC_H #include "Common/Types.h" UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchSPARC.c ================================================ // BranchSPARC.c #include "BranchSPARC.h" UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) { UInt32 i; for (i = 0; i + 4 <= size; i += 4) { if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) { UInt32 src = ((UInt32)data[i + 0] << 24) | ((UInt32)data[i + 1] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 3]); src <<= 2; UInt32 dest; if (encoding) dest = nowPos + i + src; else dest = src - (nowPos + i); dest >>= 2; dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; data[i + 0] = (Byte)(dest >> 24); data[i + 1] = (Byte)(dest >> 16); data[i + 2] = (Byte)(dest >> 8); data[i + 3] = (Byte)dest; } } return i; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchSPARC.h ================================================ // BranchSPARC.h #ifndef __BRANCH_SPARC_H #define __BRANCH_SPARC_H #include "Common/Types.h" UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchX86.c ================================================ /* BranchX86.c */ #include "BranchX86.h" /* static int inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } */ #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; /* void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos) { *prevMask = 0; *prevPos = (UInt32)(-5); } */ UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding) { UInt32 bufferPos = 0; UInt32 limit; if (endPos < 5) return 0; if (nowPos - *prevPos > 5) *prevPos = nowPos - 5; limit = endPos - 5; while(bufferPos <= limit) { Byte b = buffer[bufferPos]; UInt32 offset; if (b != 0xE8 && b != 0xE9) { bufferPos++; continue; } offset = (nowPos + bufferPos - *prevPos); *prevPos = (nowPos + bufferPos); if (offset > 5) *prevMask = 0; else { UInt32 i; for (i = 0; i < offset; i++) { *prevMask &= 0x77; *prevMask <<= 1; } } b = buffer[bufferPos + 4]; if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] && (*prevMask >> 1) < 0x10) { UInt32 src = ((UInt32)(b) << 24) | ((UInt32)(buffer[bufferPos + 3]) << 16) | ((UInt32)(buffer[bufferPos + 2]) << 8) | (buffer[bufferPos + 1]); UInt32 dest; while(1) { UInt32 index; if (encoding) dest = (nowPos + bufferPos + 5) + src; else dest = src - (nowPos + bufferPos + 5); if (*prevMask == 0) break; index = kMaskToBitNumber[*prevMask >> 1]; b = (Byte)(dest >> (24 - index * 8)); if (!Test86MSByte(b)) break; src = dest ^ ((1 << (32 - index * 8)) - 1); } buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1)); buffer[bufferPos + 3] = (Byte)(dest >> 16); buffer[bufferPos + 2] = (Byte)(dest >> 8); buffer[bufferPos + 1] = (Byte)dest; bufferPos += 5; *prevMask = 0; } else { bufferPos++; *prevMask |= 1; if (Test86MSByte(b)) *prevMask |= 0x10; } } return bufferPos; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/BranchX86.h ================================================ /* BranchX86.h */ #ifndef __BRANCHX86_H #define __BRANCHX86_H #ifndef UInt32 #define UInt32 unsigned int #endif #ifndef Byte #define Byte unsigned char #endif #define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); } UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, UInt32 *prevMask, UInt32 *prevPos, int encoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/IA64.cpp ================================================ // IA64.cpp #include "StdAfx.h" #include "IA64.h" #include "BranchIA64.c" UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 1); } UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) { return ::IA64_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/IA64.h ================================================ // IA64.h #ifndef __IA64_H #define __IA64_H #include "BranchCoder.h" MyClassA(BC_IA64, 0x04, 1) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/PPC.cpp ================================================ // PPC.cpp #include "StdAfx.h" #include "PPC.h" #include "Windows/Defs.h" #include "BranchPPC.c" UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 1); } UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) { return ::PPC_B_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/PPC.h ================================================ // PPC.h #ifndef __PPC_H #define __PPC_H #include "BranchCoder.h" MyClassA(BC_PPC_B, 0x02, 5) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/SPARC.cpp ================================================ // SPARC.cpp #include "StdAfx.h" #include "SPARC.h" #include "Windows/Defs.h" #include "BranchSPARC.c" UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 1); } UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) { return ::SPARC_Convert(data, size, _bufferPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/SPARC.h ================================================ // SPARC.h #ifndef __SPARC_H #define __SPARC_H #include "BranchCoder.h" MyClassA(BC_SPARC, 0x08, 5) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/x86.cpp ================================================ // x86.cpp #include "StdAfx.h" #include "x86.h" #include "Windows/Defs.h" #include "BranchX86.c" UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1); } UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) { return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/x86.h ================================================ // x86.h #ifndef __X86_H #define __X86_H #include "BranchCoder.h" #include "BranchX86.h" struct CBranch86 { UInt32 _prevMask; UInt32 _prevPos; void x86Init() { x86_Convert_Init(_prevMask, _prevPos); } }; MyClassB(BCJ_x86, 0x01, 3, CBranch86 , virtual void SubInit() { x86Init(); }) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/x86_2.cpp ================================================ // x86_2.cpp #include "StdAfx.h" #include "x86_2.h" #include "../../../Common/Alloc.h" static const int kBufferSize = 1 << 17; inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); } #ifndef EXTRACT_ONLY static bool inline Test86MSByte(Byte b) { return (b == 0 || b == 0xFF); } bool CBCJ2_x86_Encoder::Create() { if (!_mainStream.Create(1 << 16)) return false; if (!_callStream.Create(1 << 20)) return false; if (!_jumpStream.Create(1 << 20)) return false; if (!_rangeEncoder.Create(1 << 20)) return false; if (_buffer == 0) { _buffer = (Byte *)MidAlloc(kBufferSize); if (_buffer == 0) return false; } return true; } CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder() { ::MidFree(_buffer); } HRESULT CBCJ2_x86_Encoder::Flush() { RINOK(_mainStream.Flush()); RINOK(_callStream.Flush()); RINOK(_jumpStream.Flush()); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } const UInt32 kDefaultLimit = (1 << 24); HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 1 || numOutStreams != 4) return E_INVALIDARG; if (!Create()) return E_OUTOFMEMORY; bool sizeIsDefined = false; UInt64 inSize; if (inSizes != NULL) if (inSizes[0] != NULL) { inSize = *inSizes[0]; if (inSize <= kDefaultLimit) sizeIsDefined = true; } ISequentialInStream *inStream = inStreams[0]; _mainStream.SetStream(outStreams[0]); _mainStream.Init(); _callStream.SetStream(outStreams[1]); _callStream.Init(); _jumpStream.SetStream(outStreams[2]); _jumpStream.Init(); _rangeEncoder.SetStream(outStreams[3]); _rangeEncoder.Init(); for (int i = 0; i < 256; i++) _statusE8Encoder[i].Init(); _statusE9Encoder.Init(); _statusJccEncoder.Init(); CCoderReleaser releaser(this); CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize; { inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); } UInt32 nowPos = 0; UInt64 nowPos64 = 0; UInt32 bufferPos = 0; Byte prevByte = 0; UInt64 subStreamIndex = 0; UInt64 subStreamStartPos = 0; UInt64 subStreamEndPos = 0; while(true) { UInt32 processedSize = 0; while(true) { UInt32 size = kBufferSize - (bufferPos + processedSize); UInt32 processedSizeLoc; if (size == 0) break; RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); if (processedSizeLoc == 0) break; processedSize += processedSizeLoc; } UInt32 endPos = bufferPos + processedSize; if (endPos < 5) { // change it for (bufferPos = 0; bufferPos < endPos; bufferPos++) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else if (IsJcc(prevByte, b)) _statusJccEncoder.Encode(&_rangeEncoder, 0); prevByte = b; } return Flush(); } bufferPos = 0; UInt32 limit = endPos - 5; while(bufferPos <= limit) { Byte b = _buffer[bufferPos]; _mainStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { bufferPos++; prevByte = b; continue; } Byte nextByte = _buffer[bufferPos + 4]; UInt32 src = (UInt32(nextByte) << 24) | (UInt32(_buffer[bufferPos + 3]) << 16) | (UInt32(_buffer[bufferPos + 2]) << 8) | (_buffer[bufferPos + 1]); UInt32 dest = (nowPos + bufferPos + 5) + src; // if (Test86MSByte(nextByte)) bool convert; if (getSubStreamSize != NULL) { UInt64 currentPos = (nowPos64 + bufferPos); while (subStreamEndPos < currentPos) { UInt64 subStreamSize; HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); if (result == S_OK) { subStreamStartPos = subStreamEndPos; subStreamEndPos += subStreamSize; subStreamIndex++; } else if (result == S_FALSE || result == E_NOTIMPL) { getSubStreamSize.Release(); subStreamStartPos = 0; subStreamEndPos = subStreamStartPos - 1; } else return result; } if (getSubStreamSize == NULL) { if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); } else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) convert = Test86MSByte(nextByte); else { UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); } } else if (sizeIsDefined) convert = (dest < inSize); else convert = Test86MSByte(nextByte); if (convert) { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 1); else _statusJccEncoder.Encode(&_rangeEncoder, 1); bufferPos += 5; if (b == 0xE8) { _callStream.WriteByte((Byte)(dest >> 24)); _callStream.WriteByte((Byte)(dest >> 16)); _callStream.WriteByte((Byte)(dest >> 8)); _callStream.WriteByte((Byte)(dest)); } else { _jumpStream.WriteByte((Byte)(dest >> 24)); _jumpStream.WriteByte((Byte)(dest >> 16)); _jumpStream.WriteByte((Byte)(dest >> 8)); _jumpStream.WriteByte((Byte)(dest)); } prevByte = nextByte; } else { if (b == 0xE8) _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); else if (b == 0xE9) _statusE9Encoder.Encode(&_rangeEncoder, 0); else _statusJccEncoder.Encode(&_rangeEncoder, 0); bufferPos++; prevByte = b; } } nowPos += bufferPos; nowPos64 += bufferPos; if (progress != NULL) { RINOK(progress->SetRatioInfo(&nowPos64, NULL)); } UInt32 i = 0; while(bufferPos < endPos) _buffer[i++] = _buffer[bufferPos++]; bufferPos = i; } } STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } #endif HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != 4 || numOutStreams != 1) return E_INVALIDARG; if (!_mainInStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_callStream.Create(1 << 20)) return E_OUTOFMEMORY; if (!_jumpStream.Create(1 << 16)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_outStream.Create(1 << 16)) return E_OUTOFMEMORY; _mainInStream.SetStream(inStreams[0]); _callStream.SetStream(inStreams[1]); _jumpStream.SetStream(inStreams[2]); _rangeDecoder.SetStream(inStreams[3]); _outStream.SetStream(outStreams[0]); _mainInStream.Init(); _callStream.Init(); _jumpStream.Init(); _rangeDecoder.Init(); _outStream.Init(); for (int i = 0; i < 256; i++) _statusE8Decoder[i].Init(); _statusE9Decoder.Init(); _statusJccDecoder.Init(); CCoderReleaser releaser(this); Byte prevByte = 0; UInt32 processedBytes = 0; while(true) { if (processedBytes > (1 << 20) && progress != NULL) { UInt64 nowPos64 = _outStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(NULL, &nowPos64)); processedBytes = 0; } processedBytes++; Byte b; if (!_mainInStream.ReadByte(b)) return Flush(); _outStream.WriteByte(b); if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) { prevByte = b; continue; } bool status; if (b == 0xE8) status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1); else if (b == 0xE9) status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1); else status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1); if (status) { UInt32 src; if (b == 0xE8) { Byte b0; if(!_callStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_callStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } else { Byte b0; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src = ((UInt32)b0) << 24; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 16; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0) << 8; if(!_jumpStream.ReadByte(b0)) return S_FALSE; src |= ((UInt32)b0); } UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; _outStream.WriteByte((Byte)(dest)); _outStream.WriteByte((Byte)(dest >> 8)); _outStream.WriteByte((Byte)(dest >> 16)); _outStream.WriteByte((Byte)(dest >> 24)); prevByte = (dest >> 24); processedBytes += 4; } else prevByte = b; } } STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { try { return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress); } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/Branch/x86_2.h ================================================ // x86_2.h #ifndef __BRANCH_X86_2_H #define __BRANCH_X86_2_H #include "../../../Common/MyCom.h" #include "../RangeCoder/RangeCoderBit.h" #include "../../ICoder.h" // {23170F69-40C1-278B-0303-010100000100} #define MyClass2_a(Name, id, subId, encodingId) \ DEFINE_GUID(CLSID_CCompressConvert ## Name, \ 0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); #define MyClass_a(Name, id, subId) \ MyClass2_a(Name ## _Encoder, id, subId, 0x01) \ MyClass2_a(Name ## _Decoder, id, subId, 0x00) MyClass_a(BCJ2_x86, 0x01, 0x1B) const int kNumMoveBits = 5; #ifndef EXTRACT_ONLY class CBCJ2_x86_Encoder: public ICompressCoder2, public CMyUnknownImp { Byte *_buffer; public: CBCJ2_x86_Encoder(): _buffer(0) {}; ~CBCJ2_x86_Encoder(); bool Create(); COutBuffer _mainStream; COutBuffer _callStream; COutBuffer _jumpStream; NCompress::NRangeCoder::CEncoder _rangeEncoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE8Encoder[256]; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusE9Encoder; NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusJccEncoder; HRESULT Flush(); void ReleaseStreams() { _mainStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeEncoder.ReleaseStream(); } class CCoderReleaser { CBCJ2_x86_Encoder *_coder; public: CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif class CBCJ2_x86_Decoder: public ICompressCoder2, public CMyUnknownImp { public: CInBuffer _mainInStream; CInBuffer _callStream; CInBuffer _jumpStream; NCompress::NRangeCoder::CDecoder _rangeDecoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE8Decoder[256]; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusE9Decoder; NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusJccDecoder; COutBuffer _outStream; void ReleaseStreams() { _mainInStream.ReleaseStream(); _callStream.ReleaseStream(); _jumpStream.ReleaseStream(); _rangeDecoder.ReleaseStream(); _outStream.ReleaseStream(); } HRESULT Flush() { return _outStream.Flush(); } class CCoderReleaser { CBCJ2_x86_Decoder *_coder; public: CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; public: MY_UNKNOWN_IMP HRESULT CodeReal(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress); }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h ================================================ // BinTree.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace BT_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderBinTree: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr<IMatchFinderCallback> m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderBinTree(); virtual ~CMatchFinderBinTree(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h ================================================ // BinTree2.h #ifndef __BINTREE2_H #define __BINTREE2_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT2 #include "BinTree.h" #include "BinTreeMain.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h ================================================ // BinTree3.h #ifndef __BINTREE3_H #define __BINTREE3_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3 #define HASH_ARRAY_2 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h ================================================ // BinTree3Z.h #ifndef __BINTREE3Z_H #define __BINTREE3Z_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT3Z #define HASH_ZIP #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ZIP #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h ================================================ // BinTree4.h #ifndef __BINTREE4_H #define __BINTREE4_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTree4b.h ================================================ // BinTree4b.h #ifndef __BINTREE4B_H #define __BINTREE4B_H #undef BT_NAMESPACE #define BT_NAMESPACE NBT4B #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "BinTree.h" #include "BinTreeMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h ================================================ // BinTreeMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace BT_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 3; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderBinTree::CMatchFinderBinTree(): _hash(0), _cutValue(0xFF) { } void CMatchFinderBinTree::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderBinTree::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderBinTree::~CMatchFinderBinTree() { FreeMemory(); } STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1); return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2]; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; #endif _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; // We don't need tree in this case } else #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) { *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; break; } Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < len) distances[++maxLen] = delta - 1; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; break; } } } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch() { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *son = _hash + kHashSizeSum; CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; CIndex *ptr1 = son + (_cyclicBufferPos << 1); #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit != kNumHashDirectBytes) #endif { UInt32 len0, len1; len0 = len1 = kNumHashDirectBytes; UInt32 count = _cutValue; while(true) { if(curMatch <= matchMinPos || count-- == 0) break; Byte *pb = _buffer + curMatch; UInt32 len = MyMin(len0, len1); do { if (pb[len] != cur[len]) break; } while(++len != lenLimit); UInt32 delta = _pos - curMatch; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); CIndex *pair = son + (cyclicPos << 1); if (len != lenLimit) { if (pb[len] < cur[len]) { *ptr1 = curMatch; ptr1 = pair + 1; curMatch = *ptr1; len1 = len; } else { *ptr0 = curMatch; ptr0 = pair; curMatch = *ptr0; len0 = len; } } else { *ptr1 = pair[0]; *ptr0 = pair[1]; return; } } } *ptr0 = kEmptyHashValue; *ptr1 = kEmptyHashValue; } void CMatchFinderBinTree::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2); for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderBinTree::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderBinTree::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderBinTree::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HC.h ================================================ // HC.h #include "../LZInWindow.h" #include "../IMatchFinder.h" namespace HC_NAMESPACE { typedef UInt32 CIndex; const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; class CMatchFinderHC: public IMatchFinder, public IMatchFinderSetCallback, public CLZInWindow, public CMyUnknownImp { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; // it must be historySize + 1 UInt32 _matchMaxLen; CIndex *_hash; UInt32 _cutValue; CMyComPtr<IMatchFinderCallback> m_Callback; void Normalize(); void FreeThisClassMemory(); void FreeMemory(); MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *inStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); public: CMatchFinderHC(); virtual ~CMatchFinderHC(); void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } }; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HC2.h ================================================ // HC2.h #ifndef __HC2_H #define __HC2_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC2 #include "HCMF.h" #include "HCMFMain.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HC3.h ================================================ // HC3.h #ifndef __HC3_H #define __HC3_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC3 #define HASH_ARRAY_2 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HC4.h ================================================ // HC4.h #ifndef __HC4_H #define __HC4_H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4 #define HASH_ARRAY_2 #define HASH_ARRAY_3 #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HC4b.h ================================================ // HC4b.h #ifndef __HC4B__H #define __HC4B__H #undef HC_NAMESPACE #define HC_NAMESPACE NHC4b #define HASH_ARRAY_2 #define HASH_ARRAY_3 #define HASH_BIG #include "HC.h" #include "HCMain.h" #undef HASH_ARRAY_2 #undef HASH_ARRAY_3 #undef HASH_BIG #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h ================================================ // HC.h #include "../../../../Common/Defs.h" #include "../../../../Common/CRC.h" #include "../../../../Common/Alloc.h" namespace HC_NAMESPACE { #ifdef HASH_ARRAY_2 static const UInt32 kHash2Size = 1 << 10; #ifdef HASH_ARRAY_3 static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 4; static const UInt32 kHash3Size = 1 << 18; #ifdef HASH_BIG static const UInt32 kHashSize = 1 << 23; #else static const UInt32 kHashSize = 1 << 20; #endif #else static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (16); #endif #else #ifdef HASH_ZIP static const UInt32 kNumHashDirectBytes = 0; static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << 16; #else #define THERE_ARE_DIRECT_HASH_BYTES static const UInt32 kNumHashDirectBytes = 2; static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); #endif #endif static const UInt32 kHashSizeSum = kHashSize #ifdef HASH_ARRAY_2 + kHash2Size #ifdef HASH_ARRAY_3 + kHash3Size #endif #endif ; #ifdef HASH_ARRAY_2 static const UInt32 kHash2Offset = kHashSize; #ifdef HASH_ARRAY_3 static const UInt32 kHash3Offset = kHashSize + kHash2Size; #endif #endif CMatchFinderHC::CMatchFinderHC(): _hash(0), _cutValue(16) { } void CMatchFinderHC::FreeThisClassMemory() { BigFree(_hash); _hash = 0; } void CMatchFinderHC::FreeMemory() { FreeThisClassMemory(); CLZInWindow::Free(); } CMatchFinderHC::~CMatchFinderHC() { FreeMemory(); } STDMETHODIMP CMatchFinderHC::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { UInt32 sizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; if (CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, sizeReserv)) { if (historySize + 256 > kMaxValForNormalize) { FreeMemory(); return E_INVALIDARG; } _matchMaxLen = matchMaxLen; UInt32 newCyclicBufferSize = historySize + 1; if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) return S_OK; FreeThisClassMemory(); _cyclicBufferSize = newCyclicBufferSize; // don't change it _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize) * sizeof(CIndex)); if (_hash != 0) return S_OK; } FreeMemory(); return E_OUTOFMEMORY; } static const UInt32 kEmptyHashValue = 0; STDMETHODIMP CMatchFinderHC::Init(ISequentialInStream *stream) { RINOK(CLZInWindow::Init(stream)); for(UInt32 i = 0; i < kHashSizeSum; i++) _hash[i] = kEmptyHashValue; _cyclicBufferPos = 0; ReduceOffsets(-1); return S_OK; } STDMETHODIMP_(void) CMatchFinderHC::ReleaseStream() { // ReleaseStream(); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1); return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) & (kHashSize - 1); } #else // no HASH_ARRAY_3 inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value) { UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1]; hash2Value = temp & (kHash2Size - 1); return (temp ^ (UInt32(pointer[2]) << 8)) & (kHashSize - 1);; } #endif // HASH_ARRAY_3 #else // no HASH_ARRAY_2 #ifdef HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); } #else // no HASH_ZIP inline UInt32 Hash(const Byte *pointer) { return pointer[0] ^ (UInt32(pointer[1]) << 8); } #endif // HASH_ZIP #endif // HASH_ARRAY_2 STDMETHODIMP_(UInt32) CMatchFinderHC::GetLongestMatch(UInt32 *distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if(lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; Byte *cur = _buffer + _pos; UInt32 maxLen = 0; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); #else UInt32 hashValue = Hash(cur, hash2Value); #endif #else UInt32 hashValue = Hash(cur); #endif #ifdef HASH_ARRAY_2 UInt32 curMatch2 = _hash[kHash2Offset + hash2Value]; _hash[kHash2Offset + hash2Value] = _pos; distances[2] = 0xFFFFFFFF; if(curMatch2 > matchMinPos) if (_buffer[curMatch2] == cur[0]) { distances[2] = _pos - curMatch2 - 1; maxLen = 2; } #ifdef HASH_ARRAY_3 UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; _hash[kHash3Offset + hash3Value] = _pos; distances[3] = 0xFFFFFFFF; if(curMatch3 > matchMinPos) if (_buffer[curMatch3] == cur[0]) { distances[3] = _pos - curMatch3 - 1; maxLen = 3; } #endif #endif UInt32 curMatch = _hash[hashValue]; _hash[hashValue] = _pos; CIndex *chain = _hash + kHashSizeSum; chain[_cyclicBufferPos] = curMatch; distances[kNumHashBytes] = 0xFFFFFFFF; #ifdef THERE_ARE_DIRECT_HASH_BYTES if (lenLimit == kNumHashDirectBytes) { if(curMatch > matchMinPos) while (maxLen < kNumHashDirectBytes) distances[++maxLen] = _pos - curMatch - 1; } else #endif { UInt32 count = _cutValue; do { if(curMatch <= matchMinPos) break; Byte *pby1 = _buffer + curMatch; UInt32 currentLen = kNumHashDirectBytes; do { if (pby1[currentLen] != cur[currentLen]) break; } while(++currentLen != lenLimit); UInt32 delta = _pos - curMatch; while (maxLen < currentLen) distances[++maxLen] = delta - 1; if(currentLen == lenLimit) break; UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta): (_cyclicBufferPos - delta + _cyclicBufferSize); curMatch = chain[cyclicPos]; } while(--count != 0); } #ifdef HASH_ARRAY_2 #ifdef HASH_ARRAY_3 if (distances[4] < distances[3]) distances[3] = distances[4]; #endif if (distances[3] < distances[2]) distances[2] = distances[3]; #endif return maxLen; } STDMETHODIMP_(void) CMatchFinderHC::DummyLongestMatch() { if (_streamPos - _pos < kNumHashBytes) return; Byte *cur = _buffer + _pos; #ifdef HASH_ARRAY_2 UInt32 hash2Value; #ifdef HASH_ARRAY_3 UInt32 hash3Value; UInt32 hashValue = Hash(cur, hash2Value, hash3Value); _hash[kHash3Offset + hash3Value] = _pos; #else UInt32 hashValue = Hash(cur, hash2Value); #endif _hash[kHash2Offset + hash2Value] = _pos; #else UInt32 hashValue = Hash(cur); #endif _hash[kHashSizeSum + _cyclicBufferPos] = _hash[hashValue]; _hash[hashValue] = _pos; } void CMatchFinderHC::Normalize() { UInt32 subValue = _pos - _cyclicBufferSize; CIndex *items = _hash; UInt32 numItems = kHashSizeSum + _cyclicBufferSize; for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } ReduceOffsets(subValue); } STDMETHODIMP CMatchFinderHC::MovePos() { if (++_cyclicBufferPos == _cyclicBufferSize) _cyclicBufferPos = 0; RINOK(CLZInWindow::MovePos()); if (_pos == kMaxValForNormalize) Normalize(); return S_OK; } STDMETHODIMP_(Byte) CMatchFinderHC::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CMatchFinderHC::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CMatchFinderHC::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } // IMatchFinderSetCallback STDMETHODIMP CMatchFinderHC::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CMatchFinderHC::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CMatchFinderHC::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/IMatchFinder.h ================================================ // MatchFinders/IMatchFinder.h #ifndef __IMATCHFINDER_H #define __IMATCHFINDER_H // {23170F69-40C1-278A-0000-000200010000} DEFINE_GUID(IID_IInWindowStream, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200010000") IInWindowStream: public IUnknown { STDMETHOD(Init)(ISequentialInStream *inStream) PURE; STDMETHOD_(void, ReleaseStream)() PURE; STDMETHOD(MovePos)() PURE; STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020000} DEFINE_GUID(IID_IMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020000") IMatchFinder: public IInWindowStream { STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances) PURE; STDMETHOD_(void, DummyLongestMatch)() PURE; }; // {23170F69-40C1-278A-0000-000200020100} DEFINE_GUID(IID_IMatchFinderCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020100") IMatchFinderCallback: public IUnknown { STDMETHOD(BeforeChangingBufferPos)() PURE; STDMETHOD(AfterChangingBufferPos)() PURE; }; // {23170F69-40C1-278A-0000-000200020200} DEFINE_GUID(IID_IMatchFinderSetCallback, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200020200") IMatchFinderSetCallback: public IUnknown { STDMETHOD(SetCallback)(IMatchFinderCallback *callback) PURE; }; /* // {23170F69-40C1-278A-0000-000200030000} DEFINE_GUID(IID_IInitMatchFinder, 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00); MIDL_INTERFACE("23170F69-40C1-278A-0000-000200030000") IMatchFinderInit: public IUnknown { STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder) PURE; }; */ #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/LZInWindow.cpp ================================================ // LZInWindow.cpp #include "StdAfx.h" #include "LZInWindow.h" #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" void CLZInWindow::Free() { ::BigFree(_bufferBase); _bufferBase = 0; } bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == 0 || _blockSize != blockSize) { Free(); _blockSize = blockSize; if (_blockSize != 0) _bufferBase = (Byte *)::BigAlloc(_blockSize); } _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; if (_blockSize == 0) return true; return (_bufferBase != 0); } HRESULT CLZInWindow::Init(ISequentialInStream *stream) { _stream = stream; _buffer = _bufferBase; _pos = 0; _streamPos = 0; _streamEndWasReached = false; return ReadBlock(); } /* void CLZInWindow::ReleaseStream() { _stream.Release(); } */ /////////////////////////////////////////// // ReadBlock // In State: // (_buffer + _streamPos) <= (_bufferBase + _blockSize) // Out State: // _posLimit <= _blockSize - _keepSizeAfter; // if(_streamEndWasReached == false): // _streamPos >= _pos + _keepSizeAfter // _posLimit = _streamPos - _keepSizeAfter; // else // HRESULT CLZInWindow::ReadBlock() { if(_streamEndWasReached) return S_OK; while(true) { UInt32 size = UInt32(_bufferBase - _buffer) + _blockSize - _streamPos; if(size == 0) return S_OK; UInt32 numReadBytes; RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); if(numReadBytes == 0) { _posLimit = _streamPos; const Byte *pointerToPostion = _buffer + _posLimit; if(pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); _streamEndWasReached = true; return S_OK; } _streamPos += numReadBytes; if(_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; return S_OK; } } } void CLZInWindow::MoveBlock() { BeforeMoveBlock(); UInt32 offset = UInt32(_buffer - _bufferBase) + _pos - _keepSizeBefore; UInt32 numBytes = UInt32(_buffer - _bufferBase) + _streamPos - offset; memmove(_bufferBase, _bufferBase + offset, numBytes); _buffer -= offset; AfterMoveBlock(); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/LZInWindow.h ================================================ // LZInWindow.h #ifndef __LZ_IN_WINDOW_H #define __LZ_IN_WINDOW_H #include "../../IStream.h" class CLZInWindow { Byte *_bufferBase; // pointer to buffer with data ISequentialInStream *_stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream const Byte *_pointerToLastSafePosition; protected: Byte *_buffer; // Pointer to virtual Buffer begin UInt32 _blockSize; // Size of Allocated memory block UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream virtual void BeforeMoveBlock() {}; virtual void AfterMoveBlock() {}; void MoveBlock(); virtual HRESULT ReadBlock(); void Free(); public: CLZInWindow(): _bufferBase(0) {} virtual ~CLZInWindow() { Free(); } bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); HRESULT Init(ISequentialInStream *stream); // void ReleaseStream(); Byte *GetBuffer() const { return _buffer; } const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } HRESULT MovePos() { _pos++; if (_pos > _posLimit) { const Byte *pointerToPostion = _buffer + _pos; if(pointerToPostion > _pointerToLastSafePosition) MoveBlock(); return ReadBlock(); } else return S_OK; } Byte GetIndexByte(Int32 index)const { return _buffer[(size_t)_pos + index]; } // index + limit have not to exceed _keepSizeAfter; UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const { if(_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; Byte *pby = _buffer + (size_t)_pos + index; UInt32 i; for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); return i; } UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } void ReduceOffsets(Int32 subValue) { _buffer += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp ================================================ // LZOutWindow.cpp #include "StdAfx.h" #include "../../../Common/Alloc.h" #include "LZOutWindow.h" void CLZOutWindow::Init(bool solid) { if(!solid) COutBuffer::Init(); #ifdef _NO_EXCEPTIONS ErrorCode = S_OK; #endif } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/LZOutWindow.h ================================================ // LZOutWindow.h #ifndef __LZ_OUT_WINDOW_H #define __LZ_OUT_WINDOW_H #include "../../IStream.h" #include "../../Common/OutBuffer.h" /* #ifndef _NO_EXCEPTIONS class CLZOutWindowException { public: HRESULT ErrorCode; CLZOutWindowException(HRESULT errorCode): ErrorCode(errorCode) {} }; #endif */ typedef COutBufferException CLZOutWindowException; class CLZOutWindow: public COutBuffer { public: void Init(bool solid = false); // distance >= 0, len > 0, bool CopyBlock(UInt32 distance, UInt32 len) { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) { if (!_overDict) return false; pos += _bufferSize; } do { if (pos == _bufferSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos == _limitPos) FlushWithCheck(); } while(--len != 0); return true; } void PutByte(Byte b) { _buffer[_pos++] = b; if (_pos == _limitPos) FlushWithCheck(); } Byte GetByte(UInt32 distance) const { UInt32 pos = _pos - distance - 1; if (pos >= _bufferSize) pos += _bufferSize; return _buffer[pos]; } }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat.h ================================================ // Pat.h // #ifndef __PATRICIA__H // #define __PATRICIA__H #include "../../../../Common/MyCom.h" #include "../../../../Common/Types.h" #include "../LZInWindow.h" namespace PAT_NAMESPACE { struct CNode; typedef CNode *CNodePointer; // #define __AUTO_REMOVE // #define __NODE_4_BITS // #define __NODE_3_BITS // #define __NODE_2_BITS // #define __NODE_2_BITS_PADDING // #define __HASH_3 typedef UInt32 CIndex; #ifdef __NODE_4_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else #ifdef __NODE_3_BITS typedef UInt32 CIndex2; typedef UInt32 CSameBitsType; #else typedef UInt32 CIndex; typedef UInt32 CSameBitsType; typedef CIndex CIndex2; #endif #endif const UInt32 kNumBitsInIndex = sizeof(CIndex) * 8; const UInt32 kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // don't change kMatchStartValue definition, since it is used in // PatMain.h: typedef CIndex CMatchPointer; const UInt32 kDescendantEmptyValue = kMatchStartValue - 1; union CDescendant { CIndex NodePointer; CMatchPointer MatchPointer; bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; } bool IsNode() const { return NodePointer < kDescendantEmptyValue; } bool IsMatch() const { return NodePointer > kDescendantEmptyValue; } void MakeEmpty() { NodePointer = kDescendantEmptyValue; } }; #undef MY_BYTE_SIZE #ifdef __NODE_4_BITS #define MY_BYTE_SIZE 8 const UInt32 kNumSubBits = 4; #else #ifdef __NODE_3_BITS #define MY_BYTE_SIZE 9 const UInt32 kNumSubBits = 3; #else #define MY_BYTE_SIZE 8 #ifdef __NODE_2_BITS const UInt32 kNumSubBits = 2; #else const UInt32 kNumSubBits = 1; #endif #endif #endif const UInt32 kNumSubNodes = 1 << kNumSubBits; const UInt32 kSubNodesMask = kNumSubNodes - 1; struct CNode { CIndex2 LastMatch; CSameBitsType NumSameBits; union { CDescendant Descendants[kNumSubNodes]; UInt32 NextFreeNode; }; #ifdef __NODE_2_BITS #ifdef __NODE_2_BITS_PADDING UInt32 Padding[2]; #endif #endif }; #undef kIDNumBitsByte #undef kIDNumBitsString #ifdef __NODE_4_BITS #define kIDNumBitsByte 0x30 #define kIDNumBitsString TEXT("4") #else #ifdef __NODE_3_BITS #define kIDNumBitsByte 0x20 #define kIDNumBitsString TEXT("3") #else #ifdef __NODE_2_BITS #define kIDNumBitsByte 0x10 #define kIDNumBitsString TEXT("2") #else #define kIDNumBitsByte 0x00 #define kIDNumBitsString TEXT("1") #endif #endif #endif #undef kIDManualRemoveByte #undef kIDManualRemoveString #ifdef __AUTO_REMOVE #define kIDManualRemoveByte 0x00 #define kIDManualRemoveString TEXT("") #else #define kIDManualRemoveByte 0x08 #define kIDManualRemoveString TEXT("R") #endif #undef kIDHash3Byte #undef kIDHash3String #ifdef __HASH_3 #define kIDHash3Byte 0x04 #define kIDHash3String TEXT("H") #else #define kIDHash3Byte 0x00 #define kIDHash3String TEXT("") #endif #undef kIDUse3BytesByte #undef kIDUse3BytesString #define kIDUse3BytesByte 0x00 #define kIDUse3BytesString TEXT("") #undef kIDPaddingByte #undef kIDPaddingString #ifdef __NODE_2_BITS_PADDING #define kIDPaddingByte 0x01 #define kIDPaddingString TEXT("P") #else #define kIDPaddingByte 0x00 #define kIDPaddingString TEXT("") #endif // #undef kIDString // #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String // {23170F69-40C1-278C-01XX-0000000000} DEFINE_GUID(PAT_CLSID, 0x23170F69, 0x40C1, 0x278C, 0x01, kIDNumBitsByte | kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // III(PAT_NAMESPACE) class CPatricia: public IMatchFinder, public IMatchFinderSetCallback, public CMyUnknownImp, CLZInWindow { MY_UNKNOWN_IMP1(IMatchFinderSetCallback) STDMETHOD(Init)(ISequentialInStream *aStream); STDMETHOD_(void, ReleaseStream)(); STDMETHOD(MovePos)(); STDMETHOD_(Byte, GetIndexByte)(Int32 index); STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); STDMETHOD_(UInt32, GetNumAvailableBytes)(); STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); STDMETHOD_(void, DummyLongestMatch)(); STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); void FreeMemory(); public: CPatricia(); ~CPatricia(); UInt32 _sizeHistory; UInt32 _matchMaxLen; CDescendant *m_HashDescendants; #ifdef __HASH_3 CDescendant *m_Hash2Descendants; #endif CNode *m_Nodes; UInt32 m_FreeNode; UInt32 m_FreeNodeMax; #ifdef __AUTO_REMOVE UInt32 m_NumUsedNodes; UInt32 m_NumNodes; #else bool m_SpecialRemoveMode; #endif bool m_SpecialMode; UInt32 m_NumNotChangedCycles; UInt32 *m_TmpBacks; CMyComPtr<IMatchFinderCallback> m_Callback; virtual void BeforeMoveBlock(); virtual void AfterMoveBlock(); // IMatchFinderSetCallback STDMETHOD(SetCallback)(IMatchFinderCallback *callback); void ChangeLastMatch(UInt32 hashValue); #ifdef __AUTO_REMOVE void TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos); void TestRemoveNodes(); void RemoveNode(UInt32 index); void TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue); void TestRemoveNodesAndNormalize(); #else void NormalizeDescendant(CDescendant &descendant, UInt32 subValue); void Normalize(); void RemoveMatch(); #endif private: void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos) { while((aByteXOR & kSubNodesMask) == 0) { aByteXOR >>= kNumSubBits; aByte >>= kNumSubBits; aNumSameBits -= kNumSubBits; } // Insert New Node CNodePointer aNewNode = &m_Nodes[m_FreeNode]; UInt32 aNodeIndex = *aNodePointerPointer; *aNodePointerPointer = m_FreeNode; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = aByte & kSubNodesMask; UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex; aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits); aNewNode->LastMatch = aPos; aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits); } void AddLeafNode(CNodePointer aNode, Byte aByte, Byte aByteXOR, UInt32 aNumSameBits, UInt32 aPos, UInt32 aDescendantIndex) { for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits) { aByte >>= kNumSubBits; aByteXOR >>= kNumSubBits; } UInt32 aNewNodeIndex = m_FreeNode; CNodePointer aNewNode = &m_Nodes[m_FreeNode]; m_FreeNode = aNewNode->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } UInt32 aBitsNew = (aByte & kSubNodesMask); UInt32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask; for (UInt32 i = 0; i < kNumSubNodes; i++) aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue; aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue; aNewNode->Descendants[aBitsOld].MatchPointer = aNode->Descendants[aDescendantIndex].MatchPointer; aNewNode->NumSameBits = CSameBitsType(aNumSameBits); aNewNode->LastMatch = aPos; aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex; } }; } // #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat2.h ================================================ // Pat2.h #ifndef __PAT2__H #define __PAT2__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2 #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2 #define __AUTO_REMOVE #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat2H.h ================================================ // Pat2H.h #ifndef __PAT2H__H #define __PAT2H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2H #define __AUTO_REMOVE #define __NODE_2_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_2_BITS #undef __HASH_3 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat2R.h ================================================ // Pat2R.h #ifndef __PAT2R__H #define __PAT2R__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat2R #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat2R #define __NODE_2_BITS #include "Pat.h" #include "PatMain.h" #undef __NODE_2_BITS #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat3H.h ================================================ // Pat3H.h #ifndef __PAT3H__H #define __PAT3H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat3H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat3H #define __AUTO_REMOVE #define __NODE_3_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_3_BITS #undef __HASH_3 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/Pat4H.h ================================================ // Pat4H.h #ifndef __PAT4H__H #define __PAT4H__H #undef PAT_CLSID #define PAT_CLSID CLSID_CMatchFinderPat4H #undef PAT_NAMESPACE #define PAT_NAMESPACE NPat4H #define __AUTO_REMOVE #define __NODE_4_BITS #define __HASH_3 #include "Pat.h" #include "PatMain.h" #undef __AUTO_REMOVE #undef __NODE_4_BITS #undef __HASH_3 #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/Patricia/PatMain.h ================================================ // PatMain.h #include "../../../../Common/Defs.h" #include "../../../../Common/Alloc.h" namespace PAT_NAMESPACE { STDMETHODIMP CPatricia::SetCallback(IMatchFinderCallback *callback) { m_Callback = callback; return S_OK; } void CPatricia::BeforeMoveBlock() { if (m_Callback) m_Callback->BeforeChangingBufferPos(); CLZInWindow::BeforeMoveBlock(); } void CPatricia::AfterMoveBlock() { if (m_Callback) m_Callback->AfterChangingBufferPos(); CLZInWindow::AfterMoveBlock(); } const UInt32 kMatchStartValue2 = 2; const UInt32 kDescendantEmptyValue2 = kMatchStartValue2 - 1; const UInt32 kDescendantsNotInitilized2 = kDescendantEmptyValue2 - 1; #ifdef __HASH_3 static const UInt32 kNumHashBytes = 3; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kNumHash2Bytes = 2; static const UInt32 kHash2Size = 1 << (8 * kNumHash2Bytes); static const UInt32 kPrevHashSize = kNumHash2Bytes; #else static const UInt32 kNumHashBytes = 2; static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); static const UInt32 kPrevHashSize = 0; #endif CPatricia::CPatricia(): m_HashDescendants(0), #ifdef __HASH_3 m_Hash2Descendants(0), #endif m_Nodes(0), m_TmpBacks(0) { } CPatricia::~CPatricia() { FreeMemory(); } void CPatricia::FreeMemory() { MyFree(m_TmpBacks); m_TmpBacks = 0; ::BigFree(m_Nodes); m_Nodes = 0; ::BigFree(m_HashDescendants); m_HashDescendants = 0; #ifdef __HASH_3 ::BigFree(m_Hash2Descendants); m_Hash2Descendants = 0; CLZInWindow::Free(); #endif } STDMETHODIMP CPatricia::Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { FreeMemory(); int kNumBitsInNumSameBits = sizeof(CSameBitsType) * 8; if (kNumBitsInNumSameBits < 32 && ((matchMaxLen * MY_BYTE_SIZE) > ((UInt32)1 << kNumBitsInNumSameBits))) return E_INVALIDARG; const UInt32 kAlignMask = (1 << 16) - 1; UInt32 windowReservSize = historySize; windowReservSize += kAlignMask; windowReservSize &= ~(kAlignMask); const UInt32 kMinReservSize = (1 << 19); if (windowReservSize < kMinReservSize) windowReservSize = kMinReservSize; windowReservSize += 256; if (!CLZInWindow::Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize)) return E_OUTOFMEMORY; _sizeHistory = historySize; _matchMaxLen = matchMaxLen; m_HashDescendants = (CDescendant *)BigAlloc(kHashSize * sizeof(CDescendant)); if (m_HashDescendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #ifdef __HASH_3 m_Hash2Descendants = (CDescendant *)BigAlloc(kHash2Size * sizeof(CDescendant)); if (m_Hash2Descendants == 0) { FreeMemory(); return E_OUTOFMEMORY; } #endif #ifdef __AUTO_REMOVE #ifdef __HASH_3 m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 19); #else m_NumNodes = historySize + _sizeHistory * 4 / 8 + (1 << 10); #endif #else UInt32 m_NumNodes = historySize; #endif const UInt32 kMaxNumNodes = UInt32(1) << (sizeof(CIndex) * 8 - 1); if (m_NumNodes + 32 > kMaxNumNodes) return E_INVALIDARG; // m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 2) * sizeof(CNode)); m_Nodes = (CNode *)::BigAlloc((m_NumNodes + 12) * sizeof(CNode)); if (m_Nodes == 0) { FreeMemory(); return E_OUTOFMEMORY; } m_TmpBacks = (UInt32 *)MyAlloc((_matchMaxLen + 1) * sizeof(UInt32)); if (m_TmpBacks == 0) { FreeMemory(); return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CPatricia::Init(ISequentialInStream *aStream) { RINOK(CLZInWindow::Init(aStream)); // memset(m_HashDescendants, 0xFF, kHashSize * sizeof(m_HashDescendants[0])); #ifdef __HASH_3 for (UInt32 i = 0; i < kHash2Size; i++) m_Hash2Descendants[i].MatchPointer = kDescendantsNotInitilized2; #else for (UInt32 i = 0; i < kHashSize; i++) m_HashDescendants[i].MakeEmpty(); #endif m_Nodes[0].NextFreeNode = 1; m_FreeNode = 0; m_FreeNodeMax = 0; #ifdef __AUTO_REMOVE m_NumUsedNodes = 0; #else m_SpecialRemoveMode = false; #endif m_SpecialMode = false; return S_OK; } STDMETHODIMP_(void) CPatricia::ReleaseStream() { // CLZInWindow::ReleaseStream(); } // pos = _pos + kNumHashBytes // fullCurrentLimit = currentLimit + kNumHashBytes // fullMatchLen = matchLen + kNumHashBytes void CPatricia::ChangeLastMatch(UInt32 hashValue) { UInt32 pos = _pos + kNumHashBytes - 1; UInt32 descendantIndex; const Byte *currentBytePointer = _buffer + pos; UInt32 numLoadedBits = 0; Byte curByte = 0; // = 0 to disable warning of GCC CNodePointer node = &m_Nodes[m_HashDescendants[hashValue].NodePointer]; while(true) { UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits < numSameBits) { numSameBits -= numLoadedBits; currentBytePointer += (numSameBits / MY_BYTE_SIZE); numSameBits %= MY_BYTE_SIZE; curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } curByte >>= numSameBits; numLoadedBits -= numSameBits; } if(numLoadedBits == 0) { curByte = *currentBytePointer++; numLoadedBits = MY_BYTE_SIZE; } descendantIndex = (curByte & kSubNodesMask); node->LastMatch = pos; numLoadedBits -= kNumSubBits; curByte >>= kNumSubBits; if(node->Descendants[descendantIndex].IsNode()) node = &m_Nodes[node->Descendants[descendantIndex].NodePointer]; else break; } node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; } UInt32 CPatricia::GetLongestMatch(UInt32 *distances) { UInt32 fullCurrentLimit; if (_pos + _matchMaxLen <= _streamPos) fullCurrentLimit = _matchMaxLen; else { fullCurrentLimit = _streamPos - _pos; if(fullCurrentLimit < kNumHashBytes) return 0; } UInt32 pos = _pos + kNumHashBytes; #ifdef __HASH_3 UInt32 hash2Value = ((UInt32(_buffer[_pos])) << 8) | _buffer[_pos + 1]; UInt32 hashValue = (hash2Value << 8) | _buffer[_pos + 2]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; if(hash2Descendant.MatchPointer <= kDescendantEmptyValue2) { if(hash2Descendant.MatchPointer == kDescendantsNotInitilized2) { UInt32 base = hashValue & 0xFFFF00; for (UInt32 i = 0; i < 0x100; i++) m_HashDescendants[base + i].MakeEmpty(); } hash2Descendant.MatchPointer = pos + kMatchStartValue2; hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } distances[kNumHash2Bytes] = pos - (hash2Descendant.MatchPointer - kMatchStartValue2) - 1; hash2Descendant.MatchPointer = pos + kMatchStartValue2; #ifdef __AUTO_REMOVE if (distances[kNumHash2Bytes] >= _sizeHistory) { if (hashDescendant.IsNode()) RemoveNode(hashDescendant.NodePointer); hashDescendant.MatchPointer = pos + kMatchStartValue; return 0; } #endif if (fullCurrentLimit == kNumHash2Bytes) return kNumHash2Bytes; #else UInt32 hashValue = UInt32(GetIndexByte(1)) | (UInt32(GetIndexByte(0)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(m_SpecialMode) { if(hashDescendant.IsMatch()) m_NumNotChangedCycles = 0; if(m_NumNotChangedCycles >= _sizeHistory - 1) { ChangeLastMatch(hashValue); m_NumNotChangedCycles = 0; } if(GetIndexByte(fullCurrentLimit - 1) == GetIndexByte(fullCurrentLimit - 2)) { if(hashDescendant.IsMatch()) hashDescendant.MatchPointer = pos + kMatchStartValue; else m_NumNotChangedCycles++; for(UInt32 i = kNumHashBytes; i <= fullCurrentLimit; i++) distances[i] = 0; return fullCurrentLimit; } else if(m_NumNotChangedCycles > 0) ChangeLastMatch(hashValue); m_SpecialMode = false; } if(hashDescendant.IsEmpty()) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } UInt32 currentLimit = fullCurrentLimit - kNumHashBytes; if(hashDescendant.IsMatch()) { CMatchPointer matchPointer = hashDescendant.MatchPointer; UInt32 backReal = pos - (matchPointer - kMatchStartValue); UInt32 back = backReal - 1; #ifdef __AUTO_REMOVE if (back >= _sizeHistory) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kPrevHashSize; } #endif UInt32 matchLen; distances += kNumHashBytes; Byte *buffer = _buffer + pos; for(matchLen = 0; true; matchLen++) { *distances++ = back; if (matchLen == currentLimit) { hashDescendant.MatchPointer = pos + kMatchStartValue; return kNumHashBytes + matchLen; } if (buffer[matchLen] != buffer[(size_t)matchLen - backReal]) break; } // UInt32 matchLen = GetMatchLen(kNumHashBytes, back, currentLimit); UInt32 fullMatchLen = matchLen + kNumHashBytes; hashDescendant.NodePointer = m_FreeNode; CNodePointer node = &m_Nodes[m_FreeNode]; m_FreeNode = node->NextFreeNode; #ifdef __AUTO_REMOVE m_NumUsedNodes++; #endif if (m_FreeNode > m_FreeNodeMax) { m_FreeNodeMax = m_FreeNode; m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1; } for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].NodePointer = kDescendantEmptyValue; node->LastMatch = pos; Byte byteNew = GetIndexByte(fullMatchLen); Byte byteOld = GetIndexByte(fullMatchLen - backReal); Byte bitsNew, bitsOld; UInt32 numSameBits = matchLen * MY_BYTE_SIZE; while (true) { bitsNew = (byteNew & kSubNodesMask); bitsOld = (byteOld & kSubNodesMask); if(bitsNew != bitsOld) break; byteNew >>= kNumSubBits; byteOld >>= kNumSubBits; numSameBits += kNumSubBits; } node->NumSameBits = CSameBitsType(numSameBits); node->Descendants[bitsNew].MatchPointer = pos + kMatchStartValue; node->Descendants[bitsOld].MatchPointer = matchPointer; return fullMatchLen; } const Byte *baseCurrentBytePointer = _buffer + pos; const Byte *currentBytePointer = baseCurrentBytePointer; UInt32 numLoadedBits = 0; Byte curByte = 0; CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[*nodePointerPointer]; distances += kNumHashBytes; const Byte *bytePointerLimit = baseCurrentBytePointer + currentLimit; const Byte *currentAddingOffset = _buffer; #ifdef __AUTO_REMOVE UInt32 lowPos; if (pos > _sizeHistory) lowPos = pos - _sizeHistory; else lowPos = 0; #endif while(true) { #ifdef __AUTO_REMOVE if (node->LastMatch < lowPos) { RemoveNode(*nodePointerPointer); *nodePointerPointer = pos + kMatchStartValue; if (currentBytePointer == baseCurrentBytePointer) return kPrevHashSize; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif if(numLoadedBits == 0) { *distances++ = pos - node->LastMatch - 1; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = 0; return fullCurrentLimit; } curByte = (*currentBytePointer++); currentAddingOffset++; numLoadedBits = MY_BYTE_SIZE; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { Byte byteXOR = ((*(currentAddingOffset + node->LastMatch -1)) >> (MY_BYTE_SIZE - numLoadedBits)) ^ curByte; while(numLoadedBits <= numSameBits) { if(byteXOR != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } *distances++ = pos - node->LastMatch - 1; numSameBits -= numLoadedBits; if(currentBytePointer >= bytePointerLimit) { for (UInt32 i = 0; i < kNumSubNodes; i++) node->Descendants[i].MatchPointer = pos + kMatchStartValue; node->LastMatch = pos; node->NumSameBits = CSameBitsType(node->NumSameBits - numSameBits); return fullCurrentLimit; } numLoadedBits = MY_BYTE_SIZE; curByte = (*currentBytePointer++); byteXOR = curByte ^ (*(currentAddingOffset + node->LastMatch)); currentAddingOffset++; } if((byteXOR & ((1 << numSameBits) - 1)) != 0) { AddInternalNode(node, nodePointerPointer, curByte, byteXOR, numSameBits, pos); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } curByte >>= numSameBits; numLoadedBits -= numSameBits; } UInt32 descendantIndex = (curByte & kSubNodesMask); numLoadedBits -= kNumSubBits; nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; UInt32 nextNodeIndex = *nodePointerPointer; node->LastMatch = pos; if (nextNodeIndex < kDescendantEmptyValue) { curByte >>= kNumSubBits; node = &m_Nodes[nextNodeIndex]; } else if (nextNodeIndex == kDescendantEmptyValue) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } else break; } UInt32 descendantIndex = (curByte & kSubNodesMask); curByte >>= kNumSubBits; CMatchPointer matchPointer = node->Descendants[descendantIndex].MatchPointer; CMatchPointer realMatchPointer; realMatchPointer = matchPointer - kMatchStartValue; #ifdef __AUTO_REMOVE if (realMatchPointer < lowPos) { node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } #endif Byte byteXOR; UInt32 numSameBits = 0; if(numLoadedBits != 0) { Byte matchByte = *(currentAddingOffset + realMatchPointer -1); matchByte >>= (MY_BYTE_SIZE - numLoadedBits); byteXOR = matchByte ^ curByte; if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } numSameBits += numLoadedBits; } const Byte *matchBytePointer = _buffer + realMatchPointer + (currentBytePointer - baseCurrentBytePointer); for(; currentBytePointer < bytePointerLimit; numSameBits += MY_BYTE_SIZE) { curByte = (*currentBytePointer++); *distances++ = pos - realMatchPointer - 1; byteXOR = curByte ^ (*matchBytePointer++); if(byteXOR != 0) { AddLeafNode(node, curByte, byteXOR, numSameBits, pos, descendantIndex); return kNumHashBytes + (UInt32)(currentBytePointer - baseCurrentBytePointer - 1); } } *distances = pos - realMatchPointer - 1; node->Descendants[descendantIndex].MatchPointer = pos + kMatchStartValue; if(*distances == 0) { m_SpecialMode = true; m_NumNotChangedCycles = 0; } return fullCurrentLimit; } STDMETHODIMP_(void) CPatricia::DummyLongestMatch() { GetLongestMatch(m_TmpBacks); } // ------------------------------------ // Remove Match typedef Byte CRemoveDataWord; static const int kSizeRemoveDataWordInBits = MY_BYTE_SIZE * sizeof(CRemoveDataWord); #ifndef __AUTO_REMOVE void CPatricia::RemoveMatch() { if(m_SpecialRemoveMode) { if(GetIndexByte(_matchMaxLen - 1 - _sizeHistory) == GetIndexByte(_matchMaxLen - _sizeHistory)) return; m_SpecialRemoveMode = false; } UInt32 pos = _pos + kNumHashBytes - _sizeHistory; #ifdef __HASH_3 const Byte *pp = _buffer + _pos - _sizeHistory; UInt32 hash2Value = ((UInt32(pp[0])) << 8) | pp[1]; UInt32 hashValue = (hash2Value << 8) | pp[2]; CDescendant &hashDescendant = m_HashDescendants[hashValue]; CDescendant &hash2Descendant = m_Hash2Descendants[hash2Value]; if (hash2Descendant >= kMatchStartValue2) if(hash2Descendant.MatchPointer == pos + kMatchStartValue2) hash2Descendant.MatchPointer = kDescendantEmptyValue2; #else UInt32 hashValue = UInt32(GetIndexByte(1 - _sizeHistory)) | (UInt32(GetIndexByte(0 - _sizeHistory)) << 8); CDescendant &hashDescendant = m_HashDescendants[hashValue]; #endif if(hashDescendant.IsEmpty()) return; if(hashDescendant.IsMatch()) { if(hashDescendant.MatchPointer == pos + kMatchStartValue) hashDescendant.MakeEmpty(); return; } UInt32 descendantIndex; const CRemoveDataWord *currentPointer = (const CRemoveDataWord *)(_buffer + pos); UInt32 numLoadedBits = 0; CRemoveDataWord curWord = 0; // = 0 to disable GCC warning CIndex *nodePointerPointer = &hashDescendant.NodePointer; CNodePointer node = &m_Nodes[hashDescendant.NodePointer]; while(true) { if(numLoadedBits == 0) { curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } UInt32 numSameBits = node->NumSameBits; if(numSameBits > 0) { if (numLoadedBits <= numSameBits) { numSameBits -= numLoadedBits; currentPointer += (numSameBits / kSizeRemoveDataWordInBits); numSameBits %= kSizeRemoveDataWordInBits; curWord = *currentPointer++; numLoadedBits = kSizeRemoveDataWordInBits; } curWord >>= numSameBits; numLoadedBits -= numSameBits; } descendantIndex = (curWord & kSubNodesMask); numLoadedBits -= kNumSubBits; curWord >>= kNumSubBits; UInt32 nextNodeIndex = node->Descendants[descendantIndex].NodePointer; if (nextNodeIndex < kDescendantEmptyValue) { nodePointerPointer = &node->Descendants[descendantIndex].NodePointer; node = &m_Nodes[nextNodeIndex]; } else break; } if (node->Descendants[descendantIndex].MatchPointer != pos + kMatchStartValue) { const Byte *currentBytePointer = _buffer + _pos - _sizeHistory; const Byte *currentBytePointerLimit = currentBytePointer + _matchMaxLen; for(;currentBytePointer < currentBytePointerLimit; currentBytePointer++) if(*currentBytePointer != *(currentBytePointer+1)) return; m_SpecialRemoveMode = true; return; } UInt32 numNodes = 0, numMatches = 0; UInt32 i; for (i = 0; i < kNumSubNodes; i++) { UInt32 nodeIndex = node->Descendants[i].NodePointer; if (nodeIndex < kDescendantEmptyValue) numNodes++; else if (nodeIndex > kDescendantEmptyValue) numMatches++; } numMatches -= 1; if (numNodes + numMatches > 1) { node->Descendants[descendantIndex].MakeEmpty(); return; } if(numNodes == 1) { UInt32 i; for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsNode()) break; UInt32 nextNodeIndex = node->Descendants[i].NodePointer; CNodePointer nextNode = &m_Nodes[nextNodeIndex]; nextNode->NumSameBits += node->NumSameBits + kNumSubBits; *node = *nextNode; nextNode->NextFreeNode = m_FreeNode; m_FreeNode = nextNodeIndex; return; } UInt32 matchPointer = 0; // = 0 to disable GCC warning for (i = 0; i < kNumSubNodes; i++) if (node->Descendants[i].IsMatch() && i != descendantIndex) { matchPointer = node->Descendants[i].MatchPointer; break; } node->NextFreeNode = m_FreeNode; m_FreeNode = *nodePointerPointer; *nodePointerPointer = matchPointer; } #endif // Commented code is more correct, but it gives warning // on GCC: (1 << 32) // So we use kMatchStartValue twice: // kMatchStartValue = UInt32(1) << (kNumBitsInIndex - 1); // must be defined in Pat.h /* const UInt32 kNormalizeStartPos = (UInt32(1) << (kNumBitsInIndex)) - kMatchStartValue - kNumHashBytes - 1; */ const UInt32 kNormalizeStartPos = kMatchStartValue - kNumHashBytes - 1; STDMETHODIMP CPatricia::MovePos() { #ifndef __AUTO_REMOVE if(_pos >= _sizeHistory) RemoveMatch(); #endif RINOK(CLZInWindow::MovePos()); #ifdef __AUTO_REMOVE if (m_NumUsedNodes >= m_NumNodes) TestRemoveNodes(); #endif if (_pos >= kNormalizeStartPos) { #ifdef __AUTO_REMOVE TestRemoveNodesAndNormalize(); #else Normalize(); #endif } return S_OK; } #ifndef __AUTO_REMOVE void CPatricia::NormalizeDescendant(CDescendant &descendant, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) descendant.MatchPointer = descendant.MatchPointer - subValue; else { CNode &node = m_Nodes[descendant.NodePointer]; node.LastMatch = node.LastMatch - subValue; for (UInt32 i = 0; i < kNumSubNodes; i++) NormalizeDescendant(node.Descendants[i], subValue); } } void CPatricia::Normalize() { UInt32 subValue = _pos - _sizeHistory; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) NormalizeDescendant(m_HashDescendants[base + i], subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) NormalizeDescendant(m_HashDescendants[hash], subValue); #endif } #else void CPatricia::TestRemoveDescendant(CDescendant &descendant, UInt32 limitPos) { CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsEmpty()) continue; if (descendant2.IsMatch()) { if (descendant2.MatchPointer < limitPos) descendant2.MakeEmpty(); else { numChilds++; childIndex = i; } } else { TestRemoveDescendant(descendant2, limitPos); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } } if (numChilds > 1) return; CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::RemoveNode(UInt32 index) { CNode &node = m_Nodes[index]; for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; if (descendant2.IsNode()) RemoveNode(descendant2.NodePointer); } node.NextFreeNode = m_FreeNode; m_FreeNode = index; m_NumUsedNodes--; } void CPatricia::TestRemoveNodes() { UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) { CDescendant &descendant = m_HashDescendants[base + i]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) { CDescendant &descendant = m_HashDescendants[hash]; if (descendant.IsEmpty()) continue; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); } else TestRemoveDescendant(descendant, limitPos); } #endif } void CPatricia::TestRemoveAndNormalizeDescendant(CDescendant &descendant, UInt32 limitPos, UInt32 subValue) { if (descendant.IsEmpty()) return; if (descendant.IsMatch()) { if (descendant.MatchPointer < limitPos) descendant.MakeEmpty(); else descendant.MatchPointer = descendant.MatchPointer - subValue; return; } CNode &node = m_Nodes[descendant.NodePointer]; UInt32 numChilds = 0; UInt32 childIndex = 0; // = 0 to disable GCC warning for (UInt32 i = 0; i < kNumSubNodes; i++) { CDescendant &descendant2 = node.Descendants[i]; TestRemoveAndNormalizeDescendant(descendant2, limitPos, subValue); if (!descendant2.IsEmpty()) { numChilds++; childIndex = i; } } if (numChilds > 1) { node.LastMatch = node.LastMatch - subValue; return; } CIndex nodePointerTemp = descendant.NodePointer; if (numChilds == 1) { const CDescendant &descendant2 = node.Descendants[childIndex]; if (descendant2.IsNode()) m_Nodes[descendant2.NodePointer].NumSameBits += node.NumSameBits + kNumSubBits; descendant = descendant2; } else descendant.MakeEmpty(); node.NextFreeNode = m_FreeNode; m_FreeNode = nodePointerTemp; m_NumUsedNodes--; } void CPatricia::TestRemoveNodesAndNormalize() { UInt32 subValue = _pos - _sizeHistory; UInt32 limitPos = kMatchStartValue + _pos - _sizeHistory + kNumHashBytes; CLZInWindow::ReduceOffsets(subValue); #ifdef __HASH_3 UInt32 limitPos2 = kMatchStartValue2 + _pos - _sizeHistory + kNumHashBytes; for(UInt32 hash = 0; hash < kHash2Size; hash++) { CDescendant &descendant = m_Hash2Descendants[hash]; if (descendant.MatchPointer != kDescendantsNotInitilized2) { UInt32 base = hash << 8; for (UInt32 i = 0; i < 0x100; i++) TestRemoveAndNormalizeDescendant(m_HashDescendants[base + i], limitPos, subValue); } if (descendant.MatchPointer < kMatchStartValue2) continue; if (descendant.MatchPointer < limitPos2) descendant.MatchPointer = kDescendantEmptyValue2; else descendant.MatchPointer = descendant.MatchPointer - subValue; } #else for(UInt32 hash = 0; hash < kHashSize; hash++) TestRemoveAndNormalizeDescendant(m_HashDescendants[hash], limitPos, subValue); #endif } #endif STDMETHODIMP_(Byte) CPatricia::GetIndexByte(Int32 index) { return CLZInWindow::GetIndexByte(index); } STDMETHODIMP_(UInt32) CPatricia::GetMatchLen(Int32 index, UInt32 back, UInt32 limit) { return CLZInWindow::GetMatchLen(index, back, limit); } STDMETHODIMP_(UInt32) CPatricia::GetNumAvailableBytes() { return CLZInWindow::GetNumAvailableBytes(); } STDMETHODIMP_(const Byte *) CPatricia::GetPointerToCurrentPos() { return CLZInWindow::GetPointerToCurrentPos(); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZ/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/LZMA.h ================================================ // LZMA.h #ifndef __LZMA_H #define __LZMA_H namespace NCompress { namespace NLZMA { const UInt32 kNumRepDistances = 4; const int kNumStates = 12; const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; class CState { public: Byte Index; void Init() { Index = 0; } void UpdateChar() { Index = kLiteralNextStates[Index]; } void UpdateMatch() { Index = kMatchNextStates[Index]; } void UpdateRep() { Index = kRepNextStates[Index]; } void UpdateShortRep() { Index = kShortRepNextStates[Index]; } bool IsCharState() const { return Index < 7; } }; const int kNumPosSlotBits = 6; const int kDicLogSizeMin = 0; const int kDicLogSizeMax = 32; const int kDistTableSizeMax = kDicLogSizeMax * 2; const UInt32 kNumLenToPosStates = 4; inline UInt32 GetLenToPosState(UInt32 len) { len -= 2; if (len < kNumLenToPosStates) return len; return kNumLenToPosStates - 1; } namespace NLength { const int kNumPosStatesBitsMax = 4; const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); const int kNumPosStatesBitsEncodingMax = 4; const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); const int kNumLowBits = 3; const int kNumMidBits = 3; const int kNumHighBits = 8; const UInt32 kNumLowSymbols = 1 << kNumLowBits; const UInt32 kNumMidSymbols = 1 << kNumMidBits; const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); } const UInt32 kMatchMinLen = 2; const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; const int kNumAlignBits = 4; const UInt32 kAlignTableSize = 1 << kNumAlignBits; const UInt32 kAlignMask = (kAlignTableSize - 1); const UInt32 kStartPosModelIndex = 4; const UInt32 kEndPosModelIndex = 14; const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); const int kNumLitPosStatesBitsEncodingMax = 4; const int kNumLitContextBitsMax = 8; const int kNumMoveBits = 5; }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp ================================================ // LZMADecoder.cpp #include "StdAfx.h" #include "LZMADecoder.h" #include "../../../Common/Defs.h" namespace NCompress { namespace NLZMA { const int kLenIdFinished = -1; const int kLenIdNeedInit = -2; void CDecoder::Init() { { for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } } { for (UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotDecoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posDecoders[i].Init(); } _posAlignDecoder.Init(); _lenDecoder.Init(_posStateMask + 1); _repMatchLenDecoder.Init(_posStateMask + 1); _literalDecoder.Init(); _state.Init(); _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; } HRESULT CDecoder::CodeSpec(UInt32 curSize) { if (_outSizeDefined) { const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); if (curSize > rem) curSize = (UInt32)rem; } if (_remainLen == kLenIdFinished) return S_OK; if (_remainLen == kLenIdNeedInit) { _rangeDecoder.Init(); Init(); _remainLen = 0; } if (curSize == 0) return S_OK; UInt32 rep0 = _reps[0]; UInt32 rep1 = _reps[1]; UInt32 rep2 = _reps[2]; UInt32 rep3 = _reps[3]; CState state = _state; Byte previousByte; while(_remainLen > 0 && curSize > 0) { previousByte = _outWindowStream.GetByte(rep0); _outWindowStream.PutByte(previousByte); _remainLen--; curSize--; } UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); if (nowPos64 == 0) previousByte = 0; else previousByte = _outWindowStream.GetByte(0); while(curSize > 0) { { #ifdef _NO_EXCEPTIONS if (_rangeDecoder.Stream.ErrorCode != S_OK) return _rangeDecoder.Stream.ErrorCode; #endif if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; UInt32 posState = UInt32(nowPos64) & _posStateMask; if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) { if(!state.IsCharState()) previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); else previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, (UInt32)nowPos64, previousByte); _outWindowStream.PutByte(previousByte); state.UpdateChar(); curSize--; nowPos64++; } else { UInt32 len; if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) { len = 0; if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) { if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) { state.UpdateShortRep(); len = 1; } } else { UInt32 distance; if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) distance = rep1; else { if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; state.UpdateRep(); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); state.UpdateMatch(); UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); if (posSlot >= kStartPosModelIndex) { UInt32 numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); else { rep0 += (_rangeDecoder.DecodeDirectBits( numDirectBits - kNumAlignBits) << kNumAlignBits); rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); if (rep0 == 0xFFFFFFFF) { _remainLen = kLenIdFinished; return S_OK; } } } else rep0 = posSlot; } UInt32 locLen = len; if (len > curSize) locLen = (UInt32)curSize; if (!_outWindowStream.CopyBlock(rep0, locLen)) return S_FALSE; previousByte = _outWindowStream.GetByte(0); curSize -= locLen; nowPos64 += locLen; len -= locLen; if (len != 0) { _remainLen = (Int32)len; break; } #ifdef _NO_EXCEPTIONS if (_outWindowStream.ErrorCode != S_OK) return _outWindowStream.ErrorCode; #endif } } } if (_rangeDecoder.Stream.WasFinished()) return S_FALSE; _reps[0] = rep0; _reps[1] = rep1; _reps[2] = rep2; _reps[3] = rep3; _state = state; return S_OK; } STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *, const UInt64 *outSize, ICompressProgressInfo *progress) { SetInStream(inStream); _outWindowStream.SetStream(outStream); SetOutStreamSize(outSize); CDecoderFlusher flusher(this); while (true) { UInt32 curSize = 1 << 18; RINOK(CodeSpec(curSize)); if (_remainLen == kLenIdFinished) break; if (progress != NULL) { UInt64 inSize = _rangeDecoder.GetProcessedSize(); UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); } if (_outSizeDefined) if (_outWindowStream.GetProcessedSize() >= _outSize) break; } flusher.NeedFlush = false; return Flush(); } #ifdef _NO_EXCEPTIONS #define LZMA_TRY_BEGIN #define LZMA_TRY_END #else #define LZMA_TRY_BEGIN try { #define LZMA_TRY_END } \ catch(const CInBufferException &e) { return e.ErrorCode; } \ catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ catch(...) { return S_FALSE; } #endif STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { LZMA_TRY_BEGIN return CodeReal(inStream, outStream, inSize, outSize, progress); LZMA_TRY_END } STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) { if (size < 5) return E_INVALIDARG; int lc = properties[0] % 9; Byte remainder = (Byte)(properties[0] / 9); int lp = remainder % 5; int pb = remainder / 5; UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); return SetDecoderPropertiesRaw(lc, lp, pb, dictionarySize); } STDMETHODIMP CDecoder::SetDecoderPropertiesRaw(int lc, int lp, int pb, UInt32 dictionarySize) { if (pb > NLength::kNumPosStatesBitsMax) return E_INVALIDARG; _posStateMask = (1 << pb) - 1; if (!_outWindowStream.Create(dictionarySize)) return E_OUTOFMEMORY; if (!_literalDecoder.Create(lp, lc)) return E_OUTOFMEMORY; if (!_rangeDecoder.Create(1 << 20)) return E_OUTOFMEMORY; return S_OK; } STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _rangeDecoder.GetProcessedSize(); return S_OK; } STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _rangeDecoder.SetStream(inStream); return S_OK; } STDMETHODIMP CDecoder::ReleaseInStream() { _rangeDecoder.ReleaseStream(); return S_OK; } STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) { if (_outSizeDefined = (outSize != NULL)) _outSize = *outSize; _remainLen = kLenIdNeedInit; _outWindowStream.Init(); return S_OK; } #ifdef _ST_MODE STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { LZMA_TRY_BEGIN if (processedSize) *processedSize = 0; const UInt64 startPos = _outWindowStream.GetProcessedSize(); _outWindowStream.SetMemStream((Byte *)data); RINOK(CodeSpec(size)); if (processedSize) *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); return Flush(); LZMA_TRY_END } #endif }} ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/LZMADecoder.h ================================================ // LZMA/Decoder.h #ifndef __LZMA_DECODER_H #define __LZMA_DECODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/LZOutWindow.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder; class CLiteralDecoder2 { CMyBitDecoder _decoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _decoders[i].Init(); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) { UInt32 symbol = 1; RC_INIT_VAR do { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) { UInt32 symbol = 1; RC_INIT_VAR do { UInt32 matchBit = (matchByte >> 7) & 1; matchByte <<= 1; // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); // symbol = (symbol << 1) | bit; UInt32 bit; RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, bit = 0, bit = 1) if (matchBit != bit) { while (symbol < 0x100) { // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) } break; } } while (symbol < 0x100); RC_FLUSH_VAR return (Byte)symbol; } }; class CLiteralDecoder { CLiteralDecoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralDecoder(): _coders(0) {} ~CLiteralDecoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; namespace NLength { class CDecoder { CMyBitDecoder _choice; CMyBitDecoder _choice2; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) { if(_choice.Decode(rangeDecoder) == 0) return _lowCoder[posState].Decode(rangeDecoder); if(_choice2.Decode(rangeDecoder) == 0) return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); } }; } class CDecoder: public ICompressCoder, public ICompressSetDecoderProperties2, #ifdef _ST_MODE public ICompressSetInStream, public ICompressSetOutStreamSize, public ISequentialInStream, #endif public CMyUnknownImp { CLZOutWindow _outWindowStream; NRangeCoder::CDecoder _rangeDecoder; CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; CMyBitDecoder _isRep[kNumStates]; CMyBitDecoder _isRepG0[kNumStates]; CMyBitDecoder _isRepG1[kNumStates]; CMyBitDecoder _isRepG2[kNumStates]; CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates]; CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder; NLength::CDecoder _lenDecoder; NLength::CDecoder _repMatchLenDecoder; CLiteralDecoder _literalDecoder; UInt32 _posStateMask; /////////////////// // State UInt32 _reps[4]; CState _state; Int32 _remainLen; // -1 means end of stream. // -2 means need Init UInt64 _outSize; bool _outSizeDefined; void Init(); HRESULT CodeSpec(UInt32 size); public: #ifdef _ST_MODE MY_UNKNOWN_IMP4( ICompressSetDecoderProperties2, ICompressSetInStream, ICompressSetOutStreamSize, ISequentialInStream) #else MY_UNKNOWN_IMP1( ICompressSetDecoderProperties2) #endif void ReleaseStreams() { _outWindowStream.ReleaseStream(); ReleaseInStream(); } class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(); } }; HRESULT Flush() { return _outWindowStream.Flush(); } STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); STDMETHOD(SetDecoderPropertiesRaw)(int lc, int lp, int pb, UInt32 dictionarySize); STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); #ifdef _ST_MODE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); #endif CDecoder(): _outSizeDefined(false) {} virtual ~CDecoder() {} }; }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp ================================================ // LZMA/Encoder.cpp #include "StdAfx.h" #include "../../../Common/Defs.h" #include "../../Common/StreamUtils.h" #include "LZMAEncoder.h" // for minimal compressing code size define these: // #define COMPRESS_MF_BT // #define COMPRESS_MF_BT4 #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC) #define COMPRESS_MF_BT #define COMPRESS_MF_PAT #define COMPRESS_MF_HC #endif #ifdef COMPRESS_MF_BT #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B) #define COMPRESS_MF_BT2 #define COMPRESS_MF_BT3 #define COMPRESS_MF_BT4 #define COMPRESS_MF_BT4B #endif #ifdef COMPRESS_MF_BT2 #include "../LZ/BinTree/BinTree2.h" #endif #ifdef COMPRESS_MF_BT3 #include "../LZ/BinTree/BinTree3.h" #endif #ifdef COMPRESS_MF_BT4 #include "../LZ/BinTree/BinTree4.h" #endif #ifdef COMPRESS_MF_BT4B #include "../LZ/BinTree/BinTree4b.h" #endif #endif #ifdef COMPRESS_MF_PAT #include "../LZ/Patricia/Pat2.h" #include "../LZ/Patricia/Pat2H.h" #include "../LZ/Patricia/Pat3H.h" #include "../LZ/Patricia/Pat4H.h" #include "../LZ/Patricia/Pat2R.h" #endif #ifdef COMPRESS_MF_HC #include "../LZ/HashChain/HC3.h" #include "../LZ/HashChain/HC4.h" #endif #ifdef COMPRESS_MF_MT #include "../LZ/MT/MT.h" #endif namespace NCompress { namespace NLZMA { const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; enum { kBT2, kBT3, kBT4, kBT4B, kPat2, kPat2H, kPat3H, kPat4H, kPat2R, kHC3, kHC4 }; static const wchar_t *kMatchFinderIDs[] = { L"BT2", L"BT3", L"BT4", L"BT4B", L"PAT2", L"PAT2H", L"PAT3H", L"PAT4H", L"PAT2R", L"HC3", L"HC4" }; Byte g_FastPos[1024]; class CFastPosInit { public: CFastPosInit() { Init(); } void Init() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = (1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } } g_FastPosInit; void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } while(i != 0); } void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol) { UInt32 context = 1; int i = 8; do { i--; UInt32 bit = (symbol >> i) & 1; UInt32 matchBit = (matchByte >> i) & 1; _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); context = (context << 1) | bit; if (matchBit != bit) { while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; _encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } break; } } while(i != 0); } UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const { UInt32 price = 0; UInt32 context = 1; int i = 8; if (matchMode) { do { i--; UInt32 matchBit = (matchByte >> i) & 1; UInt32 bit = (symbol >> i) & 1; price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) break; } while (i != 0); } while(i != 0) { i--; UInt32 bit = (symbol >> i) & 1; price += _encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; }; namespace NLength { void CEncoder::Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { if(symbol < kNumLowSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { _choice.Encode(rangeEncoder, 1); if(symbol < kNumLowSymbols + kNumMidSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); } } } UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const { if(symbol < kNumLowSymbols) return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol); UInt32 price = _choice.GetPrice1(); if(symbol < kNumLowSymbols + kNumMidSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols); } return price; } } CEncoder::CEncoder(): _numFastBytes(kNumFastBytesDefault), _distTableSize(kDefaultDictionaryLogSize * 2), _posStateBits(2), _posStateMask(4 - 1), _numLiteralPosStateBits(0), _numLiteralContextBits(3), _dictionarySize(1 << kDefaultDictionaryLogSize), _dictionarySizePrev(UInt32(-1)), _numFastBytesPrev(UInt32(-1)), _matchFinderIndex(kBT4), #ifdef COMPRESS_MF_MT _multiThread(false), #endif _writeEndMark(false) { _maxMode = false; _fastMode = false; } HRESULT CEncoder::Create() { if (!_rangeEncoder.Create(1 << 20)) return E_OUTOFMEMORY; if (!_matchFinder) { switch(_matchFinderIndex) { #ifdef COMPRESS_MF_BT #ifdef COMPRESS_MF_BT2 case kBT2: _matchFinder = new NBT2::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT3 case kBT3: _matchFinder = new NBT3::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4 case kBT4: _matchFinder = new NBT4::CMatchFinderBinTree; break; #endif #ifdef COMPRESS_MF_BT4B case kBT4B: _matchFinder = new NBT4B::CMatchFinderBinTree; break; #endif #endif #ifdef COMPRESS_MF_PAT case kPat2: _matchFinder = new NPat2::CPatricia; break; case kPat2H: _matchFinder = new NPat2H::CPatricia; break; case kPat3H: _matchFinder = new NPat3H::CPatricia; break; case kPat4H: _matchFinder = new NPat4H::CPatricia; break; case kPat2R: _matchFinder = new NPat2R::CPatricia; break; #endif #ifdef COMPRESS_MF_HC case kHC3: _matchFinder = new NHC3::CMatchFinderHC; break; case kHC4: _matchFinder = new NHC4::CMatchFinderHC; break; #endif } if (_matchFinder == 0) return E_OUTOFMEMORY; #ifdef COMPRESS_MF_MT if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4))) { CMatchFinderMT *mfSpec = new CMatchFinderMT; if (mfSpec == 0) return E_OUTOFMEMORY; CMyComPtr<IMatchFinder> mf = mfSpec; RINOK(mfSpec->SetMatchFinder(_matchFinder)); _matchFinder.Release(); _matchFinder = mf; } #endif } if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) return E_OUTOFMEMORY; if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return S_OK; RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen * 2 + 1 - _numFastBytes)); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; return S_OK; } static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) { while (true) { wchar_t c = *testString; if (c >= 'a' && c <= 'z') c -= 0x20; if (*base != c) return false; if (c == 0) return true; base++; testString++; } } #include <stdio.h> static int FindMatchFinder(const wchar_t *s) { for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) if (AreStringsEqual(kMatchFinderIDs[m], s)) return m; return -1; } STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) { for (UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &prop = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumFastBytes: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 numFastBytes = prop.ulVal; if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) return E_INVALIDARG; _numFastBytes = numFastBytes; break; } case NCoderPropID::kAlgorithm: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 maximize = prop.ulVal; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case NCoderPropID::kMatchFinder: { if (prop.vt != VT_BSTR) return E_INVALIDARG; int matchFinderIndexPrev = _matchFinderIndex; int m = FindMatchFinder(prop.bstrVal); if (m < 0) return E_INVALIDARG; _matchFinderIndex = m; if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } break; } #ifdef COMPRESS_MF_MT case NCoderPropID::kMultiThread: { if (prop.vt != VT_BOOL) return E_INVALIDARG; bool newMultiThread = (prop.boolVal == VARIANT_TRUE); if (newMultiThread != _multiThread) { _dictionarySizePrev = UInt32(-1); _matchFinder.Release(); } _multiThread = newMultiThread; break; } #endif case NCoderPropID::kDictionarySize: { const int kDicLogSizeMaxCompress = 28; if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionarySize = prop.ulVal; if (dictionarySize < UInt32(1 << kDicLogSizeMin) || dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) return E_INVALIDARG; _dictionarySize = dictionarySize; UInt32 dicLogSize; for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= (UInt32(1) << dicLogSize)) break; _distTableSize = dicLogSize * 2; break; } case NCoderPropID::kPosStateBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) return E_INVALIDARG; _posStateBits = value; _posStateMask = (1 << _posStateBits) - 1; break; } case NCoderPropID::kLitPosBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) return E_INVALIDARG; _numLiteralPosStateBits = value; break; } case NCoderPropID::kLitContextBits: { if (prop.vt != VT_UI4) return E_INVALIDARG; UInt32 value = prop.ulVal; if (value > (UInt32)kNumLitContextBitsMax) return E_INVALIDARG; _numLiteralContextBits = value; break; } case NCoderPropID::kEndMarker: { if (prop.vt != VT_BOOL) return E_INVALIDARG; SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); break; } default: return E_INVALIDARG; } } return S_OK; } STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) { const UInt32 kPropSize = 5; Byte properties[kPropSize]; properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; for (int i = 0; i < 4; i++) properties[1 + i] = Byte(_dictionarySize >> (8 * i)); return WriteStream(outStream, properties, kPropSize, NULL); } STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) { _rangeEncoder.SetStream(outStream); return S_OK; } STDMETHODIMP CEncoder::ReleaseOutStream() { _rangeEncoder.ReleaseStream(); return S_OK; } HRESULT CEncoder::Init() { CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); // _repMatchLenEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK; } HRESULT CEncoder::MovePos(UInt32 num) { for (;num != 0; num--) { _matchFinder->DummyLongestMatch(); RINOK(_matchFinder->MovePos()); _additionalOffset++; } return S_OK; } UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } /* inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit) { back++; for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++); return i; } */ /* Out: (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal */ HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { if(_optimumEndIndex != _optimumCurrentIndex) { const COptimal &optimum = _optimum[_optimumCurrentIndex]; lenRes = optimum.PosPrev - _optimumCurrentIndex; backRes = optimum.BackPrev; _optimumCurrentIndex = optimum.PosPrev; return S_OK; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } Byte currentByte = _matchFinder->GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if(lenMain < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for(len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); COptimal &optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } position++; COptimal &curOptimum = _optimum[cur]; UInt32 posPrev = curOptimum.PosPrev; CState state; if (curOptimum.Prev1IsChar) { posPrev--; if (curOptimum.Prev2) { state = _optimum[curOptimum.PosPrev2].State; if (curOptimum.BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (curOptimum.IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); /* if (curOptimum.Prev1IsChar) for(int i = 0; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i]; */ } else { UInt32 pos; if (curOptimum.Prev1IsChar && curOptimum.Prev2) { posPrev = curOptimum.PosPrev2; pos = curOptimum.BackPrev2; state.UpdateRep(); } else { pos = curOptimum.BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } const COptimal &prevOptimum = _optimum[posPrev]; if (pos < kNumRepDistances) { reps[0] = prevOptimum.Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = prevOptimum.Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = prevOptimum.Backs[i - 1]; } } curOptimum.State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) curOptimum.Backs[i] = reps[i]; UInt32 newLen; RINOK(ReadMatchDistances(newLen)); if(newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } UInt32 curPrice = curOptimum.Price; // Byte currentByte = _matchFinder->GetIndexByte(0 - 1); // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice0() + _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { // try Literal + rep0 UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) if (data[temp] != data[(size_t)temp - backOffset]) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while(lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (data[lenTest] != data[(size_t)lenTest - backOffset]) break; UInt32 lenTestTemp = lenTest; do { while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { // Try Match + Literal + Rep0 UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (data[lenTest2] != data[(size_t)lenTest2 - backOffset]) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[state2.Index][posStateNext].GetPrice0() + _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1], true, data[(size_t)lenTest - backOffset], data[lenTest]); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + kNumRepDistances; } } } } } } } } static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif)); } HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes) { lenRes = _matchFinder->GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes], kMatchMaxLen - lenRes); _additionalOffset++; return _matchFinder->MovePos(); } HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) { UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; for(UInt32 i = 0; i < kNumRepDistances; i++) { repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if(repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } if(lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 1); } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12))) { backRes = repMaxIndex; lenRes = repLens[repMaxIndex]; return MovePos(lenRes - 1); } } if (lenMain >= 2) { RINOK(ReadMatchDistances(_longestMatchLength)); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } for(UInt32 i = 0; i < kNumRepDistances; i++) { UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = UInt32(-1); lenRes = 1; return S_OK; } } backRes = backMain + kNumRepDistances; lenRes = lenMain; return MovePos(lenMain - 2); } backRes = UInt32(-1); lenRes = 1; return S_OK; } STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder) { _matchFinder = matchFinder; return S_OK; } HRESULT CEncoder::Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); return _rangeEncoder.FlushStream(); } void CEncoder::WriteEndMarker(UInt32 posState) { // This function for writing End Mark for stream version of LZMA. // In current version this feature is not used. if (!_writeEndMark) return; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); UInt32 posSlot = (1 << kNumPosSlotBits) - 1; UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); UInt32 footerBits = 30; UInt32 posReduced = (UInt32(1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); } HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { _needReleaseMFStream = false; CCoderReleaser coderReleaser(this); RINOK(SetStreams(inStream, outStream, inSize, outSize)); while(true) { UInt64 processedInSize; UInt64 processedOutSize; Int32 finished; RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); if (finished != 0) return S_OK; if (progress != 0) { RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); } } } HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize) { _inStream = inStream; _finished = false; RINOK(Create()); RINOK(SetOutStream(outStream)); RINOK(Init()); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; return S_OK; } HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) { if (_inStream != 0) { RINOK(_matchFinder->Init(_inStream)); _needReleaseMFStream = true; _inStream = 0; } *finished = 1; if (_finished) return S_OK; _finished = true; UInt64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); UInt32 len; // it's not used RINOK(ReadMatchDistances(len)); UInt32 posState = UInt32(nowPos64) & _posStateMask; _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); while(true) { #ifdef _NO_EXCEPTIONS if (_rangeEncoder.Stream.ErrorCode != S_OK) return _rangeEncoder.Stream.ErrorCode; #endif UInt32 pos; UInt32 posState = UInt32(nowPos64) & _posStateMask; UInt32 len; HRESULT result; if (_fastMode) result = GetOptimumFast(UInt32(nowPos64), pos, len); else result = GetOptimum(UInt32(nowPos64), pos, len); RINOK(result); if(len == 1 && pos == 0xFFFFFFFF) { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte); if(!_state.IsCharState()) { Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); } else subCoder->Encode(&_rangeEncoder, curByte); _state.UpdateChar(); _previousByte = curByte; } else { _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); if(pos < kNumRepDistances) { _isRep[_state.Index].Encode(&_rangeEncoder, 1); if(pos == 0) { _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); if(len == 1) _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0); else _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for(UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(&_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState); pos -= kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); if (posSlot >= kStartPosModelIndex) { UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - base; if (posSlot < kEndPosModelIndex) NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, &_rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for(UInt32 i = kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { *inSize = nowPos64; *outSize = _rangeEncoder.GetProcessedSize(); if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(UInt32(nowPos64)); if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; *finished = 0; return S_OK; } } } } STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) { #ifndef _NO_EXCEPTIONS try { #endif return CodeReal(inStream, outStream, inSize, outSize, progress); #ifndef _NO_EXCEPTIONS } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return E_FAIL; } #endif } void CEncoder::FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); } } void CEncoder::FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < kStartPosModelIndex; i++) _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i]; for (; i < kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); UInt32 footerBits = ((posSlot >> 1) - 1); UInt32 base = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] + NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + base - posSlot - 1, footerBits, i - base); } } } void CEncoder::FillAlignPrices() { for (UInt32 i = 0; i < kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = kAlignTableSize; } }} ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h ================================================ // LZMA/Encoder.h #ifndef __LZMA_ENCODER_H #define __LZMA_ENCODER_H #include "../../../Common/MyCom.h" #include "../../../Common/Alloc.h" #include "../../ICoder.h" #include "../LZ/IMatchFinder.h" #include "../RangeCoder/RangeCoderBitTree.h" #include "LZMA.h" namespace NCompress { namespace NLZMA { typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder; class CBaseState { protected: CState _state; Byte _previousByte; UInt32 _repDistances[kNumRepDistances]; void Init() { _state.Init(); _previousByte = 0; for(UInt32 i = 0 ; i < kNumRepDistances; i++) _repDistances[i] = 0; } }; struct COptimal { CState State; bool Prev1IsChar; bool Prev2; UInt32 PosPrev2; UInt32 BackPrev2; UInt32 Price; UInt32 PosPrev; // posNext; UInt32 BackPrev; UInt32 Backs[kNumRepDistances]; void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } bool IsShortRep() { return (BackPrev == 0); } }; extern Byte g_FastPos[1024]; inline UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } inline UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } const UInt32 kIfinityPrice = 0xFFFFFFF; const UInt32 kNumOpts = 1 << 12; class CLiteralEncoder2 { CMyBitEncoder _encoders[0x300]; public: void Init() { for (int i = 0; i < 0x300; i++) _encoders[i].Init(); } void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; }; class CLiteralEncoder { CLiteralEncoder2 *_coders; int _numPrevBits; int _numPosBits; UInt32 _posMask; public: CLiteralEncoder(): _coders(0) {} ~CLiteralEncoder() { Free(); } void Free() { MyFree(_coders); _coders = 0; } bool Create(int numPosBits, int numPrevBits) { if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits) ) { Free(); UInt32 numStates = 1 << (numPosBits + numPrevBits); _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); } _numPosBits = numPosBits; _posMask = (1 << numPosBits) - 1; _numPrevBits = numPrevBits; return (_coders != 0); } void Init() { UInt32 numStates = 1 << (_numPrevBits + _numPosBits); for (UInt32 i = 0; i < numStates; i++) _coders[i].Init(); } UInt32 GetState(UInt32 pos, Byte prevByte) const { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) { return &_coders[GetState(pos, prevByte)]; } /* void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, symbol); } void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, UInt32 pos, Byte prevByte, Byte matchByte, Byte symbol) { _coders[GetState(pos, prevByte)].Encode(rangeEncoder, matchByte, symbol); } */ UInt32 GetPrice(UInt32 pos, Byte prevByte, bool matchMode, Byte matchByte, Byte symbol) const { return _coders[GetState(pos, prevByte)].GetPrice(matchMode, matchByte, symbol); } }; namespace NLength { class CEncoder { CMyBitEncoder _choice; CMyBitEncoder _choice2; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder; public: void Init(UInt32 numPosStates); void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); UInt32 GetPrice(UInt32 symbol, UInt32 posState) const; }; const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; class CPriceTableEncoder: public CEncoder { UInt32 _prices[kNumSymbolsTotal][kNumPosStatesEncodingMax]; UInt32 _tableSize; UInt32 _counters[kNumPosStatesEncodingMax]; public: void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[symbol][posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[len][posState] = CEncoder::GetPrice(len, posState); _counters[posState] = _tableSize; } void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) { CEncoder::Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } }; } class CEncoder : public ICompressCoder, public ICompressSetOutStream, public ICompressSetCoderProperties, public ICompressWriteCoderProperties, public CBaseState, public CMyUnknownImp { COptimal _optimum[kNumOpts]; CMyComPtr<IMatchFinder> _matchFinder; // test it NRangeCoder::CEncoder _rangeEncoder; CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; CMyBitEncoder _isRep[kNumStates]; CMyBitEncoder _isRepG0[kNumStates]; CMyBitEncoder _isRepG1[kNumStates]; CMyBitEncoder _isRepG2[kNumStates]; CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates]; CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder; NLength::CPriceTableEncoder _lenEncoder; NLength::CPriceTableEncoder _repMatchLenEncoder; CLiteralEncoder _literalEncoder; UInt32 _matchDistances[kMatchMaxLen + 1]; bool _fastMode; bool _maxMode; UInt32 _numFastBytes; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; UInt32 _alignPrices[kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize; UInt32 _posStateBits; UInt32 _posStateMask; UInt32 _numLiteralPosStateBits; UInt32 _numLiteralContextBits; UInt32 _dictionarySize; UInt32 _dictionarySizePrev; UInt32 _numFastBytesPrev; UInt64 lastPosSlotFillingPos; UInt64 nowPos64; bool _finished; ISequentialInStream *_inStream; int _matchFinderIndex; #ifdef COMPRESS_MF_MT bool _multiThread; #endif bool _writeEndMark; bool _needReleaseMFStream; HRESULT ReadMatchDistances(UInt32 &len); HRESULT MovePos(UInt32 num); UInt32 GetRepLen1Price(CState state, UInt32 posState) const { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[state.Index][posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const { UInt32 price = _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState); if(repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[state.Index][posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } /* UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const { if (pos >= kNumFullDistances) return kIfinityPrice; return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); } UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const { UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } */ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = GetLenToPosState(len); if (pos < kNumFullDistances) price = _distancesPrices[lenToPosState][pos]; else price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + _alignPrices[pos & kAlignMask]; return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); } UInt32 Backward(UInt32 &backRes, UInt32 cur); HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); void FillPosSlotPrices(); void FillDistancesPrices(); void FillAlignPrices(); void ReleaseMFStream() { if (_matchFinder && _needReleaseMFStream) { _matchFinder->ReleaseStream(); _needReleaseMFStream = false; } } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } HRESULT Flush(UInt32 nowPos); class CCoderReleaser { CEncoder *_coder; public: CCoderReleaser(CEncoder *coder): _coder(coder) {} ~CCoderReleaser() { _coder->ReleaseStreams(); } }; friend class CCoderReleaser; void WriteEndMarker(UInt32 posState); public: CEncoder(); void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark= writeEndMarker; } HRESULT Create(); MY_UNKNOWN_IMP3( ICompressSetOutStream, ICompressSetCoderProperties, ICompressWriteCoderProperties ) HRESULT Init(); // ICompressCoder interface HRESULT SetStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize); HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // ICompressCoder interface STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); // IInitMatchFinder interface STDMETHOD(InitMatchFinder)(IMatchFinder *matchFinder); // ICompressSetCoderProperties2 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties); // ICompressWriteCoderProperties STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); STDMETHOD(ReleaseOutStream)(); virtual ~CEncoder() {} }; }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp ================================================ # Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=AloneLZMA - Win32 DebugU !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") !MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "AloneLZMA - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseU" # PROP BASE Intermediate_Dir "ReleaseU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseU" # PROP Intermediate_Dir "ReleaseU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c # ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugU" # PROP BASE Intermediate_Dir "DebugU" # PROP BASE Ignore_Export_Lib 0 # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugU" # PROP Intermediate_Dir "DebugU" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c # ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept !ENDIF # Begin Target # Name "AloneLZMA - Win32 Release" # Name "AloneLZMA - Win32 Debug" # Name "AloneLZMA - Win32 ReleaseU" # Name "AloneLZMA - Win32 DebugU" # Begin Group "Spec" # PROP Default_Filter "" # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"StdAfx.h" # End Source File # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Compress" # PROP Default_Filter "" # Begin Group "LZMA" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA\LZMA.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMADecoder.h # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.cpp # End Source File # Begin Source File SOURCE=..\LZMA\LZMAEncoder.h # End Source File # End Group # Begin Group "RangeCoder" # PROP Default_Filter "" # Begin Source File SOURCE=..\RangeCoder\RangeCoder.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.cpp # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBit.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderBitTree.h # End Source File # Begin Source File SOURCE=..\RangeCoder\RangeCoderOpt.h # End Source File # End Group # Begin Group "LZ" # PROP Default_Filter "" # Begin Group "Pat" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\Patricia\Pat.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat2R.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat3H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\Pat4H.h # End Source File # Begin Source File SOURCE=..\LZ\Patricia\PatMain.h # End Source File # End Group # Begin Group "BT" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\BinTree\BinTree.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree2.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3Z.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree3ZMain.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTree4b.h # End Source File # Begin Source File SOURCE=..\LZ\BinTree\BinTreeMain.h # End Source File # End Group # Begin Group "HC" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZ\HashChain\HC.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC2.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC3.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HC4b.h # End Source File # Begin Source File SOURCE=..\LZ\HashChain\HCMain.h # End Source File # End Group # Begin Source File SOURCE=..\LZ\IMatchFinder.h # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZInWindow.h # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.cpp # End Source File # Begin Source File SOURCE=..\LZ\LZOutWindow.h # End Source File # End Group # Begin Group "Branch" # PROP Default_Filter "" # Begin Source File SOURCE=..\Branch\BranchX86.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\Branch\BranchX86.h # End Source File # End Group # Begin Group "LZMA_C" # PROP Default_Filter "" # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=..\LZMA_C\LzmaDecode.h # End Source File # End Group # End Group # Begin Group "Windows" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Windows\FileIO.cpp # End Source File # Begin Source File SOURCE=..\..\..\Windows\FileIO.h # End Source File # End Group # Begin Group "Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\..\Common\Alloc.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Alloc.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CommandLineParser.h # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\CRC.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Windows\Defs.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyCom.h # End Source File # Begin Source File SOURCE=..\..\..\Common\MyWindows.h # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\NewHandler.h # End Source File # Begin Source File SOURCE=..\..\..\Common\String.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\String.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringConvert.h # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\StringToInt.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Types.h # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.cpp # End Source File # Begin Source File SOURCE=..\..\..\Common\Vector.h # End Source File # End Group # Begin Group "7zip Common" # PROP Default_Filter "" # Begin Source File SOURCE=..\..\Common\FileStreams.cpp # End Source File # Begin Source File SOURCE=..\..\Common\FileStreams.h # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\InBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.cpp # End Source File # Begin Source File SOURCE=..\..\Common\OutBuffer.h # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.cpp # End Source File # Begin Source File SOURCE=..\..\Common\StreamUtils.h # End Source File # End Group # Begin Source File SOURCE=..\..\ICoder.h # End Source File # Begin Source File SOURCE=.\LzmaAlone.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.cpp # End Source File # Begin Source File SOURCE=.\LzmaBench.h # End Source File # Begin Source File SOURCE=.\LzmaRam.cpp # End Source File # Begin Source File SOURCE=.\LzmaRam.h # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.c # SUBTRACT CPP /YX /Yc /Yu # End Source File # Begin Source File SOURCE=.\LzmaRamDecode.h # End Source File # End Target # End Project ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp ================================================ // LzmaAlone.cpp #include "StdAfx.h" #include "../../../Common/MyWindows.h" #include "../../../Common/MyInitGuid.h" #include <stdio.h> #if defined(_WIN32) || defined(OS2) || defined(MSDOS) #include <fcntl.h> #include <io.h> #define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) #else #define MY_SET_BINARY_MODE(file) #endif #include "../../../Common/CommandLineParser.h" #include "../../../Common/StringConvert.h" #include "../../../Common/StringToInt.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaBench.h" #include "LzmaRam.h" extern "C" { #include "LzmaRamDecode.h" } using namespace NCommandLineParser; #ifdef _WIN32 bool g_IsNT = false; static inline bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif static const char *kCantAllocate = "Can not allocate memory"; static const char *kReadError = "Read error"; static const char *kWriteError = "Write error"; namespace NKey { enum Enum { kHelp1 = 0, kHelp2, kMode, kDictionary, kFastBytes, kLitContext, kLitPos, kPosBits, kMatchFinder, kEOS, kStdIn, kStdOut, kFilter86 }; } static const CSwitchForm kSwitchForms[] = { { L"?", NSwitchType::kSimple, false }, { L"H", NSwitchType::kSimple, false }, { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, { L"EOS", NSwitchType::kSimple, false }, { L"SI", NSwitchType::kSimple, false }, { L"SO", NSwitchType::kSimple, false }, { L"F86", NSwitchType::kSimple, false } }; static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); static void PrintHelp() { fprintf(stderr, "\nUsage: LZMA <e|d> inputFile outputFile [<switches>...]\n" " e: encode file\n" " d: decode file\n" " b: Benchmark\n" "<Switches>\n" " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" " -pb{N}: set number of pos bits - [0, 4], default: 2\n" " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, bt4b, pat2r, pat2,\n" " pat2h, pat3h, pat4h, hc3, hc4], default: bt4\n" " -eos: write End Of Stream marker\n" " -si: read data from stdin\n" " -so: write data to stdout\n" ); } static void PrintHelpAndExit(const char *s) { fprintf(stderr, "\nError: %s\n\n", s); PrintHelp(); throw -1; } static void IncorrectCommand() { PrintHelpAndExit("Incorrect command"); } static void WriteArgumentsToStringList(int numArguments, const char *arguments[], UStringVector &strings) { for(int i = 1; i < numArguments; i++) strings.Add(MultiByteToUnicodeString(arguments[i])); } static bool GetNumber(const wchar_t *s, UInt32 &value) { value = 0; if (MyStringLen(s) == 0) return false; const wchar_t *end; UInt64 res = ConvertStringToUInt64(s, &end); if (*end != L'\0') return false; if (res > 0xFFFFFFFF) return false; value = UInt32(res); return true; } int main2(int n, const char *args[]) { #ifdef _WIN32 g_IsNT = IsItWindowsNT(); #endif fprintf(stderr, "\nLZMA 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (n == 1) { PrintHelp(); return 0; } if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4) { fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); return 1; } UStringVector commandStrings; WriteArgumentsToStringList(n, args, commandStrings); CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { IncorrectCommand(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &command = nonSwitchStrings[paramIndex++]; bool dictionaryIsDefined = false; UInt32 dictionary = 1 << 21; if(parser[NKey::kDictionary].ThereIs) { UInt32 dicLog; if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) IncorrectCommand(); dictionary = 1 << dicLog; dictionaryIsDefined = true; } UString mf = L"BT4"; if (parser[NKey::kMatchFinder].ThereIs) mf = parser[NKey::kMatchFinder].PostStrings[0]; if (command.CompareNoCase(L"b") == 0) { const UInt32 kNumDefaultItereations = 10; UInt32 numIterations = kNumDefaultItereations; { if (paramIndex < nonSwitchStrings.Size()) if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) numIterations = kNumDefaultItereations; } return LzmaBenchmark(stderr, numIterations, dictionary, mf.CompareNoCase(L"BT4") == 0); } bool encodeMode = false; if (command.CompareNoCase(L"e") == 0) encodeMode = true; else if (command.CompareNoCase(L"d") == 0) encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[NKey::kStdIn].ThereIs; bool stdOutMode = parser[NKey::kStdOut].ThereIs; CMyComPtr<ISequentialInStream> inStream; CInFileStream *inStreamSpec = 0; if (stdInMode) { inStream = new CStdInFileStream; MY_SET_BINARY_MODE(stdin); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &inputName = nonSwitchStrings[paramIndex++]; inStreamSpec = new CInFileStream; inStream = inStreamSpec; if (!inStreamSpec->Open(GetSystemString(inputName))) { fprintf(stderr, "\nError: can not open input file %s\n", (const char *)GetOemString(inputName)); return 1; } } CMyComPtr<ISequentialOutStream> outStream; if (stdOutMode) { outStream = new CStdOutFileStream; MY_SET_BINARY_MODE(stdout); } else { if (paramIndex >= nonSwitchStrings.Size()) IncorrectCommand(); const UString &outputName = nonSwitchStrings[paramIndex++]; COutFileStream *outStreamSpec = new COutFileStream; outStream = outStreamSpec; if (!outStreamSpec->Create(GetSystemString(outputName), true)) { fprintf(stderr, "\nError: can not open output file %s\n", (const char *)GetOemString(outputName)); return 1; } } if (parser[NKey::kFilter86].ThereIs) { // -f86 switch is for x86 filtered mode: BCJ + LZMA. if (parser[NKey::kEOS].ThereIs || stdInMode) throw "Can not use stdin in this mode"; UInt64 fileSize; inStreamSpec->File.GetLength(fileSize); if (fileSize > 0xF0000000) throw "File is too big"; UInt32 inSize = (UInt32)fileSize; Byte *inBuffer = 0; if (inSize != 0) { inBuffer = (Byte *)MyAlloc((size_t)inSize); if (inBuffer == 0) throw kCantAllocate; } UInt32 processedSize; if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) throw "Can not read"; if ((UInt32)inSize != processedSize) throw "Read size error"; Byte *outBuffer = 0; size_t outSizeProcessed; if (encodeMode) { // we allocate 105% of original size for output buffer size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); if (outSize != 0) { outBuffer = (Byte *)MyAlloc((size_t)outSize); if (outBuffer == 0) throw kCantAllocate; } if (!dictionaryIsDefined) dictionary = 1 << 23; int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, dictionary, SZ_FILTER_AUTO); if (res != 0) { fprintf(stderr, "\nEncoder error = %d\n", (int)res); return 1; } } else { size_t outSize; if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) throw "data error"; if (outSize != 0) { outBuffer = (Byte *)MyAlloc(outSize); if (outBuffer == 0) throw kCantAllocate; } int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); if (res != 0) throw "LzmaDecoder error"; } if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) throw kWriteError; MyFree(outBuffer); MyFree(inBuffer); return 0; } UInt64 fileSize; if (encodeMode) { NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; if (!dictionaryIsDefined) dictionary = 1 << 23; UInt32 posStateBits = 2; UInt32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data UInt32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data UInt32 algorithm = 2; UInt32 numFastBytes = 128; bool eos = parser[NKey::kEOS].ThereIs || stdInMode; if(parser[NKey::kMode].ThereIs) if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) IncorrectCommand(); if(parser[NKey::kFastBytes].ThereIs) if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) IncorrectCommand(); if(parser[NKey::kLitContext].ThereIs) if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) IncorrectCommand(); if(parser[NKey::kLitPos].ThereIs) if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) IncorrectCommand(); if(parser[NKey::kPosBits].ThereIs) if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) IncorrectCommand(); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); /* NWindows::NCOM::CPropVariant properties[kNumProps]; properties[0] = UInt32(dictionary); properties[1] = UInt32(posStateBits); properties[2] = UInt32(litContextBits); properties[3] = UInt32(litPosBits); properties[4] = UInt32(algorithm); properties[5] = UInt32(numFastBytes); properties[6] = mf; properties[7] = eos; */ PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(dictionary); properties[1].ulVal = UInt32(posStateBits); properties[2].ulVal = UInt32(litContextBits); properties[3].ulVal = UInt32(litPosBits); properties[4].ulVal = UInt32(algorithm); properties[5].ulVal = UInt32(numFastBytes); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)mf; properties[7].vt = VT_BOOL; properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) IncorrectCommand(); encoderSpec->WriteCoderProperties(outStream); if (eos || stdInMode) fileSize = (UInt64)(Int64)-1; else inStreamSpec->File.GetLength(fileSize); for (int i = 0; i < 8; i++) { Byte b = Byte(fileSize >> (8 * i)); if (outStream->Write(&b, 1, 0) != S_OK) { fprintf(stderr, kWriteError); return 1; } } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr, "\nError: Can not allocate memory\n"); return 1; } else if (result != S_OK) { fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); return 1; } } else { NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; const UInt32 kPropertiesSize = 5; Byte properties[kPropertiesSize]; UInt32 processedSize; if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != kPropertiesSize) { fprintf(stderr, kReadError); return 1; } if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) { fprintf(stderr, "SetDecoderProperties error"); return 1; } fileSize = 0; for (int i = 0; i < 8; i++) { Byte b; if (inStream->Read(&b, 1, &processedSize) != S_OK) { fprintf(stderr, kReadError); return 1; } if (processedSize != 1) { fprintf(stderr, kReadError); return 1; } fileSize |= ((UInt64)b) << (8 * i); } if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { fprintf(stderr, "Decoder error"); return 1; } } return 0; } int main(int n, const char *args[]) { try { return main2(n, args); } catch(const char *s) { fprintf(stderr, "\nError: %s\n", s); return 1; } catch(...) { fprintf(stderr, "\nError\n"); return 1; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp ================================================ // LzmaBench.cpp #include "StdAfx.h" #include "LzmaBench.h" #ifndef _WIN32 #include <time.h> #endif #include "../../../Common/CRC.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" static const UInt32 kAdditionalSize = #ifdef _WIN32_WCE (1 << 20); #else (6 << 20); #endif static const UInt32 kCompressedAdditionalSize = (1 << 10); static const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public: CRandomGenerator() { Init(); } void Init() { A1 = 362436069; A2 = 521288629;} UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); } }; class CBitRandomGenerator { CRandomGenerator RG; UInt32 Value; int NumBits; public: void Init() { Value = 0; NumBits = 0; } UInt32 GetRnd(int numBits) { if (NumBits > numBits) { UInt32 result = Value & ((1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; UInt32 result = (Value << numBits); Value = RG.GetRnd(); result |= Value & ((1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG; UInt32 Pos; public: UInt32 BufferSize; Byte *Buffer; CBenchRandomGenerator(): Buffer(0) {} ~CBenchRandomGenerator() { delete []Buffer; } void Init() { RG.Init(); } void Set(UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd(len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } void Generate() { while(Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = Byte(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CBenchmarkInStream: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; UInt32 Pos; UInt32 Size; public: MY_UNKNOWN_IMP void Init(const Byte *data, UInt32 size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class CBenchmarkOutStream: public ISequentialOutStream, public CMyUnknownImp { UInt32 BufferSize; FILE *_f; public: UInt32 Pos; Byte *Buffer; CBenchmarkOutStream(): _f(0), Buffer(0) {} virtual ~CBenchmarkOutStream() { delete []Buffer; } void Init(FILE *f, UInt32 bufferSize) { delete []Buffer; Buffer = 0; Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; _f = f; } MY_UNKNOWN_IMP STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < BufferSize; i++) Buffer[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { fprintf(_f, "\nERROR: Buffer is full\n"); return E_FAIL; } return S_OK; } class CCrcOutStream: public ISequentialOutStream, public CMyUnknownImp { public: CCRC CRC; MY_UNKNOWN_IMP void Init() { CRC.Init(); } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { CRC.Update(data, size); if(processedSize != NULL) *processedSize = size; return S_OK; } static UInt64 GetTimeCount() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceCounter(&value)) return value.QuadPart; return GetTickCount(); #else return clock(); #endif } static UInt64 GetFreq() { #ifdef _WIN32 LARGE_INTEGER value; if (::QueryPerformanceFrequency(&value)) return value.QuadPart; return 1000; #else return CLOCKS_PER_SEC; #endif } struct CProgressInfo: public ICompressProgressInfo, public CMyUnknownImp { UInt64 ApprovedStart; UInt64 InSize; UInt64 Time; void Init() { InSize = 0; Time = 0; } MY_UNKNOWN_IMP STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); }; STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) { if (*inSize >= ApprovedStart && InSize == 0) { Time = ::GetTimeCount(); InSize = *inSize; } return S_OK; } static const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = GetFreq(); UInt64 elTime = elapsedTime; while(freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } /* static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } */ static void PrintRating(FILE *f, UInt64 rating) { fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000)); } static void PrintResults( FILE *f, UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024)); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(f, rating); } static void ThrowError(FILE *f, HRESULT result, const char *s) { fprintf(f, "\nError: "); if (result == E_ABORT) fprintf(f, "User break"); if (result == E_OUTOFMEMORY) fprintf(f, "Can not allocate memory"); else fprintf(f, s); fprintf(f, "\n"); } const wchar_t *bt2 = L"BT2"; const wchar_t *bt4 = L"BT4"; int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations == 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n"); return 1; } fprintf(f, "\n Compressing Decompressing\n\n"); NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream; CMyComPtr<ISequentialOutStream> propStream = propStreamSpec; propStreamSpec->Init(f, kMaxLzmaPropSize); PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kMatchFinder }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[0].ulVal = UInt32(dictionarySize); properties[1].vt = VT_BSTR; properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2; const UInt32 kBufferSize = dictionarySize + kAdditionalSize; const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) { fprintf(f, "\nError: Incorrect command\n"); return 1; } encoderSpec->WriteCoderProperties(propStream); CBenchRandomGenerator rg; rg.Init(); rg.Set(kBufferSize); rg.Generate(); CCRC crc; crc.Update(rg.Buffer, rg.BufferSize); CProgressInfo *progressInfoSpec = new CProgressInfo; CMyComPtr<ICompressProgressInfo> progressInfo = progressInfoSpec; progressInfoSpec->ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; for (UInt32 i = 0; i < numIterations; i++) { progressInfoSpec->Init(); CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; inStreamSpec->Init(rg.Buffer, rg.BufferSize); CMyComPtr<ISequentialInStream> inStream = inStreamSpec; CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream; outStreamSpec->Init(f, kCompressedBufferSize); CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo); UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time; UInt32 compressedSize = outStreamSpec->Pos; if(result != S_OK) { ThrowError(f, result, "Encoder Error"); return 1; } if (progressInfoSpec->InSize == 0) { fprintf(f, "\nError: Internal ERROR 1282\n"); return 1; } /////////////////////// // Decompressing CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec; UInt64 decodeTime; for (int j = 0; j < 2; j++) { inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); crcOutStreamSpec->Init(); if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK) { fprintf(f, "\nError: Set Decoder Properties Error\n"); return 1; } UInt64 outSize = kBufferSize; UInt64 startTime = ::GetTimeCount(); result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0); decodeTime = ::GetTimeCount() - startTime; if(result != S_OK) { ThrowError(f, result, "Decode Error"); return 1; } if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest()) { fprintf(f, "\nError: CRC Error\n"); return 1; } } UInt64 benchSize = kBufferSize - progressInfoSpec->InSize; PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); fprintf(f, "\n"); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } fprintf(f, "---------------------------------------------------\n"); PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); fprintf(f, " "); PrintResults(f, dictionarySize, isBT4, totalDecodeTime, kBufferSize * numIterations, true, totalCompressedSize); fprintf(f, " Average\n"); return 0; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h ================================================ // LzmaBench.h #ifndef __LzmaBench_h #define __LzmaBench_h #include <stdio.h> #include "../../../Common/Types.h" int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp ================================================ // LzmaRam.cpp #include "StdAfx.h" #include "../../../Common/Types.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #include "LzmaRam.h" extern "C" { #include "../Branch/BranchX86.h" } class CInStreamRam: public ISequentialInStream, public CMyUnknownImp { const Byte *Data; size_t Size; size_t Pos; public: MY_UNKNOWN_IMP void Init(const Byte *data, size_t size) { Data = data; Size = size; Pos = 0; } STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) { UInt32 remain = Size - Pos; if (size > remain) size = remain; for (UInt32 i = 0; i < size; i++) ((Byte *)data)[i] = Data[Pos + i]; Pos += size; if(processedSize != NULL) *processedSize = size; return S_OK; } class COutStreamRam: public ISequentialOutStream, public CMyUnknownImp { size_t Size; public: Byte *Data; size_t Pos; bool Overflow; void Init(Byte *data, size_t size) { Data = data; Size = size; Pos = 0; Overflow = false; } void SetPos(size_t pos) { Overflow = false; Pos = pos; } MY_UNKNOWN_IMP HRESULT WriteByte(Byte b) { if (Pos >= Size) { Overflow = true; return E_FAIL; } Data[Pos++] = b; return S_OK; } STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) { UInt32 i; for (i = 0; i < size && Pos < Size; i++) Data[Pos++] = ((const Byte *)data)[i]; if(processedSize != NULL) *processedSize = i; if (i != size) { Overflow = true; return E_FAIL; } return S_OK; } #define SZE_FAIL (1) #define SZE_OUTOFMEMORY (2) #define SZE_OUT_OVERFLOW (3) int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode) { #ifndef _NO_EXCEPTIONS try { #endif *outSizeProcessed = 0; const size_t kIdSize = 1; const size_t kLzmaPropsSize = 5; const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; if (outSize < kMinDestSize) return SZE_OUT_OVERFLOW; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kAlgorithm, NCoderPropID::kDictionarySize, NCoderPropID::kNumFastBytes, }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; properties[0].vt = VT_UI4; properties[1].vt = VT_UI4; properties[2].vt = VT_UI4; properties[0].ulVal = (UInt32)2; properties[1].ulVal = (UInt32)dictionarySize; properties[2].ulVal = (UInt32)64; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return 1; COutStreamRam *outStreamSpec = new COutStreamRam; if (outStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; CInStreamRam *inStreamSpec = new CInStreamRam; if (inStreamSpec == 0) return SZE_OUTOFMEMORY; CMyComPtr<ISequentialInStream> inStream = inStreamSpec; outStreamSpec->Init(outBuffer, outSize); if (outStreamSpec->WriteByte(0) != S_OK) return SZE_OUT_OVERFLOW; if (encoderSpec->WriteCoderProperties(outStream) != S_OK) return SZE_OUT_OVERFLOW; if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) return 1; int i; for (i = 0; i < 8; i++) { UInt64 t = (UInt64)(inSize); if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) return SZE_OUT_OVERFLOW; } Byte *filteredStream = 0; bool useFilter = (filterMode != SZ_FILTER_NO); if (useFilter) { if (inSize != 0) { filteredStream = (Byte *)MyAlloc(inSize); if (filteredStream == 0) return SZE_OUTOFMEMORY; memmove(filteredStream, inBuffer, inSize); } UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1); } UInt32 minSize = 0; int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; bool bestIsFiltered = false; int mainResult = 0; size_t startPos = outStreamSpec->Pos; for (i = 0; i < numPasses; i++) { if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) break; outStreamSpec->SetPos(startPos); bool curModeIsFiltered = false; if (useFilter && i == 0) curModeIsFiltered = true; if (numPasses > 1 && i == numPasses - 1) curModeIsFiltered = true; inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); mainResult = 0; if (lzmaResult == E_OUTOFMEMORY) { mainResult = SZE_OUTOFMEMORY; break; } if (i == 0 || outStreamSpec->Pos <= minSize) { minSize = outStreamSpec->Pos; bestIsFiltered = curModeIsFiltered; } if (outStreamSpec->Overflow) mainResult = SZE_OUT_OVERFLOW; else if (lzmaResult != S_OK) { mainResult = SZE_FAIL; break; } } *outSizeProcessed = outStreamSpec->Pos; if (bestIsFiltered) outBuffer[0] = 1; if (useFilter) MyFree(filteredStream); return mainResult; #ifndef _NO_EXCEPTIONS } catch(...) { return SZE_OUTOFMEMORY; } #endif } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h ================================================ // LzmaRam.h #ifndef __LzmaRam_h #define __LzmaRam_h #include <stdlib.h> #include "../../../Common/Types.h" /* LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. It uses .lzma format, but it writes one additional byte to .lzma file: 0: - no filter 1: - x86(BCJ) filter. To provide best compression ratio dictionarySize mustbe >= inSize LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. RAM Requirements: RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize FilterBlockSize = 0, if useFilter == false FilterBlockSize = inSize, if useFilter == true Return code: 0 - OK 1 - Unspecified Error 2 - Memory allocating error 3 - Output buffer OVERFLOW If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: 2 passes when FILTER_NO provides better compression. 3 passes when FILTER_YES provides better compression. */ enum ESzFilterMode { SZ_FILTER_NO, SZ_FILTER_YES, SZ_FILTER_AUTO }; int LzmaRamEncode( const Byte *inBuffer, size_t inSize, Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, UInt32 dictionarySize, ESzFilterMode filterMode); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c ================================================ /* LzmaRamDecode.c */ #include "LzmaRamDecode.h" #ifdef _SZ_ONE_DIRECTORY #include "LzmaDecode.h" #include "BranchX86.h" #else #include "../LZMA_C/LzmaDecode.h" #include "../Branch/BranchX86.h" #endif #define LZMA_PROPS_SIZE 14 #define LZMA_SIZE_OFFSET 6 int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize) { unsigned int i; if (inSize < LZMA_PROPS_SIZE) return 1; *outSize = 0; for(i = 0; i < sizeof(size_t); i++) *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); for(; i < 8; i++) if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) return 1; return 0; } #define SZE_DATA_ERROR (1) #define SZE_OUTOFMEMORY (2) int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)) { CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ int result; SizeT outSizeProcessedLoc; SizeT inProcessed; int useFilter; if (inSize < LZMA_PROPS_SIZE) return 1; useFilter = inBuffer[0]; *outSizeProcessed = 0; if (useFilter > 1) return 1; if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return 1; state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return SZE_OUTOFMEMORY; result = LzmaDecode(&state, inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, outBuffer, (SizeT)outSize, &outSizeProcessedLoc); freeFunc(state.Probs); if (result != LZMA_RESULT_OK) return 1; *outSizeProcessed = (size_t)outSizeProcessedLoc; if (useFilter == 1) { UInt32 _prevMask; UInt32 _prevPos; x86_Convert_Init(_prevMask, _prevPos); x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0); } return 0; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h ================================================ /* LzmaRamDecode.h */ #ifndef __LzmaRamDecode_h #define __LzmaRamDecode_h #include <stdlib.h> /* LzmaRamGetUncompressedSize: In: inBuffer - input data inSize - input data size Out: outSize - uncompressed size Return code: 0 - OK 1 - Error in headers */ int LzmaRamGetUncompressedSize( const unsigned char *inBuffer, size_t inSize, size_t *outSize); /* LzmaRamDecompress: In: inBuffer - input data inSize - input data size outBuffer - output data outSize - output size allocFunc - alloc function (can be malloc) freeFunc - free function (can be free) Out: outSizeProcessed - processed size Return code: 0 - OK 1 - Error in headers / data stream 2 - Memory allocating error Memory requirements depend from properties of LZMA stream. With default lzma settings it's about 16 KB. */ int LzmaRamDecompress( const unsigned char *inBuffer, size_t inSize, unsigned char *outBuffer, size_t outSize, size_t *outSizeProcessed, void * (*allocFunc)(size_t size), void (*freeFunc)(void *)); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp ================================================ // StdAfx.cpp #include "StdAfx.h" ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../../../Common/MyWindows.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/makefile ================================================ PROG = lzma.exe CFLAGS = $(CFLAGS) -I ../../../ LIBS = $(LIBS) oleaut32.lib user32.lib !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** LZMA_OBJS = \ $O\LzmaAlone.obj \ $O\LzmaBench.obj \ $O\LzmaRam.obj \ LZMA_OPT_OBJS = \ $O\LZMADecoder.obj \ $O\LZMAEncoder.obj \ COMMON_OBJS = \ $O\Alloc.obj \ $O\CRC.obj \ $O\CommandLineParser.obj \ $O\String.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\Vector.obj 7ZIP_COMMON_OBJS = \ $O\InBuffer.obj \ $O\OutBuffer.obj \ $O\StreamUtils.obj \ LZ_OBJS = \ $O\LZInWindow.obj \ $O\LZOutWindow.obj \ OBJS = \ $(LZMA_OBJS) \ $(LZMA_OPT_OBJS) \ $(COMMON_OBJS) \ $(7ZIP_COMMON_OBJS) \ $(LZ_OBJS) \ $O\LzmaRamDecode.obj \ $O\LzmaDecode.obj \ $O\FileStreams.obj \ $O\FileIO.obj \ $O\RangeCoderBit.obj \ $O\BranchX86.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $(LZMA_OBJS): $(*B).cpp $(COMPL) $(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp $(COMPL_O2) $(COMMON_OBJS): ../../../Common/$(*B).cpp $(COMPL) $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp $(COMPL) $(LZ_OBJS): ../LZ/$(*B).cpp $(COMPL) $O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp $(COMPL) $O\LzmaRamDecode.obj: LzmaRamDecode.c $(COMPL_O1) $O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c $(COMPL_O2) $O\BranchX86.obj: ../Branch/BranchX86.c $(COMPL_O2) $O\FileStreams.obj: ../../Common/FileStreams.cpp $(COMPL) $O\FileIO.obj: ../../../Windows/FileIO.cpp $(COMPL) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc ================================================ PROG = lzma CXX = g++ -O2 -Wall CXX_C = gcc -O2 -Wall LIB = -lm RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ LzmaAlone.o \ LzmaBench.o \ LzmaRam.o \ LzmaRamDecode.o \ LzmaDecode.o \ BranchX86.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ StreamUtils.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaAlone.o: LzmaAlone.cpp $(CXX) $(CFLAGS) LzmaAlone.cpp LzmaBench.o: LzmaBench.cpp $(CXX) $(CFLAGS) LzmaBench.cpp LzmaRam.o: LzmaRam.cpp $(CXX) $(CFLAGS) LzmaRam.cpp LzmaRamDecode.o: LzmaRamDecode.c $(CXX_C) $(CFLAGS) LzmaRamDecode.c LzmaDecode.o: ../LZMA_C/LzmaDecode.c $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c BranchX86.o: ../Branch/BranchX86.c $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c ================================================ /* 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; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h ================================================ /* 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 ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c ================================================ /* LzmaDecodeSize.c LZMA Decoder (optimized for Size version) LZMA SDK 4.27 Copyright (c) 1999-2005 Igor Pavlov (2005-08-07) 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 typedef struct _CRangeDecoder { const Byte *Buffer; const Byte *BufferLim; UInt32 Range; UInt32 Code; #ifdef _LZMA_IN_CB ILzmaInCallback *InCallback; int Result; #endif int ExtraBytes; } CRangeDecoder; Byte RangeDecoderReadByte(CRangeDecoder *rd) { if (rd->Buffer == rd->BufferLim) { #ifdef _LZMA_IN_CB SizeT size; rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); rd->BufferLim = rd->Buffer + size; if (size == 0) #endif { rd->ExtraBytes = 1; return 0xFF; } } return (*rd->Buffer++); } /* #define ReadByte (*rd->Buffer++) */ #define ReadByte (RangeDecoderReadByte(rd)) void RangeDecoderInit(CRangeDecoder *rd #ifndef _LZMA_IN_CB , const Byte *stream, SizeT bufferSize #endif ) { int i; #ifdef _LZMA_IN_CB rd->Buffer = rd->BufferLim = 0; #else rd->Buffer = stream; rd->BufferLim = stream + bufferSize; #endif rd->ExtraBytes = 0; rd->Code = 0; rd->Range = (0xFFFFFFFF); for(i = 0; i < 5; i++) rd->Code = (rd->Code << 8) | ReadByte; } #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_FLUSH_VAR rd->Range = range; rd->Code = code; #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) { RC_INIT_VAR UInt32 result = 0; int i; for (i = numTotalBits; i != 0; i--) { /* UInt32 t; */ range >>= 1; result <<= 1; if (code >= range) { code -= range; result |= 1; } /* t = (code - range) >> 31; t &= 1; code -= range & (t - 1); result = (result + result) | (1 - t); */ RC_NORMALIZE } RC_FLUSH_VAR return result; } int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) { UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; if (rd->Code < bound) { rd->Range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 0; } else { rd->Range -= bound; rd->Code -= bound; *prob -= (*prob) >> kNumMoveBits; if (rd->Range < kTopValue) { rd->Code = (rd->Code << 8) | ReadByte; rd->Range <<= 8; } return 1; } } #define RC_GET_BIT2(prob, mi, A0, A1) \ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ if (code < bound) \ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ RC_NORMALIZE #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = numLevels; i != 0; i--) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT(prob, mi) #else mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return mi - (1 << numLevels); } int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) { int mi = 1; int i; int symbol = 0; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif for(i = 0; i < numLevels; i++) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + mi; RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) #else int bit = RangeDecoderBitDecode(probs + mi, rd); mi = mi + mi + bit; symbol |= (bit << i); #endif } #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) { int symbol = 1; #ifdef _LZMA_LOC_OPT RC_INIT_VAR #endif do { int bit; int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; #ifdef _LZMA_LOC_OPT { CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) } #else bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); symbol = (symbol << 1) | bit; #endif if (matchBit != bit) { while (symbol < 0x100) { #ifdef _LZMA_LOC_OPT CProb *prob = probs + symbol; RC_GET_BIT(prob, symbol) #else symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); #endif } break; } } while (symbol < 0x100); #ifdef _LZMA_LOC_OPT RC_FLUSH_VAR #endif return symbol; } #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) int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) { if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) return RangeDecoderBitTreeDecode(p + LenLow + (posState << kLenNumLowBits), kLenNumLowBits, rd); if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + (posState << kLenNumMidBits), kLenNumMidBits, rd); return kLenNumLowSymbols + kLenNumMidSymbols + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); } #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; CRangeDecoder rd; #ifdef _LZMA_OUT_READ 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]; rd.Range = vs->Range; rd.Code = vs->Code; #ifdef _LZMA_IN_CB rd.InCallback = InCallback; rd.Buffer = vs->Buffer; rd.BufferLim = vs->BufferLim; #else rd.Buffer = inStream; rd.BufferLim = inStream + inSize; #endif #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; RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; } 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]; #ifdef _LZMA_IN_CB rd.Result = LZMA_RESULT_OK; #endif rd.ExtraBytes = 0; #else /* if !_LZMA_OUT_READ */ int state = 0; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; int len = 0; #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 rd.InCallback = InCallback; #endif RangeDecoderInit(&rd #ifndef _LZMA_IN_CB , inStream, inSize #endif ); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; #endif /* _LZMA_OUT_READ */ while(nowPos < outSize) { int posState = (int)( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & posStateMask); #ifdef _LZMA_IN_CB if (rd.Result != LZMA_RESULT_OK) return rd.Result; #endif if (rd.ExtraBytes != 0) return LZMA_RESULT_DATA_ERROR; if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) { CProb *probs = p + Literal + (LZMA_LIT_SIZE * ((( (nowPos #ifdef _LZMA_OUT_READ + globalPos #endif ) & literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { Byte matchByte; #ifdef _LZMA_OUT_READ UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; #else matchByte = outStream[nowPos - rep0]; #endif previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); } else previousByte = LzmaLiteralDecode(probs, &rd); 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 { if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) { if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) { if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) { #ifdef _LZMA_OUT_READ UInt32 pos; #endif #ifdef _LZMA_OUT_READ if (distanceLimit == 0) #else if (nowPos == 0) #endif return LZMA_RESULT_DATA_ERROR; state = state < 7 ? 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 { UInt32 distance; if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) distance = rep1; else { if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < 7 ? 8 : 11; } else { int posSlot; rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < 7 ? 7 : 10; len = LzmaLenDecode(p + LenCoder, &rd, posState); posSlot = RangeDecoderBitTreeDecode(p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), kNumPosSlotBits, &rd); if (posSlot >= kStartPosModelIndex) { int numDirectBits = ((posSlot >> 1) - 1); rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); if (posSlot < kEndPosModelIndex) { rep0 += RangeDecoderReverseBitTreeDecode( p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); } else { rep0 += RangeDecoderDecodeDirectBits(&rd, numDirectBits - kNumAlignBits) << kNumAlignBits; rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); } } 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); } } #ifdef _LZMA_OUT_READ vs->Range = rd.Range; vs->Code = rd.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 = rd.Buffer; vs->BufferLim = rd.BufferLim; #else *inSizeProcessed = (SizeT)(rd.Buffer - inStream); #endif *outSizeProcessed = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c ================================================ /* LzmaStateDecode.c LZMA Decoder (State version) 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. */ #include "LzmaStateDecode.h" #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_INIT Code = 0; Range = 0xFFFFFFFF; \ { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} #define RC_NORMALIZE if (Range < kTopValue) { 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 /* kRequiredInBufferSize = number of required input bytes for worst case: longest match with longest distance. kLzmaInBufferSize must be larger than kRequiredInBufferSize 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) */ #define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) #define kLzmaStreamWasFinishedId (-1) 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; */ } { 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; return LZMA_RESULT_OK; } } int LzmaDecode( CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding) { UInt32 Range = vs->Range; UInt32 Code = vs->Code; unsigned char *Buffer = vs->Buffer; int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ CProb *p = vs->Probs; int state = vs->State; unsigned char previousByte; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; SizeT nowPos = 0; UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; int lc = vs->Properties.lc; int len = vs->RemainLen; UInt32 globalPos = vs->GlobalPos; UInt32 distanceLimit = vs->DistanceLimit; unsigned char *dictionary = vs->Dictionary; UInt32 dictionarySize = vs->Properties.DictionarySize; UInt32 dictionaryPos = vs->DictionaryPos; unsigned char tempDictionary[4]; (*inSizeProcessed) = 0; (*outSizeProcessed) = 0; if (len == kLzmaStreamWasFinishedId) return LZMA_RESULT_OK; if (dictionarySize == 0) { dictionary = tempDictionary; dictionarySize = 1; tempDictionary[0] = vs->TempDictionary[0]; } if (len == kLzmaNeedInitId) { while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < 5) { vs->BufferSize = BufferSize; return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; } { 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; RC_INIT; } 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]; while(1) { int bufferPos = (int)(Buffer - vs->Buffer); if (BufferSize - bufferPos < kRequiredInBufferSize) { int i; BufferSize -= bufferPos; if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; Buffer = vs->Buffer; while (inSize > 0 && BufferSize < kLzmaInBufferSize) { Buffer[BufferSize++] = *inStream++; (*inSizeProcessed)++; inSize--; } if (BufferSize < kRequiredInBufferSize && !finishDecoding) break; } if (nowPos >= outSize) break; { CProb *prob; UInt32 bound; int posState = (int)((nowPos + globalPos) & posStateMask); prob = p + IsMatch + (state << kNumPosBitsMax) + posState; IfBit0(prob) { int symbol = 1; UpdateBit0(prob) prob = p + Literal + (LZMA_LIT_SIZE * ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); if (state >= kNumLitStates) { int matchByte; UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; matchByte = dictionary[pos]; 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 = (unsigned char)symbol; outStream[nowPos++] = previousByte; if (distanceLimit < dictionarySize) distanceLimit++; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; 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) { UInt32 pos; UpdateBit0(prob); if (distanceLimit == 0) return LZMA_RESULT_DATA_ERROR; if (distanceLimit < dictionarySize) distanceLimit++; state = state < kNumLitStates ? 9 : 11; pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; outStream[nowPos++] = previousByte; 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; if (rep0 > distanceLimit) return LZMA_RESULT_DATA_ERROR; if (dictionarySize - distanceLimit > (UInt32)len) distanceLimit += len; else distanceLimit = dictionarySize; do { UInt32 pos = dictionaryPos - rep0; if (pos >= dictionarySize) pos += dictionarySize; previousByte = dictionary[pos]; dictionary[dictionaryPos] = previousByte; if (++dictionaryPos == dictionarySize) dictionaryPos = 0; len--; outStream[nowPos++] = previousByte; } while(len != 0 && nowPos < outSize); } } } RC_NORMALIZE; BufferSize -= (int)(Buffer - vs->Buffer); if (BufferSize < 0) return LZMA_RESULT_DATA_ERROR; { int i; for (i = 0; i < BufferSize; i++) vs->Buffer[i] = Buffer[i]; } vs->BufferSize = BufferSize; vs->Range = Range; vs->Code = Code; vs->DictionaryPos = dictionaryPos; vs->GlobalPos = (UInt32)(globalPos + 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]; (*outSizeProcessed) = nowPos; return LZMA_RESULT_OK; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h ================================================ /* LzmaStateDecode.h LZMA Decoder interface (State version) 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 __LZMASTATEDECODE_H #define __LZMASTATEDECODE_H /* #define _LZMA_PROB32 */ /* It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case */ /* #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 #define LZMA_BASE_SIZE 1846 #define LZMA_LIT_SIZE 768 #define LZMA_PROPERTIES_SIZE 5 typedef struct _CLzmaProperties { int lc; int lp; int pb; UInt32 DictionarySize; }CLzmaProperties; int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); #define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) #define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ #define kLzmaNeedInitId (-2) typedef struct _CLzmaDecoderState { CLzmaProperties Properties; CProb *Probs; unsigned char *Dictionary; unsigned char Buffer[kLzmaInBufferSize]; int BufferSize; UInt32 Range; UInt32 Code; UInt32 DictionaryPos; UInt32 GlobalPos; UInt32 DistanceLimit; UInt32 Reps[4]; int State; int RemainLen; /* -2: decoder needs internal initialization -1: stream was finished, 0: ok > 0: need to write RemainLen bytes as match Reps[0], */ unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ } CLzmaDecoderState; #define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } /* LzmaDecode: decoding from input stream to output stream. If finishDecoding != 0, then there are no more bytes in input stream after inStream[inSize - 1]. */ int LzmaDecode(CLzmaDecoderState *vs, const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, int finishDecoding); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c ================================================ /* LzmaStateTest.c Test application for LZMA Decoder (State version) This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-02) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaStateDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; #define kInBufferSize (1 << 15) #define kOutBufferSize (1 << 15) unsigned char g_InBuffer[kInBufferSize]; unsigned char g_OutBuffer[kOutBufferSize]; size_t MyReadFile(FILE *file, void *data, size_t size) { return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size); } int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ int i; int res = 0; CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inAvail = 0; unsigned char *inBuffer = 0; if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else { state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); if (state.Dictionary == 0) { free(state.Probs); return PrintError(rs, kCantAllocateMessage); } } /* Decompress */ LzmaDecoderInit(&state); do { SizeT inProcessed, outProcessed; int finishDecoding; UInt32 outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = outSize; if (inAvail == 0) { inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); inBuffer = g_InBuffer; } finishDecoding = (inAvail == 0); res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } inAvail -= inProcessed; inBuffer += inProcessed; if (outFile != 0) if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0 && finishDecoding) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); free(state.Dictionary); free(state.Probs); return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c ================================================ /* LzmaTest.c Test application for LZMA Decoder This file written and distributed to public domain by Igor Pavlov. This file is part of LZMA SDK 4.26 (2005-08-05) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "LzmaDecode.h" const char *kCantReadMessage = "Can not read input file"; const char *kCantWriteMessage = "Can not write output file"; const char *kCantAllocateMessage = "Can not allocate memory"; size_t MyReadFile(FILE *file, void *data, size_t size) { if (size == 0) return 0; return fread(data, 1, size, file); } int MyReadFileAndCheck(FILE *file, void *data, size_t size) { return (MyReadFile(file, data, size) == size);} size_t MyWriteFile(FILE *file, const void *data, size_t size) { if (size == 0) return 0; return fwrite(data, 1, size, file); } int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) { return (MyWriteFile(file, data, size) == size); } #ifdef _LZMA_IN_CB #define kInBufferSize (1 << 15) typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; 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; } CBuffer g_InBuffer; #endif #ifdef _LZMA_OUT_READ #define kOutBufferSize (1 << 15) unsigned char g_OutBuffer[kOutBufferSize]; #endif int PrintError(char *buffer, const char *message) { sprintf(buffer + strlen(buffer), "\nError: "); sprintf(buffer + strlen(buffer), message); return 1; } int main3(FILE *inFile, FILE *outFile, char *rs) { /* We use two 32-bit integers to construct 64-bit integer for file size. You can remove outSizeHigh, if you don't need >= 4GB supporting, or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ UInt32 outSize = 0; UInt32 outSizeHigh = 0; #ifndef _LZMA_OUT_READ SizeT outSizeFull; unsigned char *outStream; #endif int waitEOS = 1; /* waitEOS = 1, if there is no uncompressed size in headers, so decoder will wait EOS (End of Stream Marker) in compressed stream */ #ifndef _LZMA_IN_CB SizeT compressedSize; unsigned char *inStream; #endif CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ unsigned char properties[LZMA_PROPERTIES_SIZE]; int res; #ifdef _LZMA_IN_CB g_InBuffer.File = inFile; #endif if (sizeof(UInt32) < 4) return PrintError(rs, "LZMA decoder needs correct UInt32"); #ifndef _LZMA_IN_CB { long length; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); if ((long)(SizeT)length != length) return PrintError(rs, "Too big compressed stream"); compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); } #endif /* Read LZMA properties for compressed stream */ if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) return PrintError(rs, kCantReadMessage); /* Read uncompressed size */ { int i; for (i = 0; i < 8; i++) { unsigned char b; if (!MyReadFileAndCheck(inFile, &b, 1)) return PrintError(rs, kCantReadMessage); if (b != 0xFF) waitEOS = 0; if (i < 4) outSize += (UInt32)(b) << (i * 8); else outSizeHigh += (UInt32)(b) << ((i - 4) * 8); } #ifndef _LZMA_OUT_READ if (waitEOS) return PrintError(rs, "Stream with EOS marker is not supported"); outSizeFull = (SizeT)outSize; if (sizeof(SizeT) >= 8) outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) return PrintError(rs, "Too big uncompressed stream"); #endif } /* Decode LZMA properties and allocate memory */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); #ifdef _LZMA_OUT_READ if (state.Properties.DictionarySize == 0) state.Dictionary = 0; else state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); #else if (outSizeFull == 0) outStream = 0; else outStream = (unsigned char *)malloc(outSizeFull); #endif #ifndef _LZMA_IN_CB if (compressedSize == 0) inStream = 0; else inStream = (unsigned char *)malloc(compressedSize); #endif if (state.Probs == 0 #ifdef _LZMA_OUT_READ || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) #else || (outStream == 0 && outSizeFull != 0) #endif #ifndef _LZMA_IN_CB || (inStream == 0 && compressedSize != 0) #endif ) { free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return PrintError(rs, kCantAllocateMessage); } /* Decompress */ #ifdef _LZMA_IN_CB g_InBuffer.InCallback.Read = LzmaReadCompressed; #else if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) return PrintError(rs, kCantReadMessage); #endif #ifdef _LZMA_OUT_READ { #ifndef _LZMA_IN_CB SizeT inAvail = compressedSize; const unsigned char *inBuffer = inStream; #endif LzmaDecoderInit(&state); do { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; SizeT outAvail = kOutBufferSize; if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) outAvail = (SizeT)outSize; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inBuffer, inAvail, &inProcessed, #endif g_OutBuffer, outAvail, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; break; } #ifndef _LZMA_IN_CB inAvail -= inProcessed; inBuffer += inProcessed; #endif if (outFile != 0) if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; break; } if (outSize < outProcessed) outSizeHigh--; outSize -= (UInt32)outProcessed; outSize &= 0xFFFFFFFF; if (outProcessed == 0) { if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) res = 1; break; } } while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); } #else { #ifndef _LZMA_IN_CB SizeT inProcessed; #endif SizeT outProcessed; res = LzmaDecode(&state, #ifdef _LZMA_IN_CB &g_InBuffer.InCallback, #else inStream, compressedSize, &inProcessed, #endif outStream, outSizeFull, &outProcessed); if (res != 0) { sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); res = 1; } else if (outFile != 0) { if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) { PrintError(rs, kCantWriteMessage); res = 1; } } } #endif free(state.Probs); #ifdef _LZMA_OUT_READ free(state.Dictionary); #else free(outStream); #endif #ifndef _LZMA_IN_CB free(inStream); #endif return res; } int main2(int numArgs, const char *args[], char *rs) { FILE *inFile = 0; FILE *outFile = 0; int res; sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); if (numArgs < 2 || numArgs > 3) { sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); return 1; } inFile = fopen(args[1], "rb"); if (inFile == 0) return PrintError(rs, "Can not open input file"); if (numArgs > 2) { outFile = fopen(args[2], "wb+"); if (outFile == 0) return PrintError(rs, "Can not open output file"); } res = main3(inFile, outFile, rs); if (outFile != 0) fclose(outFile); fclose(inFile); return res; } int main(int numArgs, const char *args[]) { char rs[800] = { 0 }; int res = main2(numArgs, args, rs); printf(rs); return res; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/makefile ================================================ PROG = lzmaDec.exe !IFNDEF O !IFDEF CPU O=$(CPU) !ELSE O=O !ENDIF !ENDIF CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- CFLAGS_O1 = $(CFLAGS) -O1 CFLAGS_O2 = $(CFLAGS) -O2 LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 PROGPATH = $O\$(PROG) COMPL_O1 = $(CPP) $(CFLAGS_O1) $** COMPL_O2 = $(CPP) $(CFLAGS_O2) $** COMPL = $(CPP) $(CFLAGS_O1) $** OBJS = \ $O\LzmaTest.obj \ $O\LzmaDecode.obj \ all: $(PROGPATH) clean: -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch $O: if not exist "$O" mkdir "$O" $(PROGPATH): $O $(OBJS) link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) $O\LzmaTest.obj: $(*B).c $(COMPL) $O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c $(COMPL_O2) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_C/makefile.gcc ================================================ PROG = lzmadec CXX = gcc LIB = RM = rm -f CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 OBJS = LzmaTest.o LzmaDecode.o all: $(PROG) $(PROG): $(OBJS) $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) LzmaTest.o: LzmaTest.c $(CXX) $(CFLAGS) LzmaTest.c LzmaDecode.o: LzmaDecode.c $(CXX) $(CFLAGS) LzmaDecode.c clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Lib/ZLib.cpp ================================================ /* * lzma zlib simplified wrapper * * Copyright (c) 2005-2006 Oleg I. Vdovikin <oleg@cs.msu.su> * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA * */ /* * default values for encoder/decoder used by wrapper */ #include <zlib.h> /* jc: undef to kill compress2_lzma */ #define _LZMA_PARAMS #define ZLIB_LC 3 #define ZLIB_LP 0 #define ZLIB_PB 2 #define ZLIB_FB 128 /* jc: add default fast bytes param */ #ifdef WIN32 #include <initguid.h> #else #define INITGUID #endif #include "../../../Common/MyWindows.h" #include "../LZMA/LZMADecoder.h" #include "../LZMA/LZMAEncoder.h" #define STG_E_SEEKERROR ((HRESULT)0x80030019L) #define STG_E_MEDIUMFULL ((HRESULT)0x80030070L) class CInMemoryStream: public IInStream, public IStreamGetSize, public CMyUnknownImp { public: CInMemoryStream(const Bytef *data, UInt64 size) : m_data(data), m_size(size), m_offset(0) {} virtual ~CInMemoryStream() {} MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (size > m_size - m_offset) size = m_size - m_offset; if (size) { memcpy(data, m_data + m_offset, size); } m_offset += size; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) { return Read(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_size) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(GetSize)(UInt64 *size) { *size = m_size; return S_OK; } protected: const Bytef *m_data; UInt64 m_size; UInt64 m_offset; }; class COutMemoryStream: public IOutStream, public CMyUnknownImp { public: COutMemoryStream(Bytef *data, UInt64 maxsize) : m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {} virtual ~COutMemoryStream() {} MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) { if (size > m_maxsize - m_offset) size = m_maxsize - m_offset; if (size) { memcpy(m_data + m_offset, data, size); } m_offset += size; if (m_offset > m_size) m_size = m_offset; if (processedSize) *processedSize = size; return S_OK; } STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) { return Write(data, size, processedSize); } STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { UInt64 _offset; if (seekOrigin == STREAM_SEEK_SET) _offset = offset; else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; else return STG_E_INVALIDFUNCTION; if (_offset < 0 || _offset > m_maxsize) return STG_E_SEEKERROR; m_offset = _offset; if (newPosition) *newPosition = m_offset; return S_OK; } STDMETHOD(SetSize)(Int64 newSize) { if ((UInt64)newSize > m_maxsize) return STG_E_MEDIUMFULL; return S_OK; } protected: Bytef *m_data; UInt64 m_size; UInt64 m_maxsize; UInt64 m_offset; }; #ifdef _LZMA_PARAMS /* jc: new compress2 proxy that allows lzma param specification */ extern "C" int compress2_lzma_test (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level, int fb, int lc, int lp, int pb) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr<ISequentialInStream> inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); if(pb<0) pb=ZLIB_PB; if(lc<0) lc=ZLIB_LC; if(lp<0) lp=ZLIB_LP; if(fb<0) fb=ZLIB_FB; PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(1 << (level + 14)); properties[1].ulVal = UInt32(pb); properties[2].ulVal = UInt32(lc); // for normal files properties[3].ulVal = UInt32(lp); // for normal files properties[4].ulVal = UInt32(2); // todo properties[5].ulVal = UInt32(fb); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4"; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_TRUE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) return Z_MEM_ERROR; // should not happen HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { return Z_MEM_ERROR; } else if (result != S_OK) { return Z_BUF_ERROR; // should not happen } UInt64 fileSize; outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } #include <malloc.h> #include <stdio.h> #include <pthread.h> unsigned char pbmatrix[3]={0,1,2}; unsigned char lcmatrix[4]={0,1,2,3}; unsigned char lpmatrix[4]={0,1,2,3}; struct MATRIXENTRY { int pb; int lc; int lp; }; struct MATRIXENTRY matrix[]={ {2,0,0}, {2,0,1}, {2,0,2}, {2,1,0}, {2,1,2}, {2,2,0}, {2,3,0}, {0,2,0}, {0,2,1}, {0,3,0}, {0,0,0}, {0,0,2}, {1,0,1}, {1,2,0}, {1,3,0} }; int pbsave = -1; int lcsave = -1; int lpsave = -1; int testcount=0; int testlevel; int testfb; pthread_mutex_t pos_mutex; Bytef *test1; const Bytef *testsource; uLongf test2len; uLongf test1len; uLongf testsourcelen; int running=0; extern "C" void *brute(void *arg) { int oldstate; uLongf test3len = test2len; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); pthread_mutex_lock(&pos_mutex); int takelcvalue = matrix[testcount].lc; int takepbvalue = matrix[testcount].pb; int takelpvalue = matrix[testcount].lp; testcount++; if (testcount==(sizeof(matrix)/sizeof(struct MATRIXENTRY))) { running--; pthread_mutex_unlock(&pos_mutex); return NULL; } pthread_mutex_unlock(&pos_mutex); Bytef *test2 = (Bytef*)malloc(test2len); int ret = compress2_lzma_test(test2,&test3len,testsource,testsourcelen,testlevel,testfb,takelcvalue,takelpvalue,takepbvalue); pthread_mutex_lock(&pos_mutex); if (test3len<test1len) { test1len = test3len; memcpy(test1,test2,test3len); pbsave = takepbvalue; lcsave = takelcvalue; lpsave = takelpvalue; } running--; pthread_mutex_unlock(&pos_mutex); free(test2); return NULL; } extern "C" int compress2_lzma (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level, int fb, int lc, int lp, int pb) { int i,a; pthread_t *thread; test1 = (Bytef*)malloc(*destLen); test1len = *destLen+*destLen; test2len = *destLen; testsource = source; testfb = fb; testsourcelen = sourceLen; testlevel = level; testcount=0; if((thread = (pthread_t *)malloc((8) * sizeof(pthread_t))) == NULL) fprintf(stderr,"Out of memory allocating thread descriptors\n"); for (a=0;a<2;a++) { running=8; for(i = 0; i < 8; i++) { if(pthread_create(&thread[i], NULL, brute, NULL) != 0 ) fprintf(stderr,"Failed to create thread\n"); } for (i=0;i<8;i++) { pthread_join(thread[i],NULL); } } memcpy(dest+4,test1,test1len); dest[0]=pbsave; dest[1]=lcsave; dest[2]=lpsave; dest[3]=fb; *destLen=test1len+4; free(thread); free(test1); return Z_OK; } #endif ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); CMyComPtr<ISequentialInStream> inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; CMyComPtr<ICompressCoder> encoder = encoderSpec; PROPID propIDs[] = { NCoderPropID::kDictionarySize, NCoderPropID::kPosStateBits, NCoderPropID::kLitContextBits, NCoderPropID::kLitPosBits, NCoderPropID::kAlgorithm, NCoderPropID::kNumFastBytes, NCoderPropID::kMatchFinder, NCoderPropID::kEndMarker }; const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); PROPVARIANT properties[kNumProps]; for (int p = 0; p < 6; p++) properties[p].vt = VT_UI4; properties[0].ulVal = UInt32(1 << (level + 14)); properties[1].ulVal = UInt32(ZLIB_PB); properties[2].ulVal = UInt32(ZLIB_LC); // for normal files properties[3].ulVal = UInt32(ZLIB_LP); // for normal files properties[4].ulVal = UInt32(2); properties[5].ulVal = UInt32(ZLIB_FB); properties[6].vt = VT_BSTR; properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT4"; properties[7].vt = VT_BOOL; properties[7].boolVal = VARIANT_TRUE; if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) { fprintf(stderr,"coder properties error\n"); return Z_MEM_ERROR; // should not happen } HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); if (result == E_OUTOFMEMORY) { fprintf(stderr,"mem error\n"); return Z_MEM_ERROR; } else if (result != S_OK) { return Z_BUF_ERROR; // should not happen } UInt64 fileSize; outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)) { CInMemoryStream *inStreamSpec = new CInMemoryStream(source+4, sourceLen-4); CMyComPtr<ISequentialInStream> inStream = inStreamSpec; COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; CMyComPtr<ICompressCoder> decoder = decoderSpec; if (decoderSpec->SetDecoderPropertiesRaw(source[1], source[2], source[0], (1 << 23)) != S_OK) return Z_DATA_ERROR; UInt64 fileSize = *destLen; if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { return Z_DATA_ERROR; } outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); *destLen = fileSize; return Z_OK; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Lib/lzmaext.h ================================================ /* * lzmaext.h * * LZMA Parameter extensions * these minor additions by Jeremy Collake <jeremy@bitsum.com> * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, * Suite 330, Boston, MA 02111-1307 USA */ int compress2_lzma (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level, int fb, int lc, int lp, int pb); ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/LZMA_Lib/makefile ================================================ PROG = liblzma.a CXX = g++ -O3 -funroll-loops -mtune=opteron -march=opteron -mfpmath=sse -m3dnow -msse2 -mmmx -msse -msse3 -O3 -Wall -finline-functions AR = ar RM = rm -f CFLAGS = -c -I ../../../ OBJS = \ ZLib.o \ LZMADecoder.o \ LZMAEncoder.o \ LZInWindow.o \ LZOutWindow.o \ RangeCoderBit.o \ InBuffer.o \ OutBuffer.o \ FileStreams.o \ Alloc.o \ C_FileIO.o \ CommandLineParser.o \ CRC.o \ StreamUtils.o \ String.o \ StringConvert.o \ StringToInt.o \ Vector.o \ all: $(PROG) $(PROG): $(OBJS) $(AR) r $(PROG) $(OBJS) ZLib.o: ZLib.cpp $(CXX) $(CFLAGS) ZLib.cpp LZMADecoder.o: ../LZMA/LZMADecoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp LZInWindow.o: ../LZ/LZInWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp LZOutWindow.o: ../LZ/LZOutWindow.cpp $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp InBuffer.o: ../../Common/InBuffer.cpp $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp OutBuffer.o: ../../Common/OutBuffer.cpp $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp StreamUtils.o: ../../Common/StreamUtils.cpp $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp FileStreams.o: ../../Common/FileStreams.cpp $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp Alloc.o: ../../../Common/Alloc.cpp $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp C_FileIO.o: ../../../Common/C_FileIO.cpp $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp CommandLineParser.o: ../../../Common/CommandLineParser.cpp $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp CRC.o: ../../../Common/CRC.cpp $(CXX) $(CFLAGS) ../../../Common/CRC.cpp MyWindows.o: ../../../Common/MyWindows.cpp $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp String.o: ../../../Common/String.cpp $(CXX) $(CFLAGS) ../../../Common/String.cpp StringConvert.o: ../../../Common/StringConvert.cpp $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp StringToInt.o: ../../../Common/StringToInt.cpp $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp Vector.o: ../../../Common/Vector.cpp $(CXX) $(CFLAGS) ../../../Common/Vector.cpp clean: -$(RM) $(PROG) $(OBJS) ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h ================================================ // Compress/RangeCoder/RangeCoder.h #ifndef __COMPRESS_RANGECODER_H #define __COMPRESS_RANGECODER_H #include "../../Common/InBuffer.h" #include "../../Common/OutBuffer.h" namespace NCompress { namespace NRangeCoder { const int kNumTopBits = 24; const UInt32 kTopValue = (1 << kNumTopBits); class CEncoder { UInt32 _cacheSize; Byte _cache; public: UInt64 Low; UInt32 Range; COutBuffer Stream; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } void FlushData() { // Low += 1; for(int i = 0; i < 5; i++) ShiftLow(); } HRESULT FlushStream() { return Stream.Flush(); } void ReleaseStream() { Stream.ReleaseStream(); } void Encode(UInt32 start, UInt32 size, UInt32 total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } void ShiftLow() { if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) { Byte temp = _cache; do { Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); temp = 0xFF; } while(--_cacheSize != 0); _cache = (Byte)((UInt32)Low >> 24); } _cacheSize++; Low = (UInt32)Low << 8; } void EncodeDirectBits(UInt32 value, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((value >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) { UInt32 newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } }; class CDecoder { public: CInBuffer Stream; UInt32 Range; UInt32 Code; bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | Stream.ReadByte(); Range <<= 8; } } void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } void Init() { Stream.Init(); Code = 0; Range = 0xFFFFFFFF; for(int i = 0; i < 5; i++) Code = (Code << 8) | Stream.ReadByte(); } void ReleaseStream() { Stream.ReleaseStream(); } UInt32 GetThreshold(UInt32 total) { return (Code) / ( Range /= total); } void Decode(UInt32 start, UInt32 size) { Code -= start * Range; Range *= size; Normalize(); } UInt32 DecodeDirectBits(int numTotalBits) { UInt32 range = Range; UInt32 code = Code; UInt32 result = 0; for (int i = numTotalBits; i != 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ UInt32 t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { UInt32 newBound = (Range >> numTotalBits) * size0; UInt32 symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } }; }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp ================================================ // Compress/RangeCoder/RangeCoderBit.cpp #include "StdAfx.h" #include "RangeCoderBit.h" namespace NCompress { namespace NRangeCoder { UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static CPriceTables g_PriceTables; CPriceTables::CPriceTables() { Init(); } void CPriceTables::Init() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for(int i = kNumBits - 1; i >= 0; i--) { UInt32 start = 1 << (kNumBits - i - 1); UInt32 end = 1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } /* // simplest: bad solution for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = kBitPrice; */ /* const double kDummyMultMid = (1.0 / kBitPrice) / 2; const double kDummyMultMid = 0; // float solution double ln2 = log(double(2)); double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); */ /* // experimental, slow, solution: for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) { const int kCyclesBits = 5; const UInt32 kCycles = (1 << kCyclesBits); UInt32 range = UInt32(-1); UInt32 bitCount = 0; for (UInt32 j = 0; j < kCycles; j++) { range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); range *= i; while(range < (1 << 31)) { range <<= 1; bitCount++; } } bitCount <<= kNumBitPriceShiftBits; range -= (1 << 31); for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) { range <<= 1; if (range > (1 << 31)) { bitCount += (1 << k); range -= (1 << 31); } } ProbPrices[i] = (bitCount // + (1 << (kCyclesBits - 1)) ) >> kCyclesBits; } */ } }} ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h ================================================ // Compress/RangeCoder/RangeCoderBit.h #ifndef __COMPRESS_RANGECODER_BIT_H #define __COMPRESS_RANGECODER_BIT_H #include "RangeCoder.h" namespace NCompress { namespace NRangeCoder { const int kNumBitModelTotalBits = 11; const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveReducingBits = 2; const int kNumBitPriceShiftBits = 6; const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; class CPriceTables { public: static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; static void Init(); CPriceTables(); }; template <int numMoveBits> class CBitModel { public: UInt32 Prob; void UpdateModel(UInt32 symbol) { /* Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); */ if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public: void Init() { Prob = kBitModelTotal / 2; } }; template <int numMoveBits> class CBitEncoder: public CBitModel<numMoveBits> { public: void Encode(CEncoder *encoder, UInt32 symbol) { /* encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); this->UpdateModel(symbol); */ UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; if (symbol == 0) { encoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; } else { encoder->Low += newBound; encoder->Range -= newBound; this->Prob -= (this->Prob) >> numMoveBits; } if (encoder->Range < kTopValue) { encoder->Range <<= 8; encoder->ShiftLow(); } } UInt32 GetPrice(UInt32 symbol) const { return CPriceTables::ProbPrices[ (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } }; template <int numMoveBits> class CBitDecoder: public CBitModel<numMoveBits> { public: UInt32 Decode(CDecoder *decoder) { UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; if (decoder->Code < newBound) { decoder->Range = newBound; this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 0; } else { decoder->Range -= newBound; decoder->Code -= newBound; this->Prob -= (this->Prob) >> numMoveBits; if (decoder->Range < kTopValue) { decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); decoder->Range <<= 8; } return 1; } } }; }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h ================================================ // Compress/RangeCoder/RangeCoderBitTree.h #ifndef __COMPRESS_RANGECODER_BIT_TREE_H #define __COMPRESS_RANGECODER_BIT_TREE_H #include "RangeCoderBit.h" #include "RangeCoderOpt.h" namespace NCompress { namespace NRangeCoder { template <int numMoveBits, int NumBitLevels> class CBitTreeEncoder { CBitEncoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } void Encode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int bitIndex = NumBitLevels; bitIndex != 0 ;) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; } }; void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } UInt32 GetPrice(UInt32 symbol) const { symbol |= (1 << NumBitLevels); UInt32 price = 0; while (symbol != 1) { price += Models[symbol >> 1].GetPrice(symbol & 1); symbol >>= 1; } return price; } UInt32 ReverseGetPrice(UInt32 symbol) const { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } }; template <int numMoveBits, int NumBitLevels> class CBitTreeDecoder { CBitDecoder<numMoveBits> Models[1 << NumBitLevels]; public: void Init() { for(UInt32 i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } UInt32 Decode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; RC_INIT_VAR for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) { // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) } RC_FLUSH_VAR return modelIndex - (1 << NumBitLevels); }; UInt32 ReverseDecode(CDecoder *rangeDecoder) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }; template <int numMoveBits> void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 modelIndex = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[modelIndex].Encode(rangeEncoder, bit); modelIndex = (modelIndex << 1) | bit; symbol >>= 1; } } template <int numMoveBits> UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, UInt32 NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 modelIndex = 1; for (int i = NumBitLevels; i != 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[modelIndex].GetPrice(bit); modelIndex = (modelIndex << 1) | bit; } return price; } template <int numMoveBits> UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, CDecoder *rangeDecoder, int NumBitLevels) { UInt32 modelIndex = 1; UInt32 symbol = 0; RC_INIT_VAR for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); // modelIndex <<= 1; // modelIndex += bit; // symbol |= (bit << bitIndex); RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) } RC_FLUSH_VAR return symbol; } }} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h ================================================ // Compress/RangeCoder/RangeCoderOpt.h #ifndef __COMPRESS_RANGECODER_OPT_H #define __COMPRESS_RANGECODER_OPT_H #define RC_INIT_VAR \ UInt32 range = rangeDecoder->Range; \ UInt32 code = rangeDecoder->Code; #define RC_FLUSH_VAR \ rangeDecoder->Range = range; \ rangeDecoder->Code = code; #define RC_NORMALIZE \ if (range < NCompress::NRangeCoder::kTopValue) \ { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } #define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ if (code < bound) \ { A0; range = bound; \ prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ mi <<= 1; } \ else \ { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ mi = (mi + mi) + 1; }} \ RC_NORMALIZE #define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/Compress/RangeCoder/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/ICoder.h ================================================ // ICoder.h #ifndef __ICODER_H #define __ICODER_H #include "IStream.h" // "23170F69-40C1-278A-0000-000400xx0000" #define CODER_INTERFACE(i, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ struct i: public IUnknown CODER_INTERFACE(ICompressProgressInfo, 0x04) { STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressCoder, 0x05) { STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) PURE; }; CODER_INTERFACE(ICompressCoder2, 0x18) { STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) PURE; }; namespace NCoderPropID { enum EEnum { kDictionarySize = 0x400, kUsedMemorySize, kOrder, kPosStateBits = 0x440, kLitContextBits, kLitPosBits, kNumFastBytes = 0x450, kMatchFinder, kNumPasses = 0x460, kAlgorithm = 0x470, kMultiThread = 0x480, kEndMarker = 0x490 }; } CODER_INTERFACE(ICompressSetCoderProperties, 0x20) { STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties) PURE; }; /* CODER_INTERFACE(ICompressSetCoderProperties, 0x21) { STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; }; */ CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) { STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) { STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; }; CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) { STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; }; CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) { STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; }; CODER_INTERFACE(ICompressSetInStream, 0x31) { STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; STDMETHOD(ReleaseInStream)() PURE; }; CODER_INTERFACE(ICompressSetOutStream, 0x32) { STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; STDMETHOD(ReleaseOutStream)() PURE; }; CODER_INTERFACE(ICompressSetInStreamSize, 0x33) { STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; }; CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) { STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; }; CODER_INTERFACE(ICompressFilter, 0x40) { STDMETHOD(Init)() PURE; STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; // Filter return outSize (UInt32) // if (outSize <= size): Filter have converted outSize bytes // if (outSize > size): Filter have not converted anything. // and it needs at least outSize bytes to convert one block // (it's for crypto block algorithms). }; CODER_INTERFACE(ICryptoProperties, 0x80) { STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetPassword, 0x90) { STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; }; CODER_INTERFACE(ICryptoSetCRC, 0xA0) { STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; }; ////////////////////// // It's for DLL file namespace NMethodPropID { enum EEnum { kID, kName, kDecoder, kEncoder, kInStreams, kOutStreams, kDescription }; } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/7zip/IStream.h ================================================ // IStream.h #ifndef __ISTREAM_H #define __ISTREAM_H #include "../Common/MyUnknown.h" #include "../Common/Types.h" // "23170F69-40C1-278A-0000-000300xx0000" #define STREAM_INTERFACE_SUB(i, b, x) \ DEFINE_GUID(IID_ ## i, \ 0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ struct i: public b #define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) STREAM_INTERFACE(ISequentialInStream, 0x01) { STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; /* Out: if size != 0, return_value = S_OK and (*processedSize == 0), then there are no more bytes in stream. if (size > 0) && there are bytes in stream, this function must read at least 1 byte. This function is allowed to read less than number of remaining bytes in stream. You must call Read function in loop, if you need exact amount of data */ }; STREAM_INTERFACE(ISequentialOutStream, 0x02) { STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; /* if (size > 0) this function must write at least 1 byte. This function is allowed to write less than "size". You must call Write function in loop, if you need to write exact amount of data */ }; STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; }; STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) { STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; STDMETHOD(SetSize)(Int64 newSize) PURE; }; STREAM_INTERFACE(IStreamGetSize, 0x06) { STDMETHOD(GetSize)(UInt64 *size) PURE; }; STREAM_INTERFACE(IOutStreamFlush, 0x07) { STDMETHOD(Flush)() PURE; }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Alloc.cpp ================================================ // Common/Alloc.cpp #include "StdAfx.h" #ifdef _WIN32 #include "MyWindows.h" #else #include <stdlib.h> #endif #include "Alloc.h" /* #define _SZ_ALLOC_DEBUG */ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef _SZ_ALLOC_DEBUG #include <stdio.h> int g_allocCount = 0; int g_allocCountMid = 0; int g_allocCountBig = 0; #endif void *MyAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); #endif return ::malloc(size); } void MyFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree; count = %10d", --g_allocCount); #endif ::free(address); } #ifdef _WIN32 void *MidAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); #endif return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void MidFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } static SIZE_T g_LargePageSize = #ifdef _WIN64 (1 << 21); #else (1 << 22); #endif typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); bool SetLargePageSize() { GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); if (largePageMinimum == 0) return false; SIZE_T size = largePageMinimum(); if (size == 0 || (size & (size - 1)) != 0) return false; g_LargePageSize = size; return true; } void *BigAlloc(size_t size) throw() { if (size == 0) return 0; #ifdef _SZ_ALLOC_DEBUG fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); #endif if (size >= (1 << 18)) { void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); if (res != 0) return res; } return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); } void BigFree(void *address) throw() { #ifdef _SZ_ALLOC_DEBUG if (address != 0) fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); #endif if (address == 0) return; ::VirtualFree(address, 0, MEM_RELEASE); } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Alloc.h ================================================ // Common/Alloc.h #ifndef __COMMON_ALLOC_H #define __COMMON_ALLOC_H #include <stddef.h> void *MyAlloc(size_t size) throw(); void MyFree(void *address) throw(); #ifdef _WIN32 bool SetLargePageSize(); void *MidAlloc(size_t size) throw(); void MidFree(void *address) throw(); void *BigAlloc(size_t size) throw(); void BigFree(void *address) throw(); #else #define MidAlloc(size) MyAlloc(size) #define MidFree(address) MyFree(address) #define BigAlloc(size) MyAlloc(size) #define BigFree(address) MyFree(address) #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/CRC.cpp ================================================ // Common/CRC.cpp #include "StdAfx.h" #include "CRC.h" static const UInt32 kCRCPoly = 0xEDB88320; UInt32 CCRC::Table[256]; void CCRC::InitTable() { for (UInt32 i = 0; i < 256; i++) { UInt32 r = i; for (int j = 0; j < 8; j++) if (r & 1) r = (r >> 1) ^ kCRCPoly; else r >>= 1; CCRC::Table[i] = r; } } class CCRCTableInit { public: CCRCTableInit() { CCRC::InitTable(); } } g_CRCTableInit; void CCRC::UpdateByte(Byte b) { _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); } void CCRC::UpdateUInt16(UInt16 v) { UpdateByte(Byte(v)); UpdateByte(Byte(v >> 8)); } void CCRC::UpdateUInt32(UInt32 v) { for (int i = 0; i < 4; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::UpdateUInt64(UInt64 v) { for (int i = 0; i < 8; i++) UpdateByte((Byte)(v >> (8 * i))); } void CCRC::Update(const void *data, size_t size) { UInt32 v = _value; const Byte *p = (const Byte *)data; for (; size > 0 ; size--, p++) v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); _value = v; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/CRC.h ================================================ // Common/CRC.h #ifndef __COMMON_CRC_H #define __COMMON_CRC_H #include <stddef.h> #include "Types.h" class CCRC { UInt32 _value; public: static UInt32 Table[256]; static void InitTable(); CCRC(): _value(0xFFFFFFFF){}; void Init() { _value = 0xFFFFFFFF; } void UpdateByte(Byte v); void UpdateUInt16(UInt16 v); void UpdateUInt32(UInt32 v); void UpdateUInt64(UInt64 v); void Update(const void *data, size_t size); UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } static UInt32 CalculateDigest(const void *data, size_t size) { CCRC crc; crc.Update(data, size); return crc.GetDigest(); } static bool VerifyDigest(UInt32 digest, const void *data, size_t size) { return (CalculateDigest(data, size) == digest); } }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/C_FileIO.cpp ================================================ // Common/C_FileIO.h #include "C_FileIO.h" #include <fcntl.h> #include <unistd.h> namespace NC { namespace NFile { namespace NIO { bool CFileBase::OpenBinary(const char *name, int flags) { #ifdef O_BINARY flags |= O_BINARY; #endif Close(); _handle = ::open(name, flags, 0666); return _handle != -1; } bool CFileBase::Close() { if(_handle == -1) return true; if (close(_handle) != 0) return false; _handle = -1; return true; } bool CFileBase::GetLength(UInt64 &length) const { off_t curPos = Seek(0, SEEK_CUR); off_t lengthTemp = Seek(0, SEEK_END); Seek(curPos, SEEK_SET); length = (UInt64)lengthTemp; return true; } off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const { return ::lseek(_handle, distanceToMove, moveMethod); } ///////////////////////// // CInFile bool CInFile::Open(const char *name) { return CFileBase::OpenBinary(name, O_RDONLY); } ssize_t CInFile::Read(void *data, size_t size) { return read(_handle, data, size); } ///////////////////////// // COutFile bool COutFile::Create(const char *name, bool createAlways) { if (createAlways) { Close(); _handle = ::creat(name, 0666); return _handle != -1; } return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); } ssize_t COutFile::Write(const void *data, size_t size) { return write(_handle, data, size); } }}} ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/C_FileIO.h ================================================ // Common/C_FileIO.h #ifndef __COMMON_C_FILEIO_H #define __COMMON_C_FILEIO_H #include <stdio.h> #include <sys/types.h> #include "Types.h" #include "MyWindows.h" namespace NC { namespace NFile { namespace NIO { class CFileBase { protected: int _handle; bool OpenBinary(const char *name, int flags); public: CFileBase(): _handle(-1) {}; ~CFileBase() { Close(); } bool Close(); bool GetLength(UInt64 &length) const; off_t Seek(off_t distanceToMove, int moveMethod) const; }; class CInFile: public CFileBase { public: bool Open(const char *name); ssize_t Read(void *data, size_t size); }; class COutFile: public CFileBase { public: bool Create(const char *name, bool createAlways); ssize_t Write(const void *data, size_t size); }; }}} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/ComTry.h ================================================ // ComTry.h #ifndef __COM_TRY_H #define __COM_TRY_H #include "MyWindows.h" // #include "Exception.h" // #include "NewHandler.h" #define COM_TRY_BEGIN try { #define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } // catch(const CNewException &) { return E_OUTOFMEMORY; }\ // catch(const CSystemException &e) { return e.ErrorCode; }\ // catch(...) { return E_FAIL; } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/CommandLineParser.cpp ================================================ // CommandLineParser.cpp #include "StdAfx.h" #include "CommandLineParser.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) { dest1.Empty(); dest2.Empty(); bool quoteMode = false; int i; for (i = 0; i < src.Length(); i++) { wchar_t c = src[i]; if (c == L'\"') quoteMode = !quoteMode; else if (c == L' ' && !quoteMode) { i++; break; } else dest1 += c; } dest2 = src.Mid(i); } void SplitCommandLine(const UString &s, UStringVector &parts) { UString sTemp = s; sTemp.Trim(); parts.Clear(); while (true) { UString s1, s2; SplitCommandLine(sTemp, s1, s2); // s1.Trim(); // s2.Trim(); if (!s1.IsEmpty()) parts.Add(s1); if (s2.IsEmpty()) return; sTemp = s2; } } static const wchar_t kSwitchID1 = '-'; // static const wchar_t kSwitchID2 = '/'; static const wchar_t kSwitchMinus = '-'; static const wchar_t *kStopSwitchParsing = L"--"; static bool IsItSwitchChar(wchar_t c) { return (c == kSwitchID1 /*|| c == kSwitchID2 */); } CParser::CParser(int numSwitches): _numSwitches(numSwitches) { _switches = new CSwitchResult[_numSwitches]; } CParser::~CParser() { delete []_switches; } void CParser::ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings) { int numCommandStrings = commandStrings.Size(); bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { const UString &s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } // if string contains switch then function updates switch structures // out: (string is a switch) bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) { int len = s.Length(); if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(s[pos])) return false; while(pos < len) { if (IsItSwitchChar(s[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; // GCC Warning int maxLen = kNoLen; for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) { int switchLen = MyStringLen(switchForms[switchIndex].IDString); if (switchLen <= maxLen || pos + switchLen > len) continue; UString temp = s + pos; temp = temp.Left(switchLen); if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw "maxLen == kNoLen"; CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw "switch must be single"; matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; NSwitchType::EEnum type = switchForm.Type; switch(type) { case NSwitchType::kPostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case NSwitchType::kPostChar: { if (tailSize < switchForm.MinLen) throw "switch is not full"; UString set = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = set.Find(s[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case NSwitchType::kLimitedPostString: case NSwitchType::kUnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw "switch is not full"; if (type == NSwitchType::kUnLimitedPostString) { matchedSwitch.PostStrings.Add(s.Mid(pos)); return true; } int maxLen = switchForm.MaxLen; UString stringSwitch = s.Mid(pos, minLen); pos += minLen; for(int i = minLen; i < maxLen && pos < len; i++, pos++) { wchar_t c = s[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } case NSwitchType::kSimple: break; } } return true; } const CSwitchResult& CParser::operator[](size_t index) const { return _switches[index]; } ///////////////////////////////// // Command parsing procedures int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString) { for(int i = 0; i < numCommandForms; i++) { const UString id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if(commandString.Find(id) == 0) { postString = commandString.Mid(id.Length()); return i; } } else if (commandString == id) { postString.Empty(); return i; } } return -1; } bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices) { indices.Clear(); int numUsedChars = 0; for(int i = 0; i < numForms; i++) { const CCommandSubCharsSet &set = forms[i]; int currentIndex = -1; int len = MyStringLen(set.Chars); for(int j = 0; j < len; j++) { wchar_t c = set.Chars[j]; int newIndex = commandString.Find(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.Find(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if(currentIndex == -1 && !set.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length()); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/CommandLineParser.h ================================================ // Common/CommandLineParser.h #ifndef __COMMON_COMMANDLINEPARSER_H #define __COMMON_COMMANDLINEPARSER_H #include "Common/String.h" namespace NCommandLineParser { void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); void SplitCommandLine(const UString &s, UStringVector &parts); namespace NSwitchType { enum EEnum { kSimple, kPostMinus, kLimitedPostString, kUnLimitedPostString, kPostChar }; } struct CSwitchForm { const wchar_t *IDString; NSwitchType::EEnum Type; bool Multi; int MinLen; int MaxLen; const wchar_t *PostCharSet; }; struct CSwitchResult { bool ThereIs; bool WithMinus; UStringVector PostStrings; int PostCharIndex; CSwitchResult(): ThereIs(false) {}; }; class CParser { int _numSwitches; CSwitchResult *_switches; bool ParseString(const UString &s, const CSwitchForm *switchForms); public: UStringVector NonSwitchStrings; CParser(int numSwitches); ~CParser(); void ParseStrings(const CSwitchForm *switchForms, const UStringVector &commandStrings); const CSwitchResult& operator[](size_t index) const; }; ///////////////////////////////// // Command parsing procedures struct CCommandForm { wchar_t *IDString; bool PostStringMode; }; // Returns: Index of form and postString; -1, if there is no match int ParseCommand(int numCommandForms, const CCommandForm *commandForms, const UString &commandString, UString &postString); struct CCommandSubCharsSet { wchar_t *Chars; bool EmptyAllowed; }; // Returns: indices of finded chars; -1 if there is no match bool ParseSubCharsCommand(int numForms, const CCommandSubCharsSet *forms, const UString &commandString, CIntVector &indices); } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Defs.h ================================================ // Common/Defs.h #ifndef __COMMON_DEFS_H #define __COMMON_DEFS_H template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; } template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; } template <class T> inline int MyCompare(T a, T b) { return a < b ? -1 : (a == b ? 0 : 1); } inline int BoolToInt(bool value) { return (value ? 1: 0); } inline bool IntToBool(int value) { return (value != 0); } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/MyCom.h ================================================ // MyCom.h #ifndef __MYCOM_H #define __MYCOM_H #include "MyWindows.h" #define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } template <class T> class CMyComPtr { T* _p; public: // typedef T _PtrClass; CMyComPtr() { _p = NULL;} CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } CMyComPtr(const CMyComPtr<T>& lp) { if ((_p = lp._p) != NULL) _p->AddRef(); } ~CMyComPtr() { if (_p) _p->Release(); } void Release() { if (_p) { _p->Release(); _p = NULL; } } operator T*() const { return (T*)_p; } // T& operator*() const { return *_p; } T** operator&() { return &_p; } T* operator->() const { return _p; } T* operator=(T* p) { if (p != 0) p->AddRef(); if (_p) _p->Release(); _p = p; return p; } T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } bool operator!() const { return (_p == NULL); } // bool operator==(T* pT) const { return _p == pT; } // Compare two objects for equivalence void Attach(T* p2) { Release(); _p = p2; } T* Detach() { T* pt = _p; _p = NULL; return pt; } #ifdef _WIN32 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); } #endif /* HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(_p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); return hr; } */ template <class Q> HRESULT QueryInterface(REFGUID iid, Q** pp) const { return _p->QueryInterface(iid, (void**)pp); } }; ////////////////////////////////////////////////////////// class CMyComBSTR { public: BSTR m_str; CMyComBSTR() { m_str = NULL; } CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } /* CMyComBSTR(REFGUID src) { LPOLESTR szGuid; StringFromCLSID(src, &szGuid); m_str = ::SysAllocString(szGuid); CoTaskMemFree(szGuid); } */ ~CMyComBSTR() { ::SysFreeString(m_str); } CMyComBSTR& operator=(const CMyComBSTR& src) { if (m_str != src.m_str) { if (m_str) ::SysFreeString(m_str); m_str = src.MyCopy(); } return *this; } CMyComBSTR& operator=(LPCOLESTR pSrc) { ::SysFreeString(m_str); m_str = ::SysAllocString(pSrc); return *this; } unsigned int Length() const { return ::SysStringLen(m_str); } operator BSTR() const { return m_str; } BSTR* operator&() { return &m_str; } BSTR MyCopy() const { int byteLen = ::SysStringByteLen(m_str); BSTR res = ::SysAllocStringByteLen(NULL, byteLen); memmove(res, m_str, byteLen); return res; } void Attach(BSTR src) { m_str = src; } BSTR Detach() { BSTR s = m_str; m_str = NULL; return s; } void Empty() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const { return (m_str == NULL); } }; ////////////////////////////////////////////////////////// class CMyUnknownImp { public: ULONG __m_RefCount; CMyUnknownImp(): __m_RefCount(0) {} }; #define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ (REFGUID iid, void **outObject) { #define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ { *outObject = (void *)(i *)this; AddRef(); return S_OK; } #define MY_QUERYINTERFACE_END return E_NOINTERFACE; } #define MY_ADDREF_RELEASE \ STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ return __m_RefCount; delete this; return 0; } #define MY_UNKNOWN_IMP_SPEC(i) \ MY_QUERYINTERFACE_BEGIN \ i \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ MY_QUERYINTERFACE_END \ MY_ADDREF_RELEASE #define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i) \ ) #define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ ) #define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ ) #define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ ) #define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ MY_QUERYINTERFACE_ENTRY(i1) \ MY_QUERYINTERFACE_ENTRY(i2) \ MY_QUERYINTERFACE_ENTRY(i3) \ MY_QUERYINTERFACE_ENTRY(i4) \ MY_QUERYINTERFACE_ENTRY(i5) \ ) #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/MyGuidDef.h ================================================ // Common/MyGuidDef.h #ifndef GUID_DEFINED #define GUID_DEFINED #include "Types.h" typedef struct { UInt32 Data1; UInt16 Data2; UInt16 Data3; unsigned char Data4[8]; } GUID; #ifdef __cplusplus #define REFGUID const GUID & #else #define REFGUID const GUID * #endif #define REFCLSID REFGUID #define REFIID REFGUID #ifdef __cplusplus inline bool operator==(REFGUID g1, REFGUID g2) { for (int i = 0; i < (int)sizeof(g1); i++) if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) return false; return true; } inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } #endif #ifdef __cplusplus #define MY_EXTERN_C extern "C" #else #define MY_EXTERN_C extern #endif #endif // GUID_DEFINED #ifdef DEFINE_GUID #undef DEFINE_GUID #endif #ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ MY_EXTERN_C const GUID name #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/MyInitGuid.h ================================================ // Common/MyInitGuid.h #ifndef __COMMON_MYINITGUID_H #define __COMMON_MYINITGUID_H #ifdef _WIN32 #include <initguid.h> #else #define INITGUID #include "MyGuidDef.h" #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/MyUnknown.h ================================================ // MyUnknown.h #ifndef __MYUNKNOWN_H #define __MYUNKNOWN_H #ifdef _WIN32 #ifdef _WIN32_WCE #if (_WIN32_WCE > 300) #include <basetyps.h> #else #define MIDL_INTERFACE(x) struct #endif #else #include <basetyps.h> #endif #include <unknwn.h> #else #include "MyWindows.h" #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/MyWindows.h ================================================ // MyWindows.h #ifndef __MYWINDOWS_H #define __MYWINDOWS_H #ifdef _WIN32 #include <windows.h> #else #include <stddef.h> // for wchar_t #include <string.h> #include "MyGuidDef.h" typedef char CHAR; typedef unsigned char UCHAR; typedef unsigned char BYTE; typedef short SHORT; typedef unsigned short USHORT; typedef unsigned short WORD; typedef short VARIANT_BOOL; typedef int INT; typedef Int32 INT32; typedef unsigned int UINT; typedef UInt32 UINT32; typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit typedef UINT32 ULONG; typedef UINT32 DWORD; typedef Int64 LONGLONG; typedef UInt64 ULONGLONG; typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; typedef const CHAR *LPCSTR; typedef CHAR TCHAR; typedef const TCHAR *LPCTSTR; typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef const WCHAR *LPCWSTR; typedef OLECHAR *BSTR; typedef const OLECHAR *LPCOLESTR; typedef OLECHAR *LPOLESTR; typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; }FILETIME; #define HRESULT LONG #define FAILED(Status) ((HRESULT)(Status)<0) typedef ULONG PROPID; typedef LONG SCODE; #define S_OK ((HRESULT)0x00000000L) #define S_FALSE ((HRESULT)0x00000001L) #define E_NOINTERFACE ((HRESULT)0x80004002L) #define E_ABORT ((HRESULT)0x80004004L) #define E_FAIL ((HRESULT)0x80004005L) #define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) #define E_INVALIDARG ((HRESULT)0x80070057L) #ifdef _MSC_VER #define STDMETHODCALLTYPE __stdcall #else #define STDMETHODCALLTYPE #endif #define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f #define STDMETHOD(f) STDMETHOD_(HRESULT, f) #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define STDMETHODIMP STDMETHODIMP_(HRESULT) #define PURE = 0 #define MIDL_INTERFACE(x) struct struct IUnknown { STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; STDMETHOD_(ULONG, AddRef)() PURE; STDMETHOD_(ULONG, Release)() PURE; }; typedef IUnknown *LPUNKNOWN; #define VARIANT_TRUE ((VARIANT_BOOL)-1) #define VARIANT_FALSE ((VARIANT_BOOL)0) enum VARENUM { VT_EMPTY = 0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_FILETIME = 64 }; typedef unsigned short VARTYPE; typedef WORD PROPVAR_PAD1; typedef WORD PROPVAR_PAD2; typedef WORD PROPVAR_PAD3; typedef struct tagPROPVARIANT { VARTYPE vt; PROPVAR_PAD1 wReserved1; PROPVAR_PAD2 wReserved2; PROPVAR_PAD3 wReserved3; union { CHAR cVal; UCHAR bVal; SHORT iVal; USHORT uiVal; LONG lVal; ULONG ulVal; INT intVal; UINT uintVal; LARGE_INTEGER hVal; ULARGE_INTEGER uhVal; VARIANT_BOOL boolVal; SCODE scode; FILETIME filetime; BSTR bstrVal; }; } PROPVARIANT; typedef PROPVARIANT tagVARIANT; typedef tagVARIANT VARIANT; typedef VARIANT VARIANTARG; MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); MY_EXTERN_C void SysFreeString(BSTR bstr); MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); MY_EXTERN_C UINT SysStringLen(BSTR bstr); MY_EXTERN_C DWORD GetLastError(); MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); #define CP_ACP 0 #define CP_OEMCP 1 typedef enum tagSTREAM_SEEK { STREAM_SEEK_SET = 0, STREAM_SEEK_CUR = 1, STREAM_SEEK_END = 2 } STREAM_SEEK; #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/NewHandler.cpp ================================================ // NewHandler.cpp #include "StdAfx.h" #include <stdlib.h> #include "NewHandler.h" // #define DEBUG_MEMORY_LEAK #ifndef DEBUG_MEMORY_LEAK void * #ifdef _MSC_VER __cdecl #endif operator new(size_t size) { // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); void *p = ::malloc(size); if (p == 0) throw CNewException(); return p; } void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw() { /* if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p); */ ::free(p); } #else #pragma init_seg(lib) const int kDebugSize = 1000000; static void *a[kDebugSize]; static int index = 0; static int numAllocs = 0; void * __cdecl operator new(size_t size) { numAllocs++; void *p = HeapAlloc(GetProcessHeap(), 0, size); if (index == 40) { int t = 1; } if (index < kDebugSize) { a[index] = p; index++; } if (p == 0) throw CNewException(); printf("Alloc %6d, size = %8d\n", numAllocs, size); return p; } class CC { public: CC() { for (int i = 0; i < kDebugSize; i++) a[i] = 0; } ~CC() { for (int i = 0; i < kDebugSize; i++) if (a[i] != 0) return; } } g_CC; void __cdecl operator delete(void *p) { if (p == 0) return; /* for (int i = 0; i < index; i++) if (a[i] == p) a[i] = 0; */ HeapFree(GetProcessHeap(), 0, p); numAllocs--; printf("Free %d\n", numAllocs); } #endif /* int MemErrorVC(size_t) { throw CNewException(); // return 1; } CNewHandlerSetter::CNewHandlerSetter() { // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); } CNewHandlerSetter::~CNewHandlerSetter() { // _set_new_handler(MemErrorOldVCFunction); } */ ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/NewHandler.h ================================================ // Common/NewHandler.h #ifndef __COMMON_NEWHANDLER_H #define __COMMON_NEWHANDLER_H class CNewException {}; void #ifdef _MSC_VER __cdecl #endif operator delete(void *p) throw(); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H // #include "MyWindows.h" #include "NewHandler.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/String.cpp ================================================ // Common/String.cpp #include "StdAfx.h" #ifdef _WIN32 #include "StringConvert.h" #else #include <ctype.h> #endif #include "Common/String.h" #ifdef _WIN32 #ifndef _UNICODE wchar_t MyCharUpper(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharUpperA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t MyCharLower(wchar_t c) { if (c == 0) return 0; wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return (wchar_t)(unsigned int)res; const int kBufferSize = 4; char s[kBufferSize + 1]; int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); if (numChars == 0 || numChars > kBufferSize) return c; s[numChars] = 0; ::CharLowerA(s); ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); return c; } wchar_t * MyStringUpper(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharUpperW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeUpper(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } wchar_t * MyStringLower(wchar_t *s) { if (s == 0) return 0; wchar_t *res = CharLowerW(s); if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return res; AString a = UnicodeStringToMultiByte(s); a.MakeLower(); return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); } #endif /* inline int ConvertCompareResult(int r) { return r - 2; } int MyStringCollate(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollate(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); } int MyStringCollateNoCase(const char *s1, const char *s2) { return ConvertCompareResult(CompareStringA( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); } #endif int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { int res = CompareStringW( LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); #ifdef _UNICODE return ConvertCompareResult(res); #else if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) return ConvertCompareResult(res); return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), UnicodeStringToMultiByte(s2)); #endif } */ #else wchar_t MyCharUpper(wchar_t c) { return toupper(c); } /* int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; if (u1 == 0) return 0; } } */ #endif int MyStringCompare(const char *s1, const char *s2) { while (true) { unsigned char c1 = (unsigned char)*s1++; unsigned char c2 = (unsigned char)*s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompare(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 < c2) return -1; if (c1 > c2) return 1; if (c1 == 0) return 0; } } int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) { while (true) { wchar_t c1 = *s1++; wchar_t c2 = *s2++; if (c1 != c2) { wchar_t u1 = MyCharUpper(c1); wchar_t u2 = MyCharUpper(c2); if (u1 < u2) return -1; if (u1 > u2) return 1; } if (c1 == 0) return 0; } } #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2) { return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/String.h ================================================ // Common/String.h #ifndef __COMMON_STRING_H #define __COMMON_STRING_H #include <string.h> // #include <wchar.h> #include "Vector.h" #ifdef _WIN32 #include "MyWindows.h" #endif static const char *kTrimDefaultCharSet = " \n\t"; template <class T> inline int MyStringLen(const T *s) { int i; for (i = 0; s[i] != '\0'; i++); return i; } template <class T> inline T * MyStringCopy(T *dest, const T *src) { T *destStart = dest; while((*dest++ = *src++) != 0); return destStart; } inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) { return (p + 1); } inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) { return (p + 1); } inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) { return (p - 1); } inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) { return (p - 1); } #ifdef _WIN32 inline char* MyStringGetNextCharPointer(char *p) { return CharNextA(p); } inline const char* MyStringGetNextCharPointer(const char *p) { return CharNextA(p); } inline char* MyStringGetPrevCharPointer(char *base, char *p) { return CharPrevA(base, p); } inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) { return CharPrevA(base, p); } inline char MyCharUpper(char c) { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharUpper(wchar_t c) { return (wchar_t)CharUpperW((LPWSTR)c); } #else wchar_t MyCharUpper(wchar_t c); #endif inline char MyCharLower(char c) { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } #ifdef _UNICODE inline wchar_t MyCharLower(wchar_t c) { return (wchar_t)CharLowerW((LPWSTR)c); } #else wchar_t MyCharLower(wchar_t c); #endif inline char * MyStringUpper(char *s) { return CharUpperA(s); } #ifdef _UNICODE inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } #else wchar_t * MyStringUpper(wchar_t *s); #endif inline char * MyStringLower(char *s) { return CharLowerA(s); } #ifdef _UNICODE inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } #else wchar_t * MyStringLower(wchar_t *s); #endif #else // Standard-C wchar_t MyCharUpper(wchar_t c); #endif ////////////////////////////////////// // Compare /* #ifndef _WIN32_WCE int MyStringCollate(const char *s1, const char *s2); int MyStringCollateNoCase(const char *s1, const char *s2); #endif int MyStringCollate(const wchar_t *s1, const wchar_t *s2); int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); */ int MyStringCompare(const char *s1, const char *s2); int MyStringCompare(const wchar_t *s1, const wchar_t *s2); #ifdef _WIN32 int MyStringCompareNoCase(const char *s1, const char *s2); #endif int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); template <class T> class CStringBase { void TrimLeftWithCharSet(const CStringBase &charSet) { const T *p = _chars; while (charSet.Find(*p) >= 0 && (*p != 0)) p = GetNextCharPointer(p); Delete(0, (int)(p - _chars)); } void TrimRightWithCharSet(const CStringBase &charSet) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (charSet.Find(*p) >= 0) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = (int)(pLast - _chars); Delete(i, _length - i); } } void MoveItems(int destIndex, int srcIndex) { memmove(_chars + destIndex, _chars + srcIndex, sizeof(T) * (_length - srcIndex + 1)); } void InsertSpace(int &index, int size) { CorrectIndex(index); GrowLength(size); MoveItems(index + size, index); } static T *GetNextCharPointer(T *p) { return MyStringGetNextCharPointer(p); } static const T *GetNextCharPointer(const T *p) { return MyStringGetNextCharPointer(p); } static T *GetPrevCharPointer(T *base, T *p) { return MyStringGetPrevCharPointer(base, p); } static const T *GetPrevCharPointer(const T *base, const T *p) { return MyStringGetPrevCharPointer(base, p); } protected: T *_chars; int _length; int _capacity; void SetCapacity(int newCapacity) { int realCapacity = newCapacity + 1; if(realCapacity == _capacity) return; /* const int kMaxStringSize = 0x20000000; #ifndef _WIN32_WCE if(newCapacity > kMaxStringSize || newCapacity < _length) throw 1052337; #endif */ T *newBuffer = new T[realCapacity]; if(_capacity > 0) { for (int i = 0; i < (_length + 1); i++) newBuffer[i] = _chars[i]; delete []_chars; _chars = newBuffer; } else { _chars = newBuffer; _chars[0] = 0; } _capacity = realCapacity; } void GrowLength(int n) { int freeSize = _capacity - _length - 1; if (n <= freeSize) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 16; else delta = 4; if (freeSize + delta < n) delta = n - freeSize; SetCapacity(_capacity + delta); } void CorrectIndex(int &index) const { if (index > _length) index = _length; } public: CStringBase(): _chars(0), _length(0), _capacity(0) { SetCapacity(16 - 1); } CStringBase(T c): _chars(0), _length(0), _capacity(0) { SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; } CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) { int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); // can be optimized by memove() _length = length; } CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) { SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; } ~CStringBase() { delete []_chars; } operator const T*() const { return _chars;} // The minimum size of the character buffer in characters. // This value does not include space for a null terminator. T* GetBuffer(int minBufLength) { if(minBufLength >= _capacity) SetCapacity(minBufLength + 1); return _chars; } void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } void ReleaseBuffer(int newLength) { /* #ifndef _WIN32_WCE if(newLength >= _capacity) throw 282217; #endif */ _chars[newLength] = 0; _length = newLength; } CStringBase& operator=(T c) { Empty(); SetCapacity(1); _chars[0] = c; _chars[1] = 0; _length = 1; return *this; } CStringBase& operator=(const T *chars) { Empty(); int length = MyStringLen(chars); SetCapacity(length); MyStringCopy(_chars, chars); _length = length; return *this; } CStringBase& operator=(const CStringBase& s) { if(&s == this) return *this; Empty(); SetCapacity(s._length); MyStringCopy(_chars, s._chars); _length = s._length; return *this; } CStringBase& operator+=(T c) { GrowLength(1); _chars[_length] = c; _chars[++_length] = 0; return *this; } CStringBase& operator+=(const T *s) { int len = MyStringLen(s); GrowLength(len); MyStringCopy(_chars + _length, s); _length += len; return *this; } CStringBase& operator+=(const CStringBase &s) { GrowLength(s._length); MyStringCopy(_chars + _length, s._chars); _length += s._length; return *this; } void Empty() { _length = 0; _chars[0] = 0; } int Length() const { return _length; } bool IsEmpty() const { return (_length == 0); } CStringBase Mid(int startIndex) const { return Mid(startIndex, _length - startIndex); } CStringBase Mid(int startIndex, int count ) const { if (startIndex + count > _length) count = _length - startIndex; if (startIndex == 0 && startIndex + count == _length) return *this; CStringBase<T> result; result.SetCapacity(count); // MyStringNCopy(result._chars, _chars + startIndex, count); for (int i = 0; i < count; i++) result._chars[i] = _chars[startIndex + i]; result._chars[count] = 0; result._length = count; return result; } CStringBase Left(int count) const { return Mid(0, count); } CStringBase Right(int count) const { if (count > _length) count = _length; return Mid(_length - count, count); } void MakeUpper() { MyStringUpper(_chars); } void MakeLower() { MyStringLower(_chars); } int Compare(const CStringBase& s) const { return MyStringCompare(_chars, s._chars); } int CompareNoCase(const CStringBase& s) const { return MyStringCompareNoCase(_chars, s._chars); } /* int Collate(const CStringBase& s) const { return MyStringCollate(_chars, s._chars); } int CollateNoCase(const CStringBase& s) const { return MyStringCollateNoCase(_chars, s._chars); } */ int Find(T c) const { return Find(c, 0); } int Find(T c, int startIndex) const { T *p = _chars + startIndex; while (true) { if (*p == c) return (int)(p - _chars); if (*p == 0) return -1; p = GetNextCharPointer(p); } } int Find(const CStringBase &s) const { return Find(s, 0); } int Find(const CStringBase &s, int startIndex) const { if (s.IsEmpty()) return startIndex; for (; startIndex < _length; startIndex++) { int j; for (j = 0; j < s._length && startIndex + j < _length; j++) if (_chars[startIndex+j] != s._chars[j]) break; if (j == s._length) return startIndex; } return -1; } int ReverseFind(T c) const { if (_length == 0) return -1; T *p = _chars + _length - 1; while (true) { if (*p == c) return (int)(p - _chars); if (p == _chars) return -1; p = GetPrevCharPointer(_chars, p); } } int FindOneOf(const CStringBase &s) const { for(int i = 0; i < _length; i++) if (s.Find(_chars[i]) >= 0) return i; return -1; } void TrimLeft(T c) { const T *p = _chars; while (c == *p) p = GetNextCharPointer(p); Delete(0, p - _chars); } private: CStringBase GetTrimDefaultCharSet() { CStringBase<T> charSet; for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / sizeof(kTrimDefaultCharSet[0])); i++) charSet += (T)kTrimDefaultCharSet[i]; return charSet; } public: void TrimLeft() { TrimLeftWithCharSet(GetTrimDefaultCharSet()); } void TrimRight() { TrimRightWithCharSet(GetTrimDefaultCharSet()); } void TrimRight(T c) { const T *p = _chars; const T *pLast = NULL; while (*p != 0) { if (*p == c) { if (pLast == NULL) pLast = p; } else pLast = NULL; p = GetNextCharPointer(p); } if(pLast != NULL) { int i = pLast - _chars; Delete(i, _length - i); } } void Trim() { TrimRight(); TrimLeft(); } int Insert(int index, T c) { InsertSpace(index, 1); _chars[index] = c; _length++; return _length; } int Insert(int index, const CStringBase &s) { CorrectIndex(index); if (s.IsEmpty()) return _length; int numInsertChars = s.Length(); InsertSpace(index, numInsertChars); for(int i = 0; i < numInsertChars; i++) _chars[index + i] = s[i]; _length += numInsertChars; return _length; } // !!!!!!!!!!!!!!! test it if newChar = '\0' int Replace(T oldChar, T newChar) { if (oldChar == newChar) return 0; int number = 0; int pos = 0; while (pos < Length()) { pos = Find(oldChar, pos); if (pos < 0) break; _chars[pos] = newChar; pos++; number++; } return number; } int Replace(const CStringBase &oldString, const CStringBase &newString) { if (oldString.IsEmpty()) return 0; if (oldString == newString) return 0; int oldStringLength = oldString.Length(); int newStringLength = newString.Length(); int number = 0; int pos = 0; while (pos < _length) { pos = Find(oldString, pos); if (pos < 0) break; Delete(pos, oldStringLength); Insert(pos, newString); pos += newStringLength; number++; } return number; } int Delete(int index, int count = 1 ) { if (index + count > _length) count = _length - index; if (count > 0) { MoveItems(index, index + count); _length -= count; } return _length; } }; template <class T> CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2) { CStringBase<T> result(s1); result += s2; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, T c) { CStringBase<T> result(s); result += c; return result; } template <class T> CStringBase<T> operator+(T c, const CStringBase<T>& s) { CStringBase<T> result(c); result += s; return result; } template <class T> CStringBase<T> operator+(const CStringBase<T>& s, const T * chars) { CStringBase<T> result(s); result += chars; return result; } template <class T> CStringBase<T> operator+(const T * chars, const CStringBase<T>& s) { CStringBase<T> result(chars); result += s; return result; } template <class T> bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) < 0); } template <class T> bool operator==(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) == 0); } template <class T> bool operator==(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) == 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2) { return (s1.Compare(s2) != 0); } template <class T> bool operator!=(const T *s1, const CStringBase<T>& s2) { return (s2.Compare(s1) != 0); } template <class T> bool operator!=(const CStringBase<T>& s1, const T *s2) { return (s1.Compare(s2) != 0); } typedef CStringBase<char> AString; typedef CStringBase<wchar_t> UString; typedef CObjectVector<AString> AStringVector; typedef CObjectVector<UString> UStringVector; #ifdef _UNICODE typedef UString CSysString; #else typedef AString CSysString; #endif typedef CObjectVector<CSysString> CSysStringVector; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/StringConvert.cpp ================================================ // Common/StringConvert.cpp #include "StdAfx.h" #include "StringConvert.h" #ifndef _WIN32 #include <stdlib.h> #endif #ifdef _WIN32 UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; if(!srcString.IsEmpty()) { int numChars = MultiByteToWideChar(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(srcString.Length()), srcString.Length() + 1); #ifndef _WIN32_WCE if(numChars == 0) throw 282228; #endif resultString.ReleaseBuffer(numChars); } return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 2; int numChars = WideCharToMultiByte(codePage, 0, srcString, srcString.Length(), resultString.GetBuffer(numRequiredBytes), numRequiredBytes + 1, NULL, NULL); #ifndef _WIN32_WCE if(numChars == 0) throw 282229; #endif resultString.ReleaseBuffer(numChars); } return resultString; } #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString) { AString result; CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); result.ReleaseBuffer(); return result; } #endif #else UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) { UString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += wchar_t(srcString[i]); /* if(!srcString.IsEmpty()) { int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { AString resultString; for (int i = 0; i < srcString.Length(); i++) resultString += char(srcString[i]); /* if(!srcString.IsEmpty()) { int numRequiredBytes = srcString.Length() * 6 + 1; int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); if (numChars < 0) throw "Your environment does not support UNICODE"; resultString.ReleaseBuffer(numChars); } */ return resultString; } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/StringConvert.h ================================================ // Common/StringConvert.h #ifndef __COMMON_STRINGCONVERT_H #define __COMMON_STRINGCONVERT_H #include "MyWindows.h" #include "Common/String.h" #include "Types.h" UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString) { return unicodeString; } inline UString GetUnicodeString(const AString &ansiString) { return MultiByteToUnicodeString(ansiString); } inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage); } inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) { return unicodeString; } inline const UString& GetUnicodeString(const UString &unicodeString, UINT) { return unicodeString; } inline const char* GetAnsiString(const char* ansiString) { return ansiString; } inline const AString& GetAnsiString(const AString &ansiString) { return ansiString; } inline AString GetAnsiString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline const char* GetOemString(const char* oemString) { return oemString; } inline const AString& GetOemString(const AString &oemString) { return oemString; } inline AString GetOemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } #ifdef _UNICODE inline const wchar_t* GetSystemString(const wchar_t* unicodeString) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString) { return unicodeString;} inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage) { return unicodeString;} inline const UString& GetSystemString(const UString &unicodeString, UINT codePage) { return unicodeString;} inline UString GetSystemString(const AString &multiByteString, UINT codePage) { return MultiByteToUnicodeString(multiByteString, codePage);} inline UString GetSystemString(const AString &multiByteString) { return MultiByteToUnicodeString(multiByteString);} #else inline const char* GetSystemString(const char *ansiString) { return ansiString; } inline const AString& GetSystemString(const AString &multiByteString, UINT) { return multiByteString; } inline const char * GetSystemString(const char *multiByteString, UINT) { return multiByteString; } inline AString GetSystemString(const UString &unicodeString) { return UnicodeStringToMultiByte(unicodeString); } inline AString GetSystemString(const UString &unicodeString, UINT codePage) { return UnicodeStringToMultiByte(unicodeString, codePage); } #endif #ifndef _WIN32_WCE AString SystemStringToOemString(const CSysString &srcString); #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/StringToInt.cpp ================================================ // Common/StringToInt.cpp #include "StdAfx.h" #include "StringToInt.h" UInt64 ConvertStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } UInt64 ConvertOctStringToUInt64(const char *s, const char **end) { UInt64 result = 0; while(true) { char c = *s; if (c < '0' || c > '7') { if (end != NULL) *end = s; return result; } result <<= 3; result += (c - '0'); s++; } } UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) { UInt64 result = 0; while(true) { wchar_t c = *s; if (c < '0' || c > '9') { if (end != NULL) *end = s; return result; } result *= 10; result += (c - '0'); s++; } } Int64 ConvertStringToInt64(const char *s, const char **end) { if (*s == '-') return -(Int64)ConvertStringToUInt64(s + 1, end); return ConvertStringToUInt64(s, end); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/StringToInt.h ================================================ // Common/StringToInt.h #ifndef __COMMON_STRINGTOINT_H #define __COMMON_STRINGTOINT_H #include <string.h> #include "Types.h" UInt64 ConvertStringToUInt64(const char *s, const char **end); UInt64 ConvertOctStringToUInt64(const char *s, const char **end); UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); Int64 ConvertStringToInt64(const char *s, const char **end); #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Types.h ================================================ // Common/Types.h #ifndef __COMMON_TYPES_H #define __COMMON_TYPES_H typedef unsigned char Byte; typedef short Int16; typedef unsigned short UInt16; typedef int Int32; typedef unsigned int UInt32; #ifdef _MSC_VER typedef __int64 Int64; typedef unsigned __int64 UInt64; #else typedef long long int Int64; typedef unsigned long long int UInt64; #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Vector.cpp ================================================ // Common/Vector.cpp #include "StdAfx.h" #include <string.h> #include "Vector.h" CBaseRecordVector::~CBaseRecordVector() { delete []((unsigned char *)_items); } void CBaseRecordVector::Clear() { DeleteFrom(0); } void CBaseRecordVector::DeleteBack() { Delete(_size - 1); } void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); } void CBaseRecordVector::ReserveOnePosition() { if(_size != _capacity) return; int delta; if (_capacity > 64) delta = _capacity / 2; else if (_capacity > 8) delta = 8; else delta = 4; Reserve(_capacity + delta); } void CBaseRecordVector::Reserve(int newCapacity) { if(newCapacity <= _capacity) return; /* #ifndef _DEBUG static const unsigned int kMaxVectorSize = 0xF0000000; if(newCapacity < _size || ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize) throw 1052354; #endif */ unsigned char *p = new unsigned char[newCapacity * _itemSize]; int numRecordsToMove = _capacity; memmove(p, _items, _itemSize * numRecordsToMove); delete [](unsigned char *)_items; _items = p; _capacity = newCapacity; } void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) { memmove(((unsigned char *)_items) + destIndex * _itemSize, ((unsigned char *)_items) + srcIndex * _itemSize, _itemSize * (_size - srcIndex)); } void CBaseRecordVector::InsertOneItem(int index) { ReserveOnePosition(); MoveItems(index + 1, index); _size++; } void CBaseRecordVector::Delete(int index, int num) { TestIndexAndCorrectNum(index, num); if (num > 0) { MoveItems(index, index + num); _size -= num; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Common/Vector.h ================================================ // Common/Vector.h #ifndef __COMMON_VECTOR_H #define __COMMON_VECTOR_H #include "Defs.h" class CBaseRecordVector { void MoveItems(int destIndex, int srcIndex); protected: int _capacity; int _size; void *_items; size_t _itemSize; void ReserveOnePosition(); void InsertOneItem(int index); void TestIndexAndCorrectNum(int index, int &num) const { if (index + num > _size) num = _size - index; } public: CBaseRecordVector(size_t itemSize): _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} virtual ~CBaseRecordVector(); int Size() const { return _size; } bool IsEmpty() const { return (_size == 0); } void Reserve(int newCapacity); virtual void Delete(int index, int num = 1); void Clear(); void DeleteFrom(int index); void DeleteBack(); }; template <class T> class CRecordVector: public CBaseRecordVector { public: CRecordVector():CBaseRecordVector(sizeof(T)){}; CRecordVector(const CRecordVector &v): CBaseRecordVector(sizeof(T)) { *this = v;} CRecordVector& operator=(const CRecordVector &v) { Clear(); return (*this += v); } CRecordVector& operator+=(const CRecordVector &v) { int size = v.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(v[i]); return *this; } int Add(T item) { ReserveOnePosition(); ((T *)_items)[_size] = item; return _size++; } void Insert(int index, T item) { InsertOneItem(index); ((T *)_items)[index] = item; } // T* GetPointer() const { return (T*)_items; } // operator const T *() const { return _items; }; const T& operator[](int index) const { return ((T *)_items)[index]; } T& operator[](int index) { return ((T *)_items)[index]; } const T& Front() const { return operator[](0); } T& Front() { return operator[](0); } const T& Back() const { return operator[](_size - 1); } T& Back() { return operator[](_size - 1); } void Swap(int i, int j) { T temp = operator[](i); operator[](i) = operator[](j); operator[](j) = temp; } void Sort(int left, int right) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (operator[](i) < operator[](left)) Swap(++last, i); Swap(left, last); Sort(left, last); Sort(last + 1, right); } void Sort() { Sort(0, Size()); } void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) { if (right - left < 2) return; Swap(left, (left + right) / 2); int last = left; for (int i = left; i < right; i++) if (compare(&operator[](i), &operator[](left), param) < 0) Swap(++last, i); Swap(left, last); Sort(left, last, compare, param); Sort(last + 1, right, compare, param); } void Sort(int (*compare)(const T*, const T*, void *), void *param) { Sort(0, Size(), compare, param); } }; typedef CRecordVector<int> CIntVector; typedef CRecordVector<unsigned int> CUIntVector; typedef CRecordVector<bool> CBoolVector; typedef CRecordVector<unsigned char> CByteVector; typedef CRecordVector<void *> CPointerVector; template <class T> class CObjectVector: public CPointerVector { public: CObjectVector(){}; ~CObjectVector() { Clear(); } CObjectVector(const CObjectVector &objectVector) { *this = objectVector; } CObjectVector& operator=(const CObjectVector &objectVector) { Clear(); return (*this += objectVector); } CObjectVector& operator+=(const CObjectVector &objectVector) { int size = objectVector.Size(); Reserve(Size() + size); for(int i = 0; i < size; i++) Add(objectVector[i]); return *this; } const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } T& Front() { return operator[](0); } const T& Front() const { return operator[](0); } T& Back() { return operator[](_size - 1); } const T& Back() const { return operator[](_size - 1); } int Add(const T& item) { return CPointerVector::Add(new T(item)); } void Insert(int index, const T& item) { CPointerVector::Insert(index, new T(item)); } virtual void Delete(int index, int num = 1) { TestIndexAndCorrectNum(index, num); for(int i = 0; i < num; i++) delete (T *)(((void **)_items)[index + i]); CPointerVector::Delete(index, num); } int Find(const T& item) const { for(int i = 0; i < Size(); i++) if (item == (*this)[i]) return i; return -1; } int FindInSorted(const T& item) const { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) return mid; if (item < midValue) right = mid; else left = mid + 1; } return -1; } int AddToSorted(const T& item) { int left = 0, right = Size(); while (left != right) { int mid = (left + right) / 2; const T& midValue = (*this)[mid]; if (item == midValue) { right = mid + 1; break; } if (item < midValue) right = mid; else left = mid + 1; } Insert(right, item); return right; } void Sort(int (*compare)(void *const *, void *const *, void *), void *param) { CPointerVector::Sort(compare, param); } static int CompareObjectItems(void *const *a1, void *const *a2, void *param) { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Windows/Defs.h ================================================ // Windows/Defs.h #ifndef __WINDOWS_DEFS_H #define __WINDOWS_DEFS_H inline bool BOOLToBool(BOOL value) { return (value != FALSE); } inline BOOL BoolToBOOL(bool value) { return (value ? TRUE: FALSE); } inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) { return (value ? VARIANT_TRUE: VARIANT_FALSE); } inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) { return (value != VARIANT_FALSE); } #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Windows/FileIO.cpp ================================================ // Windows/FileIO.cpp #include "StdAfx.h" #include "FileIO.h" #include "Defs.h" #ifndef _UNICODE #include "../Common/StringConvert.h" #endif #ifndef _UNICODE extern bool g_IsNT; #endif namespace NWindows { namespace NFile { namespace NIO { CFileBase::~CFileBase() { Close(); } bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { Close(); _handle = ::CreateFile(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } #ifndef _UNICODE bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { if (g_IsNT) { Close(); _handle = ::CreateFileW(fileName, desiredAccess, shareMode, (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE) NULL); return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); } return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), desiredAccess, shareMode, creationDisposition, flagsAndAttributes); } #endif bool CFileBase::Close() { if(!_fileIsOpen) return true; bool result = BOOLToBool(::CloseHandle(_handle)); _fileIsOpen = !result; return result; } bool CFileBase::GetPosition(UInt64 &position) const { return Seek(0, FILE_CURRENT, position); } bool CFileBase::GetLength(UInt64 &length) const { DWORD sizeHigh; DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); if(sizeLow == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; length = (((UInt64)sizeHigh) << 32) + sizeLow; return true; } bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const { LARGE_INTEGER value; value.QuadPart = distanceToMove; value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); if (value.LowPart == 0xFFFFFFFF) if(::GetLastError() != NO_ERROR) return false; newPosition = value.QuadPart; return true; } bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) { return Seek(position, FILE_BEGIN, newPosition); } bool CFileBase::SeekToBegin() { UInt64 newPosition; return Seek(0, newPosition); } bool CFileBase::SeekToEnd(UInt64 &newPosition) { return Seek(0, FILE_END, newPosition); } bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const { BY_HANDLE_FILE_INFORMATION winFileInfo; if(!::GetFileInformationByHandle(_handle, &winFileInfo)) return false; fileInfo.Attributes = winFileInfo.dwFileAttributes; fileInfo.CreationTime = winFileInfo.ftCreationTime; fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; return true; } ///////////////////////// // CInFile bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCTSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #ifndef _UNICODE bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } bool CInFile::Open(LPCWSTR fileName) { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } #endif // ReadFile and WriteFile functions in Windows have BUG: // If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) // from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES // (Insufficient system resources exist to complete the requested service). static UInt32 kChunkSizeMax = (1 << 24); bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = ReadPart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (void *)((unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } ///////////////////////// // COutFile bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } static inline DWORD GetCreationDisposition(bool createAlways) { return createAlways? CREATE_ALWAYS: CREATE_NEW; } bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCTSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #ifndef _UNICODE bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } bool COutFile::Create(LPCWSTR fileName, bool createAlways) { return Open(fileName, GetCreationDisposition(createAlways)); } #endif bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) { return SetTime(NULL, NULL, lastWriteTime); } bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) { if (size > kChunkSizeMax) size = kChunkSizeMax; DWORD processedLoc = 0; bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); processedSize = (UInt32)processedLoc; return res; } bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) { processedSize = 0; do { UInt32 processedLoc = 0; bool res = WritePart(data, size, processedLoc); processedSize += processedLoc; if (!res) return false; if (processedLoc == 0) return true; data = (const void *)((const unsigned char *)data + processedLoc); size -= processedLoc; } while (size > 0); return true; } bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } bool COutFile::SetLength(UInt64 length) { UInt64 newPosition; if(!Seek(length, newPosition)) return false; if(newPosition != length) return false; return SetEndOfFile(); } }}} ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Windows/FileIO.h ================================================ // Windows/FileIO.h #ifndef __WINDOWS_FILEIO_H #define __WINDOWS_FILEIO_H #include "../Common/Types.h" namespace NWindows { namespace NFile { namespace NIO { struct CByHandleFileInfo { DWORD Attributes; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; DWORD VolumeSerialNumber; UInt64 Size; DWORD NumberOfLinks; UInt64 FileIndex; }; class CFileBase { protected: bool _fileIsOpen; HANDLE _handle; bool Create(LPCTSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #ifndef _UNICODE bool Create(LPCWSTR fileName, DWORD desiredAccess, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); #endif public: CFileBase(): _fileIsOpen(false){}; virtual ~CFileBase(); virtual bool Close(); bool GetPosition(UInt64 &position) const; bool GetLength(UInt64 &length) const; bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; bool Seek(UInt64 position, UInt64 &newPosition); bool SeekToBegin(); bool SeekToEnd(UInt64 &newPosition); bool GetFileInformation(CByHandleFileInfo &fileInfo) const; }; class CInFile: public CFileBase { public: bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName); #endif bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); bool Read(void *data, UInt32 size, UInt32 &processedSize); }; class COutFile: public CFileBase { // DWORD m_CreationDisposition; public: // COutFile(): m_CreationDisposition(CREATE_NEW){}; bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCTSTR fileName, DWORD creationDisposition); bool Create(LPCTSTR fileName, bool createAlways); #ifndef _UNICODE bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); bool Open(LPCWSTR fileName, DWORD creationDisposition); bool Create(LPCWSTR fileName, bool createAlways); #endif /* void SetOpenCreationDisposition(DWORD creationDisposition) { m_CreationDisposition = creationDisposition; } void SetOpenCreationDispositionCreateAlways() { m_CreationDisposition = CREATE_ALWAYS; } */ bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); bool SetLastWriteTime(const FILETIME *lastWriteTime); bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); bool Write(const void *data, UInt32 size, UInt32 &processedSize); bool SetEndOfFile(); bool SetLength(UInt64 length); }; }}} #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/C/Windows/StdAfx.h ================================================ // StdAfx.h #ifndef __STDAFX_H #define __STDAFX_H #include "../Common/MyWindows.h" #include "../Common/NewHandler.h" #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CPL.html ================================================ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML><HEAD><TITLE>Common Public License - v 1.0

Common Public License - v 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

    a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
    b) in the case of each subsequent Contributor:
    i) changes to the Program, and
    ii) additions to the Program;
    where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

    a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
    b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
    c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
    d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

    a) it complies with the terms and conditions of this Agreement; and
    b) its license agreement:
    i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
    ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
    iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
    iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

    a) it must be made available under this Agreement; and
    b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Common/CRC.cs ================================================ // Common/CRC.cs namespace SevenZip { class CRC { public static readonly uint[] Table; static CRC() { Table = new uint[256]; const uint kPoly = 0xEDB88320; for (uint i = 0; i < 256; i++) { uint r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >> 1) ^ kPoly; else r >>= 1; Table[i] = r; } } uint _value = 0xFFFFFFFF; public void Init() { _value = 0xFFFFFFFF; } public void UpdateByte(byte b) { _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint i = 0; i < size; i++) _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); } public uint GetDigest() { return _value ^ 0xFFFFFFFF; } static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC crc = new CRC(); // crc.Init(); crc.Update(data, offset, size); return crc.GetDigest(); } static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return (CalculateDigest(data, offset, size) == digest); } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Common/CommandLineParser.cs ================================================ // CommandLineParser.cs using System; using System.Collections; namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen): this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi): this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); SwitchResult[] _switches; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) _switches[i] = new SwitchResult(); } bool ParseString(string srcString, SwitchForm[] switchForms) { int len = srcString.Length; if (len == 0) return false; int pos = 0; if (!IsItSwitchChar(srcString[pos])) return false; while (pos < len) { if (IsItSwitchChar(srcString[pos])) pos++; const int kNoLen = -1; int matchedSwitchIndex = 0; int maxLen = kNoLen; for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) { int switchLen = switchForms[switchIndex].IDString.Length; if (switchLen <= maxLen || pos + switchLen > len) continue; if (String.Compare(switchForms[switchIndex].IDString, 0, srcString, pos, switchLen, true) == 0) { matchedSwitchIndex = switchIndex; maxLen = switchLen; } } if (maxLen == kNoLen) throw new Exception("maxLen == kNoLen"); SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; SwitchForm switchForm = switchForms[matchedSwitchIndex]; if ((!switchForm.Multi) && matchedSwitch.ThereIs) throw new Exception("switch must be single"); matchedSwitch.ThereIs = true; pos += maxLen; int tailSize = len - pos; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: { if (tailSize == 0) matchedSwitch.WithMinus = false; else { matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); if (matchedSwitch.WithMinus) pos++; } break; } case SwitchType.PostChar: { if (tailSize < switchForm.MinLen) throw new Exception("switch is not full"); string charSet = switchForm.PostCharSet; const int kEmptyCharValue = -1; if (tailSize == 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { int index = charSet.IndexOf(srcString[pos]); if (index < 0) matchedSwitch.PostCharIndex = kEmptyCharValue; else { matchedSwitch.PostCharIndex = index; pos++; } } break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (tailSize < minLen) throw new Exception("switch is not full"); if (type == SwitchType.UnLimitedPostString) { matchedSwitch.PostStrings.Add(srcString.Substring(pos)); return true; } String stringSwitch = srcString.Substring(pos, minLen); pos += minLen; for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) { char c = srcString[pos]; if (IsItSwitchChar(c)) break; stringSwitch += c; } matchedSwitch.PostStrings.Add(stringSwitch); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int numCommandStrings = commandStrings.Length; bool stopSwitch = false; for (int i = 0; i < numCommandStrings; i++) { string s = commandStrings[i]; if (stopSwitch) NonSwitchStrings.Add(s); else if (s == kStopSwitchParsing) stopSwitch = true; else if (!ParseString(s, switchForms)) NonSwitchStrings.Add(s); } } public SwitchResult this[int index] { get { return _switches[index]; } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string id = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(id) == 0) { postString = commandString.Substring(id.Length); return i; } } else if (commandString == id) { postString = ""; return i; } } postString = ""; return -1; } static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int numUsedChars = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet charsSet = forms[i]; int currentIndex = -1; int len = charsSet.Chars.Length; for (int j = 0; j < len; j++) { char c = charsSet.Chars[j]; int newIndex = commandString.IndexOf(c); if (newIndex >= 0) { if (currentIndex >= 0) return false; if (commandString.IndexOf(c, newIndex + 1) >= 0) return false; currentIndex = j; numUsedChars++; } } if (currentIndex == -1 && !charsSet.EmptyAllowed) return false; indices.Add(currentIndex); } return (numUsedChars == commandString.Length); } const char kSwitchID1 = '-'; const char kSwitchID2 = '/'; const char kSwitchMinus = '-'; const string kStopSwitchParsing = "--"; static bool IsItSwitchChar(char c) { return (c == kSwitchID1 || c == kSwitchID2); } } public class CommandForm { public string IDString = ""; public bool PostStringMode = false; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed = false; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Common/InBuffer.cs ================================================ // InBuffer.cs namespace SevenZip.Buffer { public class InBuffer { byte[] m_Buffer; uint m_Pos; uint m_Limit; uint m_BufferSize; System.IO.Stream m_Stream; bool m_StreamWasExhausted; ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(System.IO.Stream stream) { m_Stream = stream; m_ProcessedSize = 0; m_Limit = 0; m_Pos = 0; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) return false; m_ProcessedSize += m_Pos; int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0; m_Limit = (uint)aNumProcessedBytes; m_StreamWasExhausted = (aNumProcessedBytes == 0); return (!m_StreamWasExhausted); } public void ReleaseStream() { // m_Stream.Close(); m_Stream = null; } public bool ReadByte(byte b) // check it { if (m_Pos >= m_Limit) if (!ReadBlock()) return false; b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { // return (byte)m_Stream.ReadByte(); if (m_Pos >= m_Limit) if (!ReadBlock()) return 0xFF; return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Common/OutBuffer.cs ================================================ // OutBuffer.cs namespace SevenZip.Buffer { public class OutBuffer { byte[] m_Buffer; uint m_Pos; uint m_BufferSize; System.IO.Stream m_Stream; ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(System.IO.Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0; m_Pos = 0; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) FlushData(); } public void FlushData() { if (m_Pos == 0) return; m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs ================================================ // IMatchFinder.cs using System; namespace SevenZip.Compression.LZ { interface IInWindowStream { void Init(System.IO.Stream inStream); void ReleaseStream(); void MovePos(); Byte GetIndexByte(Int32 index); UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); UInt32 GetNumAvailableBytes(); } interface IMatchFinder : IInWindowStream { void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter); UInt32 GetLongestMatch(UInt32[] distances); void DummyLongestMatch(); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZ/LzBinTree.cs ================================================ // LzBinTree.cs using System; namespace SevenZip.Compression.LZ { public class BinTree : InWindow, IMatchFinder { UInt32 _cyclicBufferPos; UInt32 _cyclicBufferSize; UInt32 _historySize; UInt32 _matchMaxLen; // UInt32 []_dummy; UInt32[] _son; UInt32[] _hash; UInt32[] _hash2; UInt32[] _hash3; UInt32 _cutValue = 0xFF; bool HASH_ARRAY = true; bool HASH_BIG = false; const UInt32 kHash3Size = 1 << 18; const UInt32 kBT2HashSize = 1 << 16; const UInt32 kBT4Hash2Size = 1 << 10; const UInt32 kBT4Hash4Size = 1 << 20; const UInt32 kBT4bHash4Size = 1 << 23; const UInt32 kBT2NumHashDirectBytes = 2; const UInt32 kBT4NumHashDirectBytes = 0; UInt32 kHash2Size = kBT4Hash2Size; UInt32 kNumHashDirectBytes = kBT4NumHashDirectBytes; UInt32 kNumHashBytes = 4; UInt32 kHashSize = kBT4Hash4Size; public void SetType(int numHashBytes, bool big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size; } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } const UInt32 kEmptyHashValue = 0; const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; UInt32 Hash(UInt32 offset, out UInt32 hash2Value, out UInt32 hash3Value) { UInt32 temp = CRC.Table[_bufferBase[offset]] ^ _bufferBase[offset + 1]; hash2Value = temp & (kHash2Size - 1); temp ^= ((UInt32)(_bufferBase[offset + 2]) << 8); hash3Value = temp & (kHash3Size - 1); return (temp ^ (CRC.Table[_bufferBase[offset + 3]] << 5)) & (kHashSize - 1); } UInt32 Hash(UInt32 offset) { return _bufferBase[offset] ^ ((UInt32)(_bufferBase[offset + 1]) << 8); } public new void Init(System.IO.Stream inStream) { base.Init(inStream); UInt32 i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public new void ReleaseStream() { base.ReleaseStream(); } public new void MovePos() { _cyclicBufferPos++; if (_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; base.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { return base.GetMatchLen(index, distance, limit); } public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter) { // _dummy = new UInt32[matchMaxLen + 1]; UInt32 windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) throw new Exception(); _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new UInt32[_cyclicBufferSize * 2]; _hash = new UInt32[kHashSize]; if (HASH_ARRAY) { _hash2 = new UInt32[kHash2Size]; _hash3 = new UInt32[kHash3Size]; } } public UInt32 GetLongestMatch(UInt32[] distances) { UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 matchHashLenMax = 0; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; UInt32 len2Distance = 0; UInt32 len3Distance = 0; bool matchLen2Exist = false; bool matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); UInt32 lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } UInt32 matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; UInt32 cur = _bufferOffset + _pos; UInt32 hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) hashValue = Hash(cur, out hash2Value, out hash3Value); else hashValue = Hash(cur); UInt32 curMatch = _hash[hashValue]; UInt32 curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } UInt32 ptrLeft = (_cyclicBufferPos << 1) + 1; UInt32 ptrRight = (_cyclicBufferPos << 1); UInt32 minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (UInt32 count = _cutValue; count > 0; count--) { UInt32 pby1 = _bufferOffset + curMatch; UInt32 currentLen = Math.Min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; UInt32 delta = _pos - curMatch; UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if (_bufferBase[pby1 + currentLen] < _bufferBase[cur + currentLen]) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) { for (UInt32 i = 0; i < numItems; i++) { UInt32 value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { UInt32 startItem = _pos - _historySize; UInt32 subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets((Int32)subValue); } public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZ/LzInWindow.cs ================================================ // LzInWindow.cs using System; namespace SevenZip.Compression.LZ { public class InWindow { public Byte[] _bufferBase = null; // pointer to buffer with data System.IO.Stream _stream; UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream UInt32 _pointerToLastSafePosition; public UInt32 _bufferOffset; public UInt32 _blockSize; // Size of Allocated memory block public UInt32 _pos; // offset (from _buffer) of curent byte UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos UInt32 _keepSizeReserv; // how many BYTEs must be kept as reserv public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream public virtual void BeforeMoveBlock() { } public virtual void AfterMoveBlock() { } public void MoveBlock() { BeforeMoveBlock(); UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; // check negative offset ???? for (UInt32 i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; AfterMoveBlock(); } public virtual void ReadBlock() { if (_streamEndWasReached) return; while (true) { int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); if (size == 0) return; int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); if (numReadBytes == 0) { _posLimit = _streamPos; UInt32 pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); _streamEndWasReached = true; return; } _streamPos += (UInt32)numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new Byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void Init(System.IO.Stream stream) { _stream = stream; _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void ReleaseStream() { _stream = null; } public void MovePos() { _pos++; if (_pos > _posLimit) { UInt32 pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (UInt32)(_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; UInt32 pby = _bufferOffset + _pos + (UInt32)index; UInt32 i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++) ; return i; } public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(Int32 subValue) { _bufferOffset += (UInt32)subValue; _posLimit -= (UInt32)subValue; _pos -= (UInt32)subValue; _streamPos -= (UInt32)subValue; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs ================================================ // LzOutWindow.cs namespace SevenZip.Compression.LZ { public class OutWindow { byte[] _buffer = null; uint _pos; uint _windowSize = 0; uint _streamPos; System.IO.Stream _stream; public void Create(uint windowSize) { if (_windowSize != windowSize) { // System.GC.Collect(); _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void Init(System.IO.Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0; _pos = 0; } } public void Init(System.IO.Stream stream) { Init(stream, false); } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint size = _pos - _streamPos; if (size == 0) return; _stream.Write(_buffer, (int)_streamPos, (int)size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(uint distance, uint len) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; for (; len > 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(uint distance) { uint pos = _pos - distance - 1; if (pos >= _windowSize) pos += _windowSize; return _buffer[pos]; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs ================================================ // LzmaBase.cs namespace SevenZip.Compression.LZMA { internal abstract class Base { public const uint kNumRepDistances = 4; public const uint kNumStates = 12; // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; public struct State { public uint Index; public void Init() { Index = 0; } public void UpdateChar() { if (Index < 4) Index = 0; else if (Index < 10) Index -= 3; else Index -= 6; } public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } public bool IsCharState() { return Index < 7; } } public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; public const int kDicLogSizeMax = 28; public const uint kDistTableSizeMax = kDicLogSizeMax * 2; public const int kNumLenToPosStatesBits = 2; // it's for speed optimization public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public const uint kMatchMinLen = 2; public static uint GetLenToPosState(uint len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (uint)(kNumLenToPosStates - 1); } public const int kNumAlignBits = 4; public const uint kAlignTableSize = 1 << kNumAlignBits; public const uint kAlignMask = (kAlignTableSize - 1); public const uint kStartPosModelIndex = 4; public const uint kEndPosModelIndex = 14; public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); public const uint kNumLitPosStatesBitsEncodingMax = 4; public const uint kNumLitContextBitsMax = 8; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs ================================================ // LzmaDecoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { class LenDecoder { BitDecoder m_Choice = new BitDecoder(); BitDecoder m_Choice2 = new BitDecoder(); BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); uint m_NumPosStates = 0; public void Create(uint numPosStates) { for (uint posState = m_NumPosStates; posState < numPosStates; posState++) { m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) return m_LowCoder[posState].Decode(rangeDecoder); else { uint symbol = Base.kNumLowLenSymbols; if (m_Choice2.Decode(rangeDecoder) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else { symbol += Base.kNumMidLenSymbols; symbol += m_HighCoder.Decode(rangeDecoder); } return symbol; } } } class LiteralDecoder { struct Decoder2 { BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) { uint symbol = 1; do symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) { uint symbol = 1; do { uint matchBit = (uint)(matchByte >> 7) & 1; matchByte <<= 1; uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } }; LZ.OutWindow m_OutWindow = new LZ.OutWindow(); RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); uint m_DictionarySize; uint m_DictionarySizeCheck; uint m_PosStateMask; public Decoder() { m_DictionarySize = 0xFFFFFFFF; for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); m_OutWindow.Create(blockSize); } } void SetLiteralProperties(int lp, int lc) { if (lp > 8) throw new InvalidParamException(); if (lc > 8) throw new InvalidParamException(); m_LiteralDecoder.Create(lp, lc); } void SetPosBitsProperties(int pb) { if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); uint numPosStates = (uint)1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; } void Init(System.IO.Stream inStream, System.IO.Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= m_PosStateMask; j++) { uint index = (i << Base.kNumPosStatesBitsMax) + j; m_IsMatchDecoders[index].Init(); m_IsRep0LongDecoders[index].Init(); } m_IsRepDecoders[i].Init(); m_IsRepG0Decoders[i].Init(); m_IsRepG1Decoders[i].Init(); m_IsRepG2Decoders[i].Init(); } m_LiteralDecoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); // m_PosSpecDecoder.Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) m_PosDecoders[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = new Base.State(); state.Init(); uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; UInt64 nowPos64 = 0; UInt64 outSize64 = (UInt64)outSize; if (nowPos64 < outSize64) { if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) throw new DataErrorException(); state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); m_OutWindow.PutByte(b); nowPos64++; } while (nowPos64 < outSize64) { // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); // while(nowPos64 < next) { uint posState = (uint)nowPos64 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { byte b; byte prevByte = m_OutWindow.GetByte(0); if (!state.IsCharState()) b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); else b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); m_OutWindow.PutByte(b); state.UpdateChar(); nowPos64++; } else { uint len; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); nowPos64++; continue; } } else { UInt32 distance; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { distance = rep1; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state.UpdateRep(); } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state.UpdateMatch(); uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (int)((posSlot >> 1) - 1); rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { if (rep0 == 0xFFFFFFFF) break; throw new DataErrorException(); } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; } } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) throw new InvalidParamException(); int lc = properties[0] % 9; int remainder = properties[0] / 9; int lp = remainder % 5; int pb = remainder / 5; if (pb > Base.kNumPosStatesBitsMax) throw new InvalidParamException(); UInt32 dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); SetDictionarySize(dictionarySize); SetLiteralProperties(lp, lc); SetPosBitsProperties(pb); } /* public override bool CanRead { get { return true; }} public override bool CanWrite { get { return true; }} public override bool CanSeek { get { return true; }} public override long Length { get { return 0; }} public override long Position { get { return 0; } set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void Write(byte[] buffer, int offset, int count) { } public override long Seek(long offset, System.IO.SeekOrigin origin) { return 0; } public override void SetLength(long value) {} */ } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs ================================================ // LzmaEncoder.cs using System; namespace SevenZip.Compression.LZMA { using RangeCoder; public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { enum EMatchFinderType { BT2, BT4, BT4B }; static string[] kMatchFinderIDs = { "BT2", "BT4", "BT4B", }; static int FindMatchFinder(string s) { for (int m = 0; m < kMatchFinderIDs.Length; m++) if (s == kMatchFinderIDs[m]) return m; return -1; } const UInt32 kIfinityPrice = 0xFFFFFFF; static Byte[] g_FastPos = new Byte[1024]; static Encoder() { const Byte kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) { UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); for (UInt32 j = 0; j < k; j++, c++) g_FastPos[c] = slotFast; } } static UInt32 GetPosSlot(UInt32 pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return (UInt32)(g_FastPos[pos >> 9] + 18); return (UInt32)(g_FastPos[pos >> 18] + 36); } static UInt32 GetPosSlot2(UInt32 pos) { if (pos < (1 << 16)) return (UInt32)(g_FastPos[pos >> 6] + 12); if (pos < (1 << 25)) return (UInt32)(g_FastPos[pos >> 15] + 30); return (UInt32)(g_FastPos[pos >> 24] + 48); } Base.State _state = new Base.State(); Byte _previousByte; UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; void BaseInit() { _state.Init(); _previousByte = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } const int kDefaultDictionaryLogSize = 20; const UInt32 kNumFastBytesDefault = 0x20; class LiteralEncoder { public struct Encoder2 { BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[0x300]; } public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) { uint context = 1; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); m_Encoders[context].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint context = 1; bool same = true; for (int i = 7; i >= 0; i--) { uint bit = (uint)((symbol >> i) & 1); uint state = context; if (same) { uint matchBit = (uint)((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } m_Encoders[state].Encode(rangeEncoder, bit); context = (context << 1) | bit; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint price = 0; uint context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { uint matchBit = (uint)(matchByte >> i) & 1; uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { uint bit = (uint)(symbol >> i) & 1; price += m_Encoders[context].GetPrice(bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = ((uint)1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (uint i = 0; i < numStates; i++) m_Coders[i].Create(); } public void Init() { uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); for (uint i = 0; i < numStates; i++) m_Coders[i].Init(); } uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) { return m_Coders[GetState(pos, prevByte)]; } } class LenEncoder { RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumLowBits RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumMidBits RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(UInt32 numPosStates) { _choice.Init(); _choice2.Init(); for (UInt32 posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { if (symbol < Base.kNumLowLenSymbols) { _choice.Encode(rangeEncoder, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; _choice.Encode(rangeEncoder, 1); if (symbol < Base.kNumMidLenSymbols) { _choice2.Encode(rangeEncoder, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public UInt32 GetPrice(UInt32 symbol, UInt32 posState) { UInt32 price = 0; if (symbol < Base.kNumLowLenSymbols) { price += _choice.GetPrice0(); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += _choice.GetPrice1(); if (symbol < Base.kNumMidLenSymbols) { price += _choice2.GetPrice0(); price += _midCoder[posState].GetPrice(symbol); } else { price += _choice2.GetPrice1(); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder : LenEncoder { UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; UInt32 _tableSize; UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } public new UInt32 GetPrice(UInt32 symbol, UInt32 posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(UInt32 posState) { for (UInt32 len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = base.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(UInt32 numPosStates) { for (UInt32 posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } const UInt32 kNumOpts = 1 << 12; class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public UInt32 PosPrev2; public UInt32 BackPrev2; public UInt32 Price; public UInt32 PosPrev; // posNext; public UInt32 BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public UInt32 Backs0; public UInt32 Backs1; public UInt32 Backs2; public UInt32 Backs3; public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public bool IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; LZ.IMatchFinder _matchFinder = null; // test it RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen + 1]; bool _fastMode = false; bool _maxMode = false; UInt32 _numFastBytes = kNumFastBytesDefault; UInt32 _longestMatchLength; UInt32 _additionalOffset; UInt32 _optimumEndIndex; UInt32 _optimumCurrentIndex; bool _longestMatchWasFound; UInt32[] _posSlotPrices = new UInt32[Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; UInt32 _alignPriceCount; UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; UInt32 _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); UInt32 _dictionarySizePrev = 0xFFFFFFFF; UInt32 _numFastBytesPrev = 0xFFFFFFFF; Int64 lastPosSlotFillingPos; Int64 nowPos64; bool _finished; System.IO.Stream _inStream; EMatchFinderType _matchFinderType = EMatchFinderType.BT4; bool _writeEndMark; bool _needReleaseMFStream; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { LZ.BinTree bt = new LZ.BinTree(); int numHashBytes = 4; bool big = false; switch (_matchFinderType) { case EMatchFinderType.BT2: numHashBytes = 2; break; case EMatchFinderType.BT4: break; case EMatchFinderType.BT4B: big = true; break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); } void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } void Init() { BaseInit(); _rangeEncoder.Init(); uint i; for (i = 0; i < Base.kNumStates; i++) { for (uint j = 0; j <= _posStateMask; j++) { uint complexState = (i << Base.kNumPosStatesBitsMax) + j; _isMatch[complexState].Init(); _isRep0Long[complexState].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); for (i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) _posEncoders[i].Init(); _lenEncoder.Init((UInt32)1 << _posStateBits); _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } void ReadMatchDistances(out UInt32 lenRes) { lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); } void MovePos(UInt32 num) { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } UInt32 GetRepLen1Price(Base.State state, UInt32 posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); } UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) { UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += _isRepG0[state.Index].GetPrice0(); price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); } else { price += _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) price += _isRepG1[state.Index].GetPrice0(); else { price += _isRepG1[state.Index].GetPrice1(); price += _isRepG2[state.Index].GetPrice(repIndex - 2); } } return price; } UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; UInt32 price; UInt32 lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } UInt32 Backward(out UInt32 backRes, UInt32 cur) { _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } UInt32[] reps = new UInt32[Base.kNumRepDistances]; UInt32[] repLens = new UInt32[Base.kNumRepDistances]; UInt32 GetOptimum(UInt32 position, out UInt32 backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; UInt32 i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } Byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); if (matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes = _optimum[1].BackPrev; return 1; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for (UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(out backRes, cur); } position++; UInt32 posPrev = _optimum[cur].PosPrev; Base.State state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state.UpdateShortRep(); else state.UpdateChar(); } else { UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; UInt32 newLen; ReadMatchDistances(out newLen); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(out backRes, cur); } UInt32 curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!state.IsCharState(), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); UInt32 numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte((Int32)temp - 1) != _matchFinder.GetIndexByte((Int32)temp - (Int32)backOffset - 1)) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + _isRep[state2.Index].GetPrice1(); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte((Int32)(-1 - (Int32)backOffset)) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte((Int32)(0 - (Int32)backOffset))) continue; UInt32 lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte((Int32)lenTest - 1) != _matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)backOffset)) break; UInt32 lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1)) != _matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1 - (Int32)backOffset))) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateRep(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)backOffset)), _matchFinder.GetIndexByte((Int32)lenTest - 1)); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (UInt32 lenTest = newLen; lenTest >= 2; lenTest--) { UInt32 curBack = _matchDistances[lenTest]; UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { UInt32 backOffset = curBack + 1; UInt32 lenTest2 = lenTest + 1; UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte((Int32)lenTest2 - 1) != _matchFinder.GetIndexByte((Int32)lenTest2 - (Int32)backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { Base.State state2 = state; state2.UpdateMatch(); UInt32 posStateNext = (position + lenTest) & _posStateMask; UInt32 curAndLenCharPrice = curAndLenPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + _literalEncoder.GetSubCoder(position + lenTest, // data[(size_t)lenTest - 1], _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). GetPrice(true, // data[(size_t)lenTest - backOffset], data[lenTest] _matchFinder.GetIndexByte((Int32)lenTest - (Int32)backOffset - 1), _matchFinder.GetIndexByte((Int32)lenTest - 1) ); state2.UpdateChar(); posStateNext = (position + lenTest + 1) & _posStateMask; UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) { UInt32 offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } bool ChangePair(UInt32 smallDist, UInt32 bigDist) { const int kDif = 7; return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); } UInt32 GetOptimumFast(UInt32 position, out UInt32 backRes) { UInt32 lenMain; if (!_longestMatchWasFound) { ReadMatchDistances(out lenMain); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 repMaxIndex = 0; for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; UInt32 backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes = repMaxIndex; UInt32 lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { ReadMatchDistances(out _longestMatchLength); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } for (UInt32 i = 0; i < Base.kNumRepDistances; i++) { UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes = 0xFFFFFFFF; return 1; } } backRes = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes = 0xFFFFFFFF; return 1; } void InitMatchFinder(LZ.IMatchFinder matchFinder) { _matchFinder = matchFinder; } void WriteEndMarker(UInt32 posState) { if (!_writeEndMark) return; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); UInt32 len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; UInt32 posReduced = (((UInt32)1) << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(UInt32 nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) { inSize = 0; outSize = 0; finished = true; if (_inStream != null) { _matchFinder.Init(_inStream); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; Int64 progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } UInt32 len; // it's not used ReadMatchDistances(out len); UInt32 posState = (UInt32)(nowPos64) & _posStateMask; _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); _state.UpdateChar(); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } while (true) { UInt32 pos; UInt32 posState = ((UInt32)nowPos64) & _posStateMask; UInt32 len; if (_fastMode) len = GetOptimumFast((UInt32)nowPos64, out pos); else len = GetOptimum((UInt32)nowPos64, out pos); UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == 0xFFFFFFFF) { _isMatch[complexState].Encode(_rangeEncoder, 0); Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); if (!_state.IsCharState()) { Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state.UpdateChar(); } else { _isMatch[complexState].Encode(_rangeEncoder, 1); if (pos < Base.kNumRepDistances) { _isRep[_state.Index].Encode(_rangeEncoder, 1); if (pos == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0); if (len == 1) _isRep0Long[complexState].Encode(_rangeEncoder, 0); else _isRep0Long[complexState].Encode(_rangeEncoder, 1); } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1); if (pos == 1) _isRepG1[_state.Index].Encode(_rangeEncoder, 0); else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1); _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); } } if (len == 1) _state.UpdateShortRep(); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state.UpdateRep(); } UInt32 distance = _repDistances[pos]; if (pos != 0) { for (UInt32 i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; UInt32 posSlot = GetPosSlot(pos); UInt32 lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); UInt32 posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } UInt32 distance = pos; for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((UInt32)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); // CCoderReleaser releaser(this); /* if (_matchFinder->GetNumAvailableBytes() == 0) return Flush(); */ if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } public void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { Int64 processedInSize; Int64 processedOutSize; bool finished; CodeOneBlock(out processedInSize, out processedOutSize, out finished); if (finished) return; if (progress != null) { progress.SetProgress(processedInSize, processedOutSize); } } } finally { ReleaseStreams(); } } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (UInt32 i = 0; i < properties.Length; i++) { object prop = properties[i]; switch (propIDs[i]) { case CoderPropID.NumFastBytes: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 numFastBytes = (Int32)prop; if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) throw new InvalidParamException(); _numFastBytes = (UInt32)numFastBytes; break; } case CoderPropID.Algorithm: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 maximize = (Int32)prop; _fastMode = (maximize == 0); _maxMode = (maximize >= 2); break; } case CoderPropID.MatchFinder: { if (!(prop is String)) throw new InvalidParamException(); EMatchFinderType matchFinderIndexPrev = _matchFinderType; int m = FindMatchFinder(((string)prop).ToUpper()); if (m < 0) throw new InvalidParamException(); _matchFinderType = (EMatchFinderType)m; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = 0xFFFFFFFF; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { const int kDicLogSizeMaxCompress = 28; if (!(prop is Int32)) throw new InvalidParamException(); ; Int32 dictionarySize = (Int32)prop; if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) throw new InvalidParamException(); _dictionarySize = (UInt32)dictionarySize; int dicLogSize; for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) if (dictionarySize <= ((UInt32)(1) << dicLogSize)) break; _distTableSize = (UInt32)dicLogSize * 2; break; } case CoderPropID.PosStateBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) throw new InvalidParamException(); _posStateBits = (int)v; _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; break; } case CoderPropID.LitPosBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) throw new InvalidParamException(); _numLiteralPosStateBits = (int)v; break; } case CoderPropID.LitContextBits: { if (!(prop is Int32)) throw new InvalidParamException(); Int32 v = (Int32)prop; if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) throw new InvalidParamException(); ; _numLiteralContextBits = (int)v; break; } case CoderPropID.EndMarker: { if (!(prop is Boolean)) throw new InvalidParamException(); SetWriteEndMarkerMode((Boolean)prop); break; } default: throw new InvalidParamException(); } } } const int kPropSize = 5; Byte[] properties = new Byte[kPropSize]; public void WriteCoderProperties(System.IO.Stream outStream) { properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); outStream.Write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { UInt32 i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { UInt32 posSlot = GetPosSlot(i); int footerBits = (int)((posSlot >> 1) - 1); UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + RangeCoder.BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (UInt32 i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs ================================================ using System; using System.IO; namespace SevenZip { using CommandLineParser; class LzmaAlone { enum Key { Help1 = 0, Help2, Mode, Dictionary, FastBytes, LitContext, LitPos, PosBits, MatchFinder, EOS, StdIn, StdOut }; static void PrintHelp() { System.Console.WriteLine("\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" // + " -si: read data from stdin\n" // + " -so: write data to stdout\n" ); } static bool GetNumber(string s, out Int32 v) { v = 0; for (int i = 0; i < s.Length; i++) { char c = s[i]; if (c < '0' || c > '9') return false; v *= 10; v += (Int32)(c - '0'); } return true; } static int IncorrectCommand() { throw (new Exception("Command line error")); // System.Console.WriteLine("\nCommand line error\n"); // return 1; } static int Main2(string[] args) { System.Console.WriteLine("\nLZMA# 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.Length == 0) { PrintHelp(); return 0; } SwitchForm[] kSwitchForms = new SwitchForm[12]; int sw = 0; kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1); kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false); kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false); Parser parser = new Parser(sw); try { parser.ParseStrings(kSwitchForms, args); } catch { return IncorrectCommand(); } if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs) { PrintHelp(); return 0; } System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings; int paramIndex = 0; if (paramIndex >= nonSwitchStrings.Count) return IncorrectCommand(); string command = (string)nonSwitchStrings[paramIndex++]; command = command.ToLower(); bool dictionaryIsDefined = false; Int32 dictionary = 1 << 21; if (parser[(int)Key.Dictionary].ThereIs) { Int32 dicLog; if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog)) IncorrectCommand(); dictionary = (Int32)1 << dicLog; dictionaryIsDefined = true; } string mf = "bt4"; if (parser[(int)Key.MatchFinder].ThereIs) mf = (string)parser[(int)Key.MatchFinder].PostStrings[0]; mf = mf.ToLower(); if (command == "b") { const Int32 kNumDefaultItereations = 10; Int32 numIterations = kNumDefaultItereations; if (paramIndex < nonSwitchStrings.Count) if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations)) numIterations = kNumDefaultItereations; return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary, mf == "bt4"); } bool encodeMode = false; if (command == "e") encodeMode = true; else if (command == "d") encodeMode = false; else IncorrectCommand(); bool stdInMode = parser[(int)Key.StdIn].ThereIs; bool stdOutMode = parser[(int)Key.StdOut].ThereIs; FileStream inStream = null; if (stdInMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string inputName = (string)nonSwitchStrings[paramIndex++]; inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read); } FileStream outStream = null; if (stdOutMode) { throw (new Exception("Not implemeted")); } else { if (paramIndex >= nonSwitchStrings.Count) IncorrectCommand(); string outputName = (string)nonSwitchStrings[paramIndex++]; outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write); } if (encodeMode) { if (!dictionaryIsDefined) dictionary = 1 << 23; Int32 posStateBits = 2; Int32 litContextBits = 3; // for normal files // UInt32 litContextBits = 0; // for 32-bit data Int32 litPosBits = 0; // UInt32 litPosBits = 2; // for 32-bit data Int32 algorithm = 2; Int32 numFastBytes = 128; bool eos = parser[(int)Key.EOS].ThereIs || stdInMode; if (parser[(int)Key.Mode].ThereIs) if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm)) IncorrectCommand(); if (parser[(int)Key.FastBytes].ThereIs) if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes)) IncorrectCommand(); if (parser[(int)Key.LitContext].ThereIs) if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits)) IncorrectCommand(); if (parser[(int)Key.LitPos].ThereIs) if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits)) IncorrectCommand(); if (parser[(int)Key.PosBits].ThereIs) if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits)) IncorrectCommand(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (Int32)(dictionary), (Int32)(posStateBits), (Int32)(litContextBits), (Int32)(litPosBits), (Int32)(algorithm), (Int32)(numFastBytes), mf, eos }; Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); Int64 fileSize; if (eos || stdInMode) fileSize = -1; else fileSize = inStream.Length; for (int i = 0; i < 8; i++) outStream.WriteByte((Byte)(fileSize >> (8 * i))); encoder.Code(inStream, outStream, -1, -1, null); } else if (command == "d") { byte[] properties = new byte[5]; if (inStream.Read(properties, 0, 5) != 5) throw (new Exception("input .lzma is too short")); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); decoder.SetDecoderProperties(properties); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.ReadByte(); if (v < 0) throw (new Exception("Can't Read 1")); outSize |= ((long)(byte)v) << (8 * i); } long compressedSize = inStream.Length - inStream.Position; decoder.Code(inStream, outStream, compressedSize, outSize, null); } else throw (new Exception("Command Error")); return 0; } [STAThread] static int Main(string[] args) { try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj ================================================  Debug AnyCPU 8.0.40607 2.0 {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973} Exe LzmaAlone Lzma# 4 true full false .\bin\Debug\ DEBUG;TRACE false true .\bin\Release\ TRACE Common\CommandLineParser.cs Common\CRC.cs ICoder.cs LZ\IMatchFinder.cs LZ\LzBinTree.cs LZ\LzInWindow.cs LZ\LzOutWindow.cs LZMA\LzmaBase.cs LZMA\LzmaDecoder.cs LZMA\LzmaEncoder.cs RangeCoder\RangeCoder.cs RangeCoder\RangeCoderBit.cs RangeCoder\RangeCoderBitTree.cs Code Code True Settings.settings SettingsSingleFileGenerator Settings.cs ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln ================================================  Microsoft Visual Studio Solution File, Format Version 9.00 # Visual C# Express 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs ================================================ // LzmaBench.cs using System; using System.IO; namespace SevenZip { /// /// LZMA Benchmark /// internal abstract class LzmaBench { const UInt32 kAdditionalSize = (6 << 20); const UInt32 kCompressedAdditionalSize = (1 << 10); const UInt32 kMaxLzmaPropSize = 10; class CRandomGenerator { UInt32 A1; UInt32 A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public UInt32 GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); } }; class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); UInt32 Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public UInt32 GetRnd(int numBits) { UInt32 result; if (NumBits > numBits) { result = Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((UInt32)1 << numBits) - 1); Value >>= numBits; NumBits = 32 - numBits; return result; } }; class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); UInt32 Pos; public UInt32 BufferSize; public Byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(UInt32 bufferSize) { Buffer = new Byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } UInt32 GetRndBit() { return RG.GetRnd(1); } /* UInt32 GetLogRand(int maxLen) { UInt32 len = GetRnd() % (maxLen + 1); return GetRnd() & ((1 << len) - 1); } */ UInt32 GetLogRandBits(int numBits) { UInt32 len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } UInt32 GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } UInt32 GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (Byte)(RG.GetRnd(8)); else { UInt32 offset = GetOffset(); while (offset >= Pos) offset >>= 1; offset += 1; UInt32 len = 2 + GetLen(); for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; class CrcOutStream : System.IO.Stream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public UInt32 GetDigest() { return CRC.GetDigest(); } public override bool CanRead { get { return false; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return true; } } public override Int64 Length { get { return 0; } } public override Int64 Position { get { return 0; } set { } } public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) { return 0; } public override void SetLength(long value) { } public override int Read(byte[] buffer, int offset, int count) { return 0; } public override void WriteByte(byte b) { CRC.UpdateByte(b); } public override void Write(byte[] buffer, int offset, int count) { CRC.Update(buffer, (uint)offset, (uint)count); } }; class CProgressInfo : ICodeProgress { public Int64 ApprovedStart; public Int64 InSize; public System.DateTime Time; public void Init() { InSize = 0; } public void SetProgress(Int64 inSize, Int64 outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = DateTime.UtcNow; InSize = inSize; } } } const int kSubBits = 8; static UInt32 GetLogSize(UInt32 size) { for (int i = kSubBits; i < 32; i++) for (UInt32 j = 0; j < (1 << kSubBits); j++) if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) return (UInt32)(i << kSubBits) + j; return (32 << kSubBits); } static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) { UInt64 freq = TimeSpan.TicksPerSecond; UInt64 elTime = elapsedTime; while (freq > 1000000) { freq >>= 1; elTime >>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size) { UInt64 numCommandsForOne; if (isBT4) { UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits)); } else { UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits)); } UInt64 numCommands = (UInt64)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) { UInt64 numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static UInt64 GetTotalRating( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTimeEn, UInt64 sizeEn, UInt64 elapsedTimeDe, UInt64 inSizeDe, UInt64 outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(UInt64 v) { string s = v.ToString(); for (int i = 0; i + s.Length < 6; i++) System.Console.Write(" "); System.Console.Write(s); } static void PrintRating(UInt64 rating) { PrintValue(rating / 1000000); System.Console.Write(" MIPS"); } static void PrintResults( UInt32 dictionarySize, bool isBT4, UInt64 elapsedTime, UInt64 size, bool decompressMode, UInt64 secondSize) { UInt64 speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.Console.Write(" KB/s "); UInt64 rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } const string bt2 = "BT2"; const string bt4 = "BT4"; static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize, bool isBT4) { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.Console.Write("\n Compressing Decompressing\n\n"); Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); CoderPropID[] propIDs = { CoderPropID.DictionarySize, CoderPropID.MatchFinder }; object[] properties = { (Int32)(dictionarySize), isBT4 ? bt4: bt2 }; UInt32 kBufferSize = dictionarySize + kAdditionalSize; UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; encoder.SetCoderProperties(propIDs, properties); System.IO.MemoryStream propStream = new System.IO.MemoryStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.ToArray(); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; UInt64 totalBenchSize = 0; UInt64 totalEncodeTime = 0; UInt64 totalDecodeTime = 0; UInt64 totalCompressedSize = 0; MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); CrcOutStream crcOutStream = new CrcOutStream(); for (Int32 i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.Seek(0, SeekOrigin.Begin); compressedStream.Seek(0, SeekOrigin.Begin); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; UInt64 encodeTime = (UInt64)sp2.Ticks; long compressedSize = compressedStream.Position; if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); UInt64 decodeTime = 0; for (int j = 0; j < 2; j++) { compressedStream.Seek(0, SeekOrigin.Begin); crcOutStream.Init(); decoder.SetDecoderProperties(propArray); UInt64 outSize = kBufferSize; System.DateTime startTime = DateTime.UtcNow; decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); TimeSpan sp = (DateTime.UtcNow - startTime); decodeTime = (ulong)sp.Ticks; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, (ulong)compressedSize); System.Console.WriteLine(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += (ulong)compressedSize; } System.Console.WriteLine("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.Console.Write(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (UInt64)numIterations, true, totalCompressedSize); System.Console.WriteLine(" Average"); return 0; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs ================================================ #region Using directives using System.Reflection; using System.Runtime.CompilerServices; #endregion // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("LZMA#")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Igor Pavlov")] [assembly: AssemblyProduct("LZMA# SDK")] [assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("4.12.*")] ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { using System; using System.IO; using System.Resources; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the Strongly Typed Resource Builder // class via a tool like ResGen or Visual Studio.NET. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. class Resources { private static System.Resources.ResourceManager _resMgr; private static System.Globalization.CultureInfo _resCulture; /*FamANDAssem*/ internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Resources.ResourceManager ResourceManager { get { if ((_resMgr == null)) { System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly); _resMgr = temp; } return _resMgr; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.Globalization.CultureInfo Culture { get { return _resCulture; } set { _resCulture = value; } } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.40607.42 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace LzmaAlone.Properties { public partial class Settings : System.Configuration.ApplicationSettingsBase { private static Settings m_Value; private static object m_SyncObject = new object(); public static Settings Value { get { if ((Settings.m_Value == null)) { System.Threading.Monitor.Enter(Settings.m_SyncObject); if ((Settings.m_Value == null)) { try { Settings.m_Value = new Settings(); } finally { System.Threading.Monitor.Exit(Settings.m_SyncObject); } } } return Settings.m_Value; } } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { class Encoder { public const uint kTopValue = (1 << 24); System.IO.Stream Stream; public UInt64 Low; public uint Range; uint _cacheSize; byte _cache; long StartPosition; public void SetStream(System.IO.Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0; Range = 0xFFFFFFFF; _cacheSize = 1; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) { byte temp = _cache; do { Stream.WriteByte((byte)(temp + (Low >> 32))); temp = 0xFF; } while (--_cacheSize != 0); _cache = (byte)(((uint)Low) >> 24); } _cacheSize++; Low = ((uint)Low) << 8; } public void EncodeDirectBits(uint v, int numTotalBits) { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>= 1; if (((v >> i) & 1) == 1) Low += Range; if (Range < kTopValue) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint newBound = (Range >> numTotalBits) * size0; if (symbol == 0) Range = newBound; else { Low += newBound; Range -= newBound; } while (Range < kTopValue) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; // (long)Stream.GetProcessedSize(); } } class Decoder { public const uint kTopValue = (1 << 24); public uint Range; public uint Code; // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); public System.IO.Stream Stream; public void Init(System.IO.Stream stream) { // Stream.Init(stream); Stream = stream; Code = 0; Range = 0xFFFFFFFF; for (int i = 0; i < 5; i++) Code = (Code << 8) | (byte)Stream.ReadByte(); } public void ReleaseStream() { // Stream.ReleaseStream(); Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < kTopValue) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint range = Range; uint code = Code; uint result = 0; for (int i = numTotalBits; i > 0; i--) { range >>= 1; /* result <<= 1; if (code >= range) { code -= range; result |= 1; } */ uint t = (code - range) >> 31; code -= range & (t - 1); result = (result << 1) | (1 - t); if (range < kTopValue) { code = (code << 8) | (byte)Stream.ReadByte(); range <<= 8; } } Range = range; Code = code; return result; } public uint DecodeBit(uint size0, int numTotalBits) { uint newBound = (Range >> numTotalBits) * size0; uint symbol; if (Code < newBound) { symbol = 0; Range = newBound; } else { symbol = 1; Code -= newBound; Range -= newBound; } Normalize(); return symbol; } // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; uint Prob; public void Init() { Prob = kBitModelTotal >> 1; } public void UpdateModel(uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> kNumMoveBits; else Prob -= (Prob) >> kNumMoveBits; } public void Encode(Encoder encoder, uint symbol) { // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); // UpdateModel(symbol); uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; if (symbol == 0) { encoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; } else { encoder.Low += newBound; encoder.Range -= newBound; Prob -= (Prob) >> kNumMoveBits; } if (encoder.Range < Encoder.kTopValue) { encoder.Range <<= 8; encoder.ShiftLow(); } } private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; static BitEncoder() { const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { UInt32 start = (UInt32)1 << (kNumBits - i - 1); UInt32 end = (UInt32)1 << (kNumBits - i); for (UInt32 j = start; j < end; j++) ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; } public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } } struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); const int kNumMoveBits = 5; uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) Prob += (kBitModelTotal - Prob) >> numMoveBits; else Prob -= (Prob) >> numMoveBits; } public void Init() { Prob = kBitModelTotal >> 1; } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; if (rangeDecoder.Code < newBound) { rangeDecoder.Range = newBound; Prob += (kBitModelTotal - Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0; } else { rangeDecoder.Range -= newBound; rangeDecoder.Code -= newBound; Prob -= (Prob) >> kNumMoveBits; if (rangeDecoder.Range < Decoder.kTopValue) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1; } } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs ================================================ using System; namespace SevenZip.Compression.RangeCoder { struct BitTreeEncoder { BitEncoder[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public void Encode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) { UInt32 m = 1; for (UInt32 i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } public UInt32 GetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; ) { bitIndex--; UInt32 bit = (symbol >> bitIndex) & 1; price += Models[m].GetPrice(bit); m = (m << 1) + bit; } return price; } public UInt32 ReverseGetPrice(UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, int NumBitLevels, UInt32 symbol) { UInt32 price = 0; UInt32 m = 1; for (int i = NumBitLevels; i > 0; i--) { UInt32 bit = symbol & 1; symbol >>= 1; price += Models[startIndex + m].GetPrice(bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) { UInt32 m = 1; for (int i = 0; i < NumBitLevels; i++) { UInt32 bit = symbol & 1; Models[startIndex + m].Encode(rangeEncoder, bit); m = (m << 1) | bit; symbol >>= 1; } } } struct BitTreeDecoder { BitDecoder[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint i = 1; i < (1 << NumBitLevels); i++) Models[i].Init(); } public uint Decode(RangeCoder.Decoder rangeDecoder) { uint m = 1; for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) m = (m << 1) + Models[m].Decode(rangeDecoder); return m - ((uint)1 << NumBitLevels); } public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, RangeCoder.Decoder rangeDecoder, int NumBitLevels) { uint m = 1; uint symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { uint bit = Models[startIndex + m].Decode(rangeDecoder); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/CS/7zip/ICoder.cs ================================================ // ICoder.h using System; namespace SevenZip { /// /// The exception that is thrown when an error in input stream occurs during decoding. /// class DataErrorException : ApplicationException { public DataErrorException(): base("Data Error") { } } /// /// The exception that is thrown when the value of an argument is outside the allowable range. /// class InvalidParamException : ApplicationException { public InvalidParamException(): base("Invalid Parameter") { } } public interface ICodeProgress { /// /// Callback progress. /// /// /// input size. -1 if unknown. /// /// /// output size. -1 if unknown. /// void SetProgress(Int64 inSize, Int64 outSize); }; public interface ICoder { /// /// Codes streams. /// /// /// input Stream. /// /// /// output Stream. /// /// /// input Size. -1 if unknown. /// /// /// output Size. -1 if unknown. /// /// /// callback progress reference. /// /// /// if input stream is not valid /// void Code(System.IO.Stream inStream, System.IO.Stream outStream, Int64 inSize, Int64 outSize, ICodeProgress progress); }; /* public interface ICoder2 { void Code(ISequentialInStream []inStreams, const UInt64 []inSizes, ISequentialOutStream []outStreams, UInt64 []outSizes, ICodeProgress progress); }; */ /// /// Provides the fields that represent properties idenitifiers for compressing. /// public enum CoderPropID { /// /// Specifies size of dictionary. /// DictionarySize = 0x400, /// /// Specifies size of memory for PPM*. /// UsedMemorySize, /// /// Specifies order for PPM methods. /// Order, /// /// Specifies number of postion state bits for LZMA (0 <= x <= 4). /// PosStateBits = 0x440, /// /// Specifies number of literal context bits for LZMA (0 <= x <= 8). /// LitContextBits, /// /// Specifies number of literal position bits for LZMA (0 <= x <= 4). /// LitPosBits, /// /// Specifies number of fast bytes for LZ*. /// NumFastBytes = 0x450, /// /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". /// MatchFinder, /// /// Specifies number of passes. /// NumPasses = 0x460, /// /// Specifies number of algorithm. /// Algorithm = 0x470, /// /// Specifies multithread mode. /// MultiThread = 0x480, /// /// Specifies mode with end marker. /// EndMarker = 0x490 }; public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); }; public interface IWriteCoderProperties { void WriteCoderProperties(System.IO.Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/CRC.java ================================================ // SevenZip/CRC.java package SevenZip; public class CRC { static public int[] Table = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; Table[i] = r; } } int _value = -1; public void Init() { _value = -1; } public void Update(byte[] data, int offset, int size) { for (int i = 0; i < size; i++) _value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8); } public void Update(byte[] data) { int size = data.length; for (int i = 0; i < size; i++) _value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8); } public void UpdateByte(int b) { _value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8); } public int GetDigest() { return _value ^ (-1); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/ICodeProgress.java ================================================ package SevenZip; public interface ICodeProgress { public void SetProgress(long inSize, long outSize); } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZ/BinTree.java ================================================ package SevenZip.Compression.LZ; import java.io.IOException; public class BinTree extends InWindow { int _cyclicBufferPos; int _cyclicBufferSize; int _historySize; int _matchMaxLen; int[] _son; int[] _hash; int[] _hash2; int[] _hash3; int _cutValue = 0xFF; boolean HASH_ARRAY = true; boolean HASH_BIG = false; static final int kHash3Size = 1 << 18; static final int kBT2HashSize = 1 << 16; static final int kBT4Hash2Size = 1 << 10; static final int kBT4Hash4Size = 1 << 20; static final int kBT4bHash4Size = 1 << 23; static final int kBT2NumHashDirectBytes = 2; static final int kBT4NumHashDirectBytes = 0; int kHash2Size = kBT4Hash2Size; int kNumHashDirectBytes = kBT4NumHashDirectBytes; int kNumHashBytes = 4; int kHashSize = kBT4Hash4Size; private static final int[] CrcTable = new int[256]; static { for (int i = 0; i < 256; i++) { int r = i; for (int j = 0; j < 8; j++) if ((r & 1) != 0) r = (r >>> 1) ^ 0xEDB88320; else r >>>= 1; CrcTable[i] = r; } } public void SetType(int numHashBytes, boolean big) { HASH_ARRAY = numHashBytes > 2; HASH_BIG = big; if (HASH_ARRAY) { kHash2Size = kBT4Hash2Size; kNumHashDirectBytes = kBT4NumHashDirectBytes; kNumHashBytes = 4; kHashSize = (HASH_BIG ? kBT4bHash4Size : kBT4Hash4Size); } else { kNumHashDirectBytes = kBT2NumHashDirectBytes; kNumHashBytes = 2; kHashSize = kBT2HashSize; } } static final int kEmptyHashValue = 0; static final int kMaxValForNormalize = ((int)1 << 30) - 1; public void Init() throws IOException { super.Init(); int i; for (i = 0; i < kHashSize; i++) _hash[i] = kEmptyHashValue; if (HASH_ARRAY) { for (i = 0; i < kHash2Size; i++) _hash2[i] = kEmptyHashValue; for (i = 0; i < kHash3Size; i++) _hash3[i] = kEmptyHashValue; } _cyclicBufferPos = 0; ReduceOffsets(-1); } public void MovePos() throws IOException { if (++_cyclicBufferPos >= _cyclicBufferSize) _cyclicBufferPos = 0; super.MovePos(); if (_pos == kMaxValForNormalize) Normalize(); } public boolean Create(int historySize, int keepAddBufferBefore, int matchMaxLen, int keepAddBufferAfter) { int windowReservSize = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; _son = null; _hash = null; _hash2 = null; _hash3 = null; super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); if (_blockSize + 256 > kMaxValForNormalize) return false; _historySize = historySize; _matchMaxLen = matchMaxLen; _cyclicBufferSize = historySize + 1; _son = new int[_cyclicBufferSize * 2]; _hash = new int[kHashSize]; if (HASH_ARRAY) { _hash2 = new int[kHash2Size]; _hash3 = new int[kHash3Size]; } return true; } public int GetLongestMatch(int[] distances) { int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return 0; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int matchHashLenMax = 0; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; int len2Distance = 0; int len3Distance = 0; boolean matchLen2Exist = false; boolean matchLen3Exist = false; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; if (curMatch2 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) { len2Distance = _pos - curMatch2 - 1; matchHashLenMax = 2; matchLen2Exist = true; } } { _hash3[hash3Value] = _pos; if (curMatch3 >= matchMinPos) { if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) { len3Distance = _pos - curMatch3 - 1; matchHashLenMax = 3; matchLen3Exist = true; if (matchLen2Exist) { if (len3Distance < len2Distance) len2Distance = len3Distance; } else { len2Distance = len3Distance; matchLen2Exist = true; } } } } } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; if (HASH_ARRAY) { distances[2] = len2Distance; distances[3] = len3Distance; } return matchHashLenMax; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int maxLen, minLeft, minRight; maxLen = minLeft = minRight = kNumHashDirectBytes; distances[maxLen] = _pos - curMatch - 1; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; while (currentLen > maxLen) distances[++maxLen] = delta - 1; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; if (HASH_ARRAY) { if (matchLen2Exist && len2Distance < distances[2]) distances[2] = len2Distance; if (matchLen3Exist && len3Distance < distances[3]) distances[3] = len3Distance; } return maxLen; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; if (HASH_ARRAY) { if (matchLen2Exist) { if (maxLen < 2) { distances[2] = len2Distance; maxLen = 2; } else if (len2Distance < distances[2]) distances[2] = len2Distance; } { if (matchLen3Exist) { if (maxLen < 3) { distances[3] = len3Distance; maxLen = 3; } else if (len3Distance < distances[3]) distances[3] = len3Distance; } } } return maxLen; } public void DummyLongestMatch() { // GetLongestMatch(_dummy); int lenLimit; if (_pos + _matchMaxLen <= _streamPos) lenLimit = _matchMaxLen; else { lenLimit = _streamPos - _pos; if (lenLimit < kNumHashBytes) return; } int matchMinPos = (_pos > _historySize) ? (_pos - _historySize) : 1; int cur = _bufferOffset + _pos; int hashValue, hash2Value = 0, hash3Value = 0; if (HASH_ARRAY) { int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF); hash2Value = temp & (kHash2Size - 1); temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8); hash3Value = temp & (kHash3Size - 1); hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & (kHashSize - 1); } else hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8)) & (kHashSize - 1); int curMatch = _hash[hashValue]; int curMatch2 = 0, curMatch3 = 0; if (HASH_ARRAY) { curMatch2 = _hash2[hash2Value]; curMatch3 = _hash3[hash3Value]; _hash2[hash2Value] = _pos; _hash3[hash3Value] = _pos; } _hash[hashValue] = _pos; if (curMatch < matchMinPos) { _son[(_cyclicBufferPos << 1)] = kEmptyHashValue; _son[(_cyclicBufferPos << 1) + 1] = kEmptyHashValue; return; } int ptrLeft = (_cyclicBufferPos << 1) + 1; int ptrRight = (_cyclicBufferPos << 1); int minLeft, minRight; minLeft = minRight = kNumHashDirectBytes; for (int count = _cutValue; count != 0; count--) { int pby1 = _bufferOffset + curMatch; int currentLen = Math.min(minLeft, minRight); for (; currentLen < lenLimit; currentLen++) if (_bufferBase[pby1 + currentLen] != _bufferBase[cur + currentLen]) break; int delta = _pos - curMatch; int cyclicPos = ((delta <= _cyclicBufferPos) ? (_cyclicBufferPos - delta) : (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; if (currentLen != lenLimit) { if ((_bufferBase[pby1 + currentLen] & 0xFF) < (_bufferBase[cur + currentLen] & 0xFF)) { _son[ptrRight] = curMatch; ptrRight = cyclicPos + 1; curMatch = _son[ptrRight]; if (currentLen > minLeft) minLeft = currentLen; } else { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } } else { if (currentLen < _matchMaxLen) { _son[ptrLeft] = curMatch; ptrLeft = cyclicPos; curMatch = _son[ptrLeft]; if (currentLen > minRight) minRight = currentLen; } else { _son[ptrLeft] = _son[cyclicPos + 1]; _son[ptrRight] = _son[cyclicPos]; return; } } if (curMatch < matchMinPos) break; } _son[ptrLeft] = kEmptyHashValue; _son[ptrRight] = kEmptyHashValue; } void NormalizeLinks(int[] items, int numItems, int subValue) { for (int i = 0; i < numItems; i++) { int value = items[i]; if (value <= subValue) value = kEmptyHashValue; else value -= subValue; items[i] = value; } } void Normalize() { int startItem = _pos - _historySize; int subValue = startItem - 1; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, kHashSize, subValue); if (HASH_ARRAY) { NormalizeLinks(_hash2, kHash2Size, subValue); NormalizeLinks(_hash3, kHash3Size, subValue); } ReduceOffsets(subValue); } public void SetCutValue(int cutValue) { _cutValue = cutValue; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZ/InWindow.java ================================================ // LZ.InWindows package SevenZip.Compression.LZ; import java.io.IOException; public class InWindow { public byte[] _bufferBase; // pointer to buffer with data java.io.InputStream _stream; int _posLimit; // offset (from _buffer) of first byte when new block reading must be done boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream int _pointerToLastSafePosition; public int _bufferOffset; public int _blockSize; // Size of Allocated memory block public int _pos; // offset (from _buffer) of curent byte int _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos int _keepSizeAfter; // how many BYTEs must be kept buffer after _pos int _keepSizeReserv; // how many BYTEs must be kept as reserv public int _streamPos; // offset (from _buffer) of first not read byte from Stream public void MoveBlock() { int offset = _bufferOffset + _pos - _keepSizeBefore; int numBytes = _bufferOffset + _streamPos - offset; // check negative offset ???? for (int i = 0; i < numBytes; i++) _bufferBase[i] = _bufferBase[offset + i]; _bufferOffset -= offset; } public void ReadBlock() throws IOException { if (_streamEndWasReached) return; while (true) { int size = (0 - _bufferOffset) + _blockSize - _streamPos; if (size == 0) return; int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size); if (numReadBytes == -1) { _posLimit = _streamPos; int pointerToPostion = _bufferOffset + _posLimit; if (pointerToPostion > _pointerToLastSafePosition) _posLimit = _pointerToLastSafePosition - _bufferOffset; _streamEndWasReached = true; return; } _streamPos += numReadBytes; if (_streamPos >= _pos + _keepSizeAfter) _posLimit = _streamPos - _keepSizeAfter; } } void Free() { _bufferBase = null; } public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; _keepSizeReserv = keepSizeReserv; int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != blockSize) { Free(); _blockSize = blockSize; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(java.io.InputStream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() throws IOException { _bufferOffset = 0; _pos = 0; _streamPos = 0; _streamEndWasReached = false; ReadBlock(); } public void MovePos() throws IOException { _pos++; if (_pos > _posLimit) { int pointerToPostion = _bufferOffset + _pos; if (pointerToPostion > _pointerToLastSafePosition) MoveBlock(); ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } // index + limit have not to exceed _keepSizeAfter; public int GetMatchLen(int index, int distance, int limit) { if (_streamEndWasReached) if ((_pos + index) + limit > _streamPos) limit = _streamPos - (_pos + index); distance++; // Byte *pby = _buffer + (size_t)_pos + index; int pby = _bufferOffset + _pos + index; int i; for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); return i; } public int GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += subValue; _posLimit -= subValue; _pos -= subValue; _streamPos -= subValue; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZ/OutWindow.java ================================================ // LZ.OutWindow package SevenZip.Compression.LZ; import java.io.IOException; public class OutWindow { byte[] _buffer; int _pos; int _windowSize = 0; int _streamPos; java.io.OutputStream _stream; public void Create(int windowSize) { if (_buffer == null || _windowSize != windowSize) _buffer = new byte[windowSize]; _windowSize = windowSize; _pos = 0; _streamPos = 0; } public void SetStream(java.io.OutputStream stream) throws IOException { ReleaseStream(); _stream = stream; } public void ReleaseStream() throws IOException { Flush(); _stream = null; } public void Init(boolean solid) { if (!solid) { _streamPos = 0; _pos = 0; } } public void Flush() throws IOException { int size = _pos - _streamPos; if (size == 0) return; _stream.write(_buffer, _streamPos, size); if (_pos >= _windowSize) _pos = 0; _streamPos = _pos; } public void CopyBlock(int distance, int len) throws IOException { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; for (; len != 0; len--) { if (pos >= _windowSize) pos = 0; _buffer[_pos++] = _buffer[pos++]; if (_pos >= _windowSize) Flush(); } } public void PutByte(byte b) throws IOException { _buffer[_pos++] = b; if (_pos >= _windowSize) Flush(); } public byte GetByte(int distance) { int pos = _pos - distance - 1; if (pos < 0) pos += _windowSize; return _buffer[pos]; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZMA/Base.java ================================================ // Base.java package SevenZip.Compression.LZMA; public class Base { public static final int kNumRepDistances = 4; public static final int kNumStates = 12; public static final int StateInit() { return 0; } public static final int StateUpdateChar(int index) { if (index < 4) return 0; if (index < 10) return index - 3; return index - 6; } public static final int StateUpdateMatch(int index) { return (index < 7 ? 7 : 10); } public static final int StateUpdateRep(int index) { return (index < 7 ? 8 : 11); } public static final int StateUpdateShortRep(int index) { return (index < 7 ? 9 : 11); } public static final boolean StateIsCharState(int index) { return index < 7; } public static final int kNumPosSlotBits = 6; public static final int kDicLogSizeMin = 0; public static final int kDicLogSizeMax = 28; public static final int kDistTableSizeMax = kDicLogSizeMax * 2; public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits; public static final int kMatchMinLen = 2; public static final int GetLenToPosState(int len) { len -= kMatchMinLen; if (len < kNumLenToPosStates) return len; return (int)(kNumLenToPosStates - 1); } public static final int kNumAlignBits = 4; public static final int kAlignTableSize = 1 << kNumAlignBits; public static final int kAlignMask = (kAlignTableSize - 1); public static final int kStartPosModelIndex = 4; public static final int kEndPosModelIndex = 14; public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; public static final int kNumFullDistances = 1 << (kEndPosModelIndex / 2); public static final int kNumLitPosStatesBitsEncodingMax = 4; public static final int kNumLitContextBitsMax = 8; public static final int kNumPosStatesBitsMax = 4; public static final int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); public static final int kNumPosStatesBitsEncodingMax = 4; public static final int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); public static final int kNumLowLenBits = 3; public static final int kNumMidLenBits = 3; public static final int kNumHighLenBits = 8; public static final int kNumLowLenSymbols = 1 << kNumLowLenBits; public static final int kNumMidLenSymbols = 1 << kNumMidLenBits; public static final int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + (1 << kNumHighLenBits); public static final int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZMA/Decoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeDecoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.OutWindow; import java.io.IOException; public class Decoder { class LenDecoder { short[] m_Choice = new short[2]; BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); int m_NumPosStates = 0; public void Create(int numPosStates) { for (; m_NumPosStates < numPosStates; m_NumPosStates++) { m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits); m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits); } } public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice); for (int posState = 0; posState < m_NumPosStates; posState++) { m_LowCoder[posState].Init(); m_MidCoder[posState].Init(); } m_HighCoder.Init(); } public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException { if (rangeDecoder.DecodeBit(m_Choice, 0) == 0) return m_LowCoder[posState].Decode(rangeDecoder); int symbol = Base.kNumLowLenSymbols; if (rangeDecoder.DecodeBit(m_Choice, 1) == 0) symbol += m_MidCoder[posState].Decode(rangeDecoder); else symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder); return symbol; } } class LiteralDecoder { class Decoder2 { short[] m_Decoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException { int symbol = 1; do symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); while (symbol < 0x100); return (byte)symbol; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException { int symbol = 1; do { int matchBit = (matchByte >> 7) & 1; matchByte <<= 1; int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol); symbol = (symbol << 1) | bit; if (matchBit != bit) { while (symbol < 0x100) symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol); break; } } while (symbol < 0x100); return (byte)symbol; } } Decoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Decoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } Decoder2 GetDecoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } OutWindow m_OutWindow = new OutWindow(); SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] m_IsRepDecoders = new short[Base.kNumStates]; short[] m_IsRepG0Decoders = new short[Base.kNumStates]; short[] m_IsRepG1Decoders = new short[Base.kNumStates]; short[] m_IsRepG2Decoders = new short[Base.kNumStates]; short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); LenDecoder m_LenDecoder = new LenDecoder(); LenDecoder m_RepLenDecoder = new LenDecoder(); LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); int m_DictionarySize = -1; int m_DictionarySizeCheck = -1; int m_PosStateMask; public Decoder() { for (int i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); } boolean SetDictionarySize(int dictionarySize) { if (dictionarySize < 0) return false; if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.max(m_DictionarySize, 1); m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12))); } return true; } boolean SetLcLpPb(int lc, int lp, int pb) { if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax) return false; m_LiteralDecoder.Create(lp, lc); int numPosStates = 1 << pb; m_LenDecoder.Create(numPosStates); m_RepLenDecoder.Create(numPosStates); m_PosStateMask = numPosStates - 1; return true; } void Init() throws IOException { m_OutWindow.Init(false); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders); SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders); m_LiteralDecoder.Init(); int i; for (i = 0; i < Base.kNumLenToPosStates; i++) m_PosSlotDecoder[i].Init(); m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); m_RangeDecoder.Init(); } public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream, long outSize) throws IOException { m_RangeDecoder.SetStream(inStream); m_OutWindow.SetStream(outStream); Init(); int state = Base.StateInit(); int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; long nowPos64 = 0; byte prevByte = 0; while (outSize < 0 || nowPos64 < outSize) { int posState = (int)nowPos64 & m_PosStateMask; if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte); if (!Base.StateIsCharState(state)) prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0)); else prevByte = decoder2.DecodeNormal(m_RangeDecoder); m_OutWindow.PutByte(prevByte); state = Base.StateUpdateChar(state); nowPos64++; } else { int len; if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1) { len = 0; if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0) { if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0) { state = Base.StateUpdateShortRep(state); len = 1; } } else { int distance; if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0) distance = rep1; else { if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0) distance = rep2; else { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } if (len == 0) { len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; state = Base.StateUpdateRep(state); } } else { rep3 = rep2; rep2 = rep1; rep1 = rep0; len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); state = Base.StateUpdateMatch(state); int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); if (posSlot >= Base.kStartPosModelIndex) { int numDirectBits = (posSlot >> 1) - 1; rep0 = ((2 | (posSlot & 1)) << numDirectBits); if (posSlot < Base.kEndPosModelIndex) rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); else { rep0 += (m_RangeDecoder.DecodeDirectBits( numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); if (rep0 < 0) { if (rep0 == -1) break; return false; } } } else rep0 = posSlot; } if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck) { // m_OutWindow.Flush(); return false; } m_OutWindow.CopyBlock(rep0, len); nowPos64 += len; prevByte = m_OutWindow.GetByte(0); } } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); return true; } public boolean SetDecoderProperties(byte[] properties) { if (properties.length < 5) return false; int val = properties[0] & 0xFF; int lc = val % 9; int remainder = val / 9; int lp = remainder % 5; int pb = remainder / 5; int dictionarySize = 0; for (int i = 0; i < 4; i++) dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8); if (!SetLcLpPb(lc, lp, pb)) return false; return SetDictionarySize(dictionarySize); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/LZMA/Encoder.java ================================================ package SevenZip.Compression.LZMA; import SevenZip.Compression.RangeCoder.BitTreeEncoder; import SevenZip.Compression.LZMA.Base; import SevenZip.Compression.LZ.BinTree; import SevenZip.ICodeProgress; import java.io.IOException; public class Encoder { public static final int EMatchFinderTypeBT2 = 0; public static final int EMatchFinderTypeBT4 = 1; public static final int EMatchFinderTypeBT4B = 2; static final int kIfinityPrice = 0xFFFFFFF; static byte[] g_FastPos = new byte[1024]; static { int kFastSlots = 20; int c = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (int slotFast = 2; slotFast < kFastSlots; slotFast++) { int k = (1 << ((slotFast >> 1) - 1)); for (int j = 0; j < k; j++, c++) g_FastPos[c] = (byte)slotFast; } } static int GetPosSlot(int pos) { if (pos < (1 << 10)) return g_FastPos[pos]; if (pos < (1 << 19)) return g_FastPos[pos >> 9] + 18; return g_FastPos[pos >> 18] + 36; } static int GetPosSlot2(int pos) { if (pos < (1 << 16)) return g_FastPos[pos >> 6] + 12; if (pos < (1 << 25)) return g_FastPos[pos >> 15] + 30; return g_FastPos[pos >> 24] + 48; } int _state = Base.StateInit(); byte _previousByte; int[] _repDistances = new int[Base.kNumRepDistances]; void BaseInit() { _state = Base.StateInit(); _previousByte = 0; for (int i = 0; i < Base.kNumRepDistances; i++) _repDistances[i] = 0; } static final int kDefaultDictionaryLogSize = 20; static final int kNumFastBytesDefault = 0x20; class LiteralEncoder { class Encoder2 { short[] m_Encoders = new short[0x300]; public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException { int context = 1; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); rangeEncoder.Encode(m_Encoders, context, bit); context = (context << 1) | bit; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException { int context = 1; boolean same = true; for (int i = 7; i >= 0; i--) { int bit = ((symbol >> i) & 1); int state = context; if (same) { int matchBit = ((matchByte >> i) & 1); state += ((1 + matchBit) << 8); same = (matchBit == bit); } rangeEncoder.Encode(m_Encoders, state, bit); context = (context << 1) | bit; } } public int GetPrice(boolean matchMode, byte matchByte, byte symbol) { int price = 0; int context = 1; int i = 7; if (matchMode) { for (; i >= 0; i--) { int matchBit = (matchByte >> i) & 1; int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); context = (context << 1) | bit; if (matchBit != bit) { i--; break; } } } for (; i >= 0; i--) { int bit = (symbol >> i) & 1; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); context = (context << 1) | bit; } return price; } } Encoder2[] m_Coders; int m_NumPrevBits; int m_NumPosBits; int m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) return; m_NumPosBits = numPosBits; m_PosMask = (1 << numPosBits) - 1; m_NumPrevBits = numPrevBits; int numStates = 1 << (m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[numStates]; for (int i = 0; i < numStates; i++) m_Coders[i] = new Encoder2(); } public void Init() { int numStates = 1 << (m_NumPrevBits + m_NumPosBits); for (int i = 0; i < numStates; i++) m_Coders[i].Init(); } public Encoder2 GetSubCoder(int pos, byte prevByte) { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } } class LenEncoder { short[] _choice = new short[2]; BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); public LenEncoder() { for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) { _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); } } public void Init(int numPosStates) { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); for (int posState = 0; posState < numPosStates; posState++) { _lowCoder[posState].Init(); _midCoder[posState].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { if (symbol < Base.kNumLowLenSymbols) { rangeEncoder.Encode(_choice, 0, 0); _lowCoder[posState].Encode(rangeEncoder, symbol); } else { symbol -= Base.kNumLowLenSymbols; rangeEncoder.Encode(_choice, 0, 1); if (symbol < Base.kNumMidLenSymbols) { rangeEncoder.Encode(_choice, 1, 0); _midCoder[posState].Encode(rangeEncoder, symbol); } else { rangeEncoder.Encode(_choice, 1, 1); _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); } } } public int GetPrice(int symbol, int posState) { int price = 0; if (symbol < Base.kNumLowLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); price += _lowCoder[posState].GetPrice(symbol); } else { symbol -= Base.kNumLowLenSymbols; price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); if (symbol < Base.kNumMidLenSymbols) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); price += _midCoder[posState].GetPrice(symbol); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols); } } return price; } }; public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; class LenPriceTableEncoder extends LenEncoder { int[] _prices = new int[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; int _tableSize; int[] _counters = new int[Base.kNumPosStatesEncodingMax]; public void SetTableSize(int tableSize) { _tableSize = tableSize; } public int GetPrice(int symbol, int posState) { return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState]; } void UpdateTable(int posState) { for (int len = 0; len < _tableSize; len++) _prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = super.GetPrice(len, posState); _counters[posState] = _tableSize; } public void UpdateTables(int numPosStates) { for (int posState = 0; posState < numPosStates; posState++) UpdateTable(posState); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException { super.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) UpdateTable(posState); } } public static final int kNumOpts = 1 << 12; class Optimal { public int State; public boolean Prev1IsChar; public boolean Prev2; public int PosPrev2; public int BackPrev2; public int Price; public int PosPrev; // posNext; public int BackPrev; // public UInt32 []Backs = new UInt32[Base.kNumRepDistances]; public int Backs0; public int Backs1; public int Backs2; public int Backs3; public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } public boolean IsShortRep() { return (BackPrev == 0); } }; Optimal[] _optimum = new Optimal[kNumOpts]; SevenZip.Compression.LZ.BinTree _matchFinder = null; // test it SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); short[] _isMatch = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; short[] _isRep = new short[Base.kNumStates]; short[] _isRepG0 = new short[Base.kNumStates]; short[] _isRepG1 = new short[Base.kNumStates]; short[] _isRepG2 = new short[Base.kNumStates]; short[] _isRep0Long = new short[Base.kNumStates << Base.kNumPosStatesBitsMax]; BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits short[] _posEncoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex]; BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); LiteralEncoder _literalEncoder = new LiteralEncoder(); int[] _matchDistances = new int[Base.kMatchMaxLen + 1]; boolean _fastMode = false; boolean _maxMode = true; int _numFastBytes = kNumFastBytesDefault; int _longestMatchLength; int _additionalOffset; int _optimumEndIndex; int _optimumCurrentIndex; boolean _longestMatchWasFound; int [] _posSlotPrices = new int [Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits]; int [] _distancesPrices = new int [Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; int [] _alignPrices = new int [Base.kAlignTableSize]; int _alignPriceCount; int _distTableSize = (kDefaultDictionaryLogSize * 2); int _posStateBits = 2; int _posStateMask = (4 - 1); int _numLiteralPosStateBits = 0; int _numLiteralContextBits = 3; int _dictionarySize = (1 << kDefaultDictionaryLogSize); int _dictionarySizePrev = -1; int _numFastBytesPrev = -1; long lastPosSlotFillingPos; long nowPos64; boolean _finished; java.io.InputStream _inStream; int _matchFinderType = EMatchFinderTypeBT4; boolean _writeEndMark = false; boolean _needReleaseMFStream = false; void Create() { // _rangeEncoder.Create(1 << 20); if (_matchFinder == null) { SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); int numHashBytes = 4; boolean big = false; switch (_matchFinderType) { case EMatchFinderTypeBT2: numHashBytes = 2; break; case EMatchFinderTypeBT4: break; case EMatchFinderTypeBT4B: big = true; break; default: break; } bt.SetType(numHashBytes, big); _matchFinder = bt; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) return; _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen * 2 + 1 - _numFastBytes); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } public Encoder() { for (int i = 0; i < kNumOpts; i++) _optimum[i] = new Optimal(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); } void Init() { BaseInit(); _rangeEncoder.Init(); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); _literalEncoder.Init(); for (int i = 0; i < Base.kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; } int ReadMatchDistances() throws java.io.IOException { int lenRes = _matchFinder.GetLongestMatch(_matchDistances); if (lenRes == _numFastBytes) lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes], Base.kMatchMaxLen - lenRes); _additionalOffset++; _matchFinder.MovePos(); return lenRes; } void MovePos(int num) throws java.io.IOException { for (; num > 0; num--) { _matchFinder.DummyLongestMatch(); _matchFinder.MovePos(); _additionalOffset++; } } int GetRepLen1Price(int state, int posState) { return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } int GetRepPrice(int repIndex, int len, int state, int posState) { int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); if (repIndex == 0) { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); } else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); if (repIndex == 1) price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); else { price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); } } return price; } int GetPosLenPrice(int pos, int len, int posState) { if (len == 2 && pos >= 0x80) return kIfinityPrice; int price; int lenToPosState = Base.GetLenToPosState(len); if (pos < Base.kNumFullDistances) price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState]; else price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] + _alignPrices[pos & Base.kAlignMask]; return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); } int Backward(int[] backRes, int cur) { _optimumEndIndex = cur; int posMem = _optimum[cur].PosPrev; int backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } int posPrev = posMem; int backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while (cur > 0); backRes[0] = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } int[] reps = new int[Base.kNumRepDistances]; int[] repLens = new int[Base.kNumRepDistances]; int GetOptimum(int position, int []backRes) throws IOException { if (_optimumEndIndex != _optimumCurrentIndex) { int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes[0] = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return lenRes; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; int i; for (i = 0; i < Base.kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { int backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } byte currentByte = _matchFinder.GetIndexByte(0 - 1); _optimum[0].State = _state; byte matchByte; matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); int posState = (position & _posStateMask); _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); if (matchByte == currentByte) { int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if (shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if (lenMain < 2) { backRes[0] = _optimum[1].BackPrev; return 1; } int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; int len; for (len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + Base.kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for (i = 0; i < Base.kNumRepDistances; i++) { int repLen = repLens[i]; for (int lenTest = 2; lenTest <= repLen; lenTest++) { int curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); Optimal optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } int cur = 0; int lenEnd = lenMain; while (true) { cur++; if (cur == lenEnd) { return Backward(backRes, cur); } position++; int posPrev = _optimum[cur].PosPrev; int state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } else state = _optimum[posPrev].State; state = Base.StateUpdateChar(state); } else state = _optimum[posPrev].State; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) state = Base.StateUpdateShortRep(state); else state = Base.StateUpdateChar(state); } else { int pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state = Base.StateUpdateRep(state); } else { pos = _optimum[cur].BackPrev; if (pos < Base.kNumRepDistances) state = Base.StateUpdateRep(state); else state = Base.StateUpdateMatch(state); } Optimal opt = _optimum[posPrev]; if (pos < Base.kNumRepDistances) { if (pos == 0) { reps[0] = opt.Backs0; reps[1] = opt.Backs1; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 1) { reps[0] = opt.Backs1; reps[1] = opt.Backs0; reps[2] = opt.Backs2; reps[3] = opt.Backs3; } else if (pos == 2) { reps[0] = opt.Backs2; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs3; } else { reps[0] = opt.Backs3; reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } else { reps[0] = (pos - Base.kNumRepDistances); reps[1] = opt.Backs0; reps[2] = opt.Backs1; reps[3] = opt.Backs2; } } _optimum[cur].State = state; _optimum[cur].Backs0 = reps[0]; _optimum[cur].Backs1 = reps[1]; _optimum[cur].Backs2 = reps[2]; _optimum[cur].Backs3 = reps[3]; int newLen = ReadMatchDistances(); if (newLen >= _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; return Backward(backRes, cur); } int curPrice = _optimum[cur].Price; currentByte = _matchFinder.GetIndexByte(0 - 1); matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); posState = (position & _posStateMask); int curAnd1Price = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); Optimal nextOptimum = _optimum[cur + 1]; boolean nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); if (matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if (shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); int numAvailableBytes = numAvailableBytesFull; if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { int backOffset = reps[0] + 1; int temp; for (temp = 1; temp < numAvailableBytes; temp++) // if (data[temp] != data[(size_t)temp - backOffset]) if (_matchFinder.GetIndexByte(temp - 1) != _matchFinder.GetIndexByte(temp - backOffset - 1)) break; int lenTest2 = temp - 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateChar(state); int posStateNext = (position + 1) & _posStateMask; int nextRepMatchPrice = curAnd1Price + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for (; lenTest2 >= 2; lenTest2--) { while (lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) { // int repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; int backOffset = reps[repIndex] + 1; if (_matchFinder.GetIndexByte(-1) != _matchFinder.GetIndexByte(-1 - backOffset) || _matchFinder.GetIndexByte(0) != _matchFinder.GetIndexByte(0 - backOffset)) continue; int lenTest; for (lenTest = 2; lenTest < numAvailableBytes; lenTest++) if (_matchFinder.GetIndexByte(lenTest - 1) != _matchFinder.GetIndexByte(lenTest - 1 - backOffset)) break; int lenTestTemp = lenTest; do { while (lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } } while(--lenTest >= 2); lenTest = lenTestTemp; if (_maxMode) { int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - 1 - backOffset)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateRep(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, _matchFinder.GetIndexByte(lenTest - 1 - backOffset), _matchFinder.GetIndexByte(lenTest - 1)); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while(lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); Optimal optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = repIndex; } } } } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); while (lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice; for (int lenTest = newLen; lenTest >= 2; lenTest--) { int curBack = _matchDistances[lenTest]; int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); Optimal optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = curBack + Base.kNumRepDistances; optimum.Prev1IsChar = false; } if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1])) { int backOffset = curBack + 1; int lenTest2 = lenTest + 1; int limit = Math.min(numAvailableBytesFull, lenTest2 + _numFastBytes); for (; lenTest2 < limit; lenTest2++) if (_matchFinder.GetIndexByte(lenTest2 - 1) != _matchFinder.GetIndexByte(lenTest2 - backOffset - 1)) break; lenTest2 -= lenTest + 1; if (lenTest2 >= 2) { int state2 = Base.StateUpdateMatch(state); int posStateNext = (position + lenTest) & _posStateMask; int curAndLenCharPrice = curAndLenPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + _literalEncoder.GetSubCoder(position + lenTest, _matchFinder.GetIndexByte(lenTest - 1 - 1)). GetPrice(true, _matchFinder.GetIndexByte(lenTest - backOffset - 1), _matchFinder.GetIndexByte(lenTest - 1) ); state2 = Base.StateUpdateChar(state2); posStateNext = (position + lenTest + 1) & _posStateMask; int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); // for(; lenTest2 >= 2; lenTest2--) { int offset = lenTest + 1 + lenTest2; while (lenEnd < cur + offset) _optimum[++lenEnd].Price = kIfinityPrice; curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); optimum = _optimum[cur + offset]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + lenTest + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = true; optimum.PosPrev2 = cur; optimum.BackPrev2 = curBack + Base.kNumRepDistances; } } } } } } } } boolean ChangePair(int smallDist, int bigDist) { int kDif = 7; return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); } int GetOptimumFast(int position, int[] backRes) throws IOException { int lenMain; if (!_longestMatchWasFound) { lenMain = ReadMatchDistances(); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } int repMaxIndex = 0; for (int i = 0; i < Base.kNumRepDistances; i++) { repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (i == 0 || repLens[i] > repLens[repMaxIndex]) repMaxIndex = i; } if (repLens[repMaxIndex] >= _numFastBytes) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } if (lenMain >= _numFastBytes) { backRes[0] = _matchDistances[_numFastBytes] + Base.kNumRepDistances; MovePos(lenMain - 1); return lenMain; } while (lenMain > 2) { if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain])) break; lenMain--; } if (lenMain == 2 && _matchDistances[2] >= 0x80) lenMain = 1; int backMain = _matchDistances[lenMain]; if (repLens[repMaxIndex] >= 2) { if (repLens[repMaxIndex] + 1 >= lenMain || repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 12))) { backRes[0] = repMaxIndex; int lenRes = repLens[repMaxIndex]; MovePos(lenRes - 1); return lenRes; } } if (lenMain >= 2) { _longestMatchLength = ReadMatchDistances(); if (_longestMatchLength >= 2 && ( (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) || _longestMatchLength == lenMain + 1 && !ChangePair(backMain, _matchDistances[_longestMatchLength]) || _longestMatchLength > lenMain + 1 || _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(_matchDistances[lenMain - 1], backMain) ) ) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } for (int i = 0; i < Base.kNumRepDistances; i++) { int repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen); if (repLen >= 2 && repLen + 1 >= lenMain) { _longestMatchWasFound = true; backRes[0] = -1; return 1; } } backRes[0] = backMain + Base.kNumRepDistances; MovePos(lenMain - 2); return lenMain; } backRes[0] = -1; return 1; } void WriteEndMarker(int posState) throws IOException { if (!_writeEndMark) return; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); int len = Base.kMatchMinLen; // kMatchMaxLen; _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); int posSlot = (1 << Base.kNumPosSlotBits) - 1; int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); int footerBits = 30; int posReduced = (1 << footerBits) - 1; _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); } void Flush(int nowPos) throws IOException { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } int[] posTemp = new int[1]; public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException { inSize[0] = 0; outSize[0] = 0; finished[0] = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; } if (_finished) return; _finished = true; long progressPosValuePrev = nowPos64; if (nowPos64 == 0) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } ReadMatchDistances(); int posState = (int)(nowPos64) & _posStateMask; _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); _state = Base.StateUpdateChar(_state); byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); _previousByte = curByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } while (true) { int posState = ((int)nowPos64) & _posStateMask; int len; if (_fastMode) len = GetOptimumFast((int)nowPos64, posTemp); else len = GetOptimum((int)nowPos64, posTemp); int pos = posTemp[0]; int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; if (len == 1 && pos == -1) { _rangeEncoder.Encode(_isMatch, complexState, 0); byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); if (!Base.StateIsCharState(_state)) { byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); } else subCoder.Encode(_rangeEncoder, curByte); _previousByte = curByte; _state = Base.StateUpdateChar(_state); } else { _rangeEncoder.Encode(_isMatch, complexState, 1); if (pos < Base.kNumRepDistances) { _rangeEncoder.Encode(_isRep, _state, 1); if (pos == 0) { _rangeEncoder.Encode(_isRepG0, _state, 0); if (len == 1) _rangeEncoder.Encode(_isRep0Long, complexState, 0); else _rangeEncoder.Encode(_isRep0Long, complexState, 1); } else { _rangeEncoder.Encode(_isRepG0, _state, 1); if (pos == 1) _rangeEncoder.Encode(_isRepG1, _state, 0); else { _rangeEncoder.Encode(_isRepG1, _state, 1); _rangeEncoder.Encode(_isRepG2, _state, pos - 2); } } if (len == 1) _state = Base.StateUpdateShortRep(_state); else { _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); _state = Base.StateUpdateRep(_state); } int distance = _repDistances[pos]; if (pos != 0) { for (int i = pos; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } } else { _rangeEncoder.Encode(_isRep, _state, 0); _state = Base.StateUpdateMatch(_state); _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); pos -= Base.kNumRepDistances; int posSlot = GetPosSlot(pos); int lenToPosState = Base.GetLenToPosState(len); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= Base.kStartPosModelIndex) { int footerBits = (int)((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); int posReduced = pos - baseVal; if (posSlot < Base.kEndPosModelIndex) BitTreeEncoder.ReverseEncode(_posEncoders, baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); else { _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); if (!_fastMode) if (--_alignPriceCount == 0) FillAlignPrices(); } } int distance = pos; for (int i = Base.kNumRepDistances - 1; i >= 1; i--) _repDistances[i] = _repDistances[i - 1]; _repDistances[0] = distance; } _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); } _additionalOffset -= len; nowPos64 += len; if (!_fastMode) if (nowPos64 - lastPosSlotFillingPos >= (1 << 9)) { FillPosSlotPrices(); FillDistancesPrices(); lastPosSlotFillingPos = nowPos64; } if (_additionalOffset == 0) { inSize[0] = nowPos64; outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((int)nowPos64); return; } if (nowPos64 - progressPosValuePrev >= (1 << 12)) { _finished = false; finished[0] = false; return; } } } } void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } void SetOutStream(java.io.OutputStream outStream) { _rangeEncoder.SetStream(outStream); } void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); if (!_fastMode) { FillPosSlotPrices(); FillDistancesPrices(); FillAlignPrices(); } _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _lenEncoder.UpdateTables(1 << _posStateBits); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); _repMatchLenEncoder.UpdateTables(1 << _posStateBits); lastPosSlotFillingPos = 0; nowPos64 = 0; } long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress) throws IOException { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(processedInSize, processedOutSize, finished); if (finished[0]) return; if (progress != null) { progress.SetProgress(processedInSize[0], processedOutSize[0]); } } } finally { ReleaseStreams(); } } public static final int kPropSize = 5; byte[] properties = new byte[kPropSize]; public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); outStream.write(properties, 0, kPropSize); } void FillPosSlotPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int posSlot; for (posSlot = 0; posSlot < Base.kEndPosModelIndex && posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot); for (; posSlot < _distTableSize; posSlot++) _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) + ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); } } void FillDistancesPrices() { for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) { int i; for (i = 0; i < Base.kStartPosModelIndex; i++) _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState]; for (; i < Base.kNumFullDistances; i++) { int posSlot = GetPosSlot(i); int footerBits = ((posSlot >> 1) - 1); int baseVal = ((2 | (posSlot & 1)) << footerBits); _distancesPrices[(i << Base.kNumLenToPosStatesBits) + lenToPosState] = _posSlotPrices[(posSlot << Base.kNumLenToPosStatesBits) + lenToPosState] + BitTreeEncoder.ReverseGetPrice(_posEncoders, baseVal - posSlot - 1, footerBits, i - baseVal); } } } void FillAlignPrices() { for (int i = 0; i < Base.kAlignTableSize; i++) _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); _alignPriceCount = Base.kAlignTableSize; } public boolean SetAlgorithm(int algorithm) { if (algorithm < 0 || algorithm > 2) return false; _fastMode = (algorithm == 0); _maxMode = (algorithm >= 2); return true; } public boolean SetDictionarySize(int dictionarySize) { int kDicLogSizeMaxCompress = Base.kDicLogSizeMax; if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) return false; _dictionarySize = dictionarySize; int dicLogSize; for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++); _distTableSize = dicLogSize * 2; return true; } public boolean SeNumFastBytes(int numFastBytes) { if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) return false; _numFastBytes = numFastBytes; return true; } public boolean SetMatchFinder(int matchFinderIndex) { if (matchFinderIndex < 0 || matchFinderIndex > 2) return false; int matchFinderIndexPrev = _matchFinderType; _matchFinderType = matchFinderIndex; if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) { _dictionarySizePrev = -1; _matchFinder = null; } return true; } public boolean SetLcLpPb(int lc, int lp, int pb) { if ( lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || lc < 0 || lc > Base.kNumLitContextBitsMax || pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) return false; _numLiteralPosStateBits = lp; _numLiteralContextBits = lc; _posStateBits = pb; _posStateMask = ((1) << _posStateBits) - 1; return true; } public void SetEndMarkerMode(boolean endMarkerMode) { _writeEndMark = endMarkerMode; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java ================================================ package SevenZip.Compression.RangeCoder; public class BitTreeDecoder { short[] Models; int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public int Decode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) m = (m << 1) + rangeDecoder.DecodeBit(Models, m); return m - (1 << NumBitLevels); } public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } public static int ReverseDecode(short[] Models, int startIndex, Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException { int m = 1; int symbol = 0; for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) { int bit = rangeDecoder.DecodeBit(Models, startIndex + m); m <<= 1; m += bit; symbol |= (bit << bitIndex); } return symbol; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class BitTreeEncoder { short[] Models; int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new short[1 << numBitLevels]; } public void Init() { Decoder.InitBitModels(Models); } public void Encode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; } } public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, m, bit); m = (m << 1) | bit; symbol >>= 1; } } public int GetPrice(int symbol) { int price = 0; int m = 1; for (int bitIndex = NumBitLevels; bitIndex != 0; ) { bitIndex--; int bit = (symbol >>> bitIndex) & 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) + bit; } return price; } public int ReverseGetPrice(int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[m], bit); m = (m << 1) | bit; } return price; } public static int ReverseGetPrice(short[] Models, int startIndex, int NumBitLevels, int symbol) { int price = 0; int m = 1; for (int i = NumBitLevels; i != 0; i--) { int bit = symbol & 1; symbol >>>= 1; price += Encoder.GetPrice(Models[startIndex + m], bit); m = (m << 1) | bit; } return price; } public static void ReverseEncode(short[] Models, int startIndex, Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException { int m = 1; for (int i = 0; i < NumBitLevels; i++) { int bit = symbol & 1; rangeEncoder.Encode(Models, startIndex + m, bit); m = (m << 1) | bit; symbol >>= 1; } } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Decoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; int Range; int Code; java.io.InputStream Stream; public final void SetStream(java.io.InputStream stream) { Stream = stream; } public final void ReleaseStream() { Stream = null; } public final void Init() throws IOException { Code = 0; Range = -1; for (int i = 0; i < 5; i++) Code = (Code << 8) | Stream.read(); } public final int DecodeDirectBits(int numTotalBits) throws IOException { int result = 0; for (int i = numTotalBits; i != 0; i--) { Range >>>= 1; int t = ((Code - Range) >>> 31); Code -= Range & (t - 1); result = (result << 1) | (1 - t); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } } return result; } public int DecodeBit(short []probs, int index) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if ((Code ^ 0x80000000) < (newBound ^ 0x80000000)) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 0; } else { Range -= newBound; Code -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); if ((Range & kTopMask) == 0) { Code = (Code << 8) | Stream.read(); Range <<= 8; } return 1; } } public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java ================================================ package SevenZip.Compression.RangeCoder; import java.io.IOException; public class Encoder { static final int kTopMask = ~((1 << 24) - 1); static final int kNumBitModelTotalBits = 11; static final int kBitModelTotal = (1 << kNumBitModelTotalBits); static final int kNumMoveBits = 5; java.io.OutputStream Stream; long Low; int Range; int _cacheSize; int _cache; long _position; public void SetStream(java.io.OutputStream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { _position = 0; Low = 0; Range = -1; _cacheSize = 1; _cache = 0; } public void FlushData() throws IOException { for (int i = 0; i < 5; i++) ShiftLow(); } public void FlushStream() throws IOException { Stream.flush(); } public void ShiftLow() throws IOException { int LowHi = (int)(Low >>> 32); if (LowHi != 0 || Low < 0xFF000000L) { _position += _cacheSize; int temp = _cache; do { Stream.write(temp + LowHi); temp = 0xFF; } while(--_cacheSize != 0); _cache = (((int)Low) >>> 24); } _cacheSize++; Low = (Low & 0xFFFFFF) << 8; } public void EncodeDirectBits(int v, int numTotalBits) throws IOException { for (int i = numTotalBits - 1; i >= 0; i--) { Range >>>= 1; if (((v >>> i) & 1) == 1) Low += Range; if ((Range & Encoder.kTopMask) == 0) { Range <<= 8; ShiftLow(); } } } public long GetProcessedSizeAdd() { return _cacheSize + _position + 4; } static final int kNumMoveReducingBits = 2; public static final int kNumBitPriceShiftBits = 6; public static void InitBitModels(short []probs) { for (int i = 0; i < probs.length; i++) probs[i] = (kBitModelTotal >>> 1); } public void Encode(short []probs, int index, int symbol) throws IOException { int prob = probs[index]; int newBound = (Range >>> kNumBitModelTotalBits) * prob; if (symbol == 0) { Range = newBound; probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits)); } else { Low += (newBound & 0xFFFFFFFFL); Range -= newBound; probs[index] = (short)(prob - ((prob) >>> kNumMoveBits)); } if ((Range & kTopMask) == 0) { Range <<= 8; ShiftLow(); } } private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits]; static { int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); for (int i = kNumBits - 1; i >= 0; i--) { int start = 1 << (kNumBits - i - 1); int end = 1 << (kNumBits - i); for (int j = start; j < end; j++) ProbPrices[j] = (i << kNumBitPriceShiftBits) + (((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1)); } } static public int GetPrice(int Prob, int symbol) { return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits]; } static public int GetPrice0(int Prob) { return ProbPrices[Prob >>> kNumMoveReducingBits]; } static public int GetPrice1(int Prob) { return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/LzmaAlone.java ================================================ package SevenZip; public class LzmaAlone { static public class CommandLine { public static final int kEncode = 0; public static final int kDecode = 1; public static final int kBenchmak = 2; public int Command = -1; public int NumBenchmarkPasses = 10; public int DictionarySize = 1 << 23; public boolean DictionarySizeIsDefined = false; public int Lc = 3; public int Lp = 0; public int Pb = 2; public int Fb = 128; public boolean FbIsDefined = false; public boolean Eos = false; public int Algorithm = 2; public int MatchFinder = 1; public String InFile; public String OutFile; boolean ParseSwitch(String s) { if (s.startsWith("d")) { DictionarySize = 1 << Integer.parseInt(s.substring(1)); DictionarySizeIsDefined = true; } else if (s.startsWith("fb")) { Fb = Integer.parseInt(s.substring(2)); FbIsDefined = true; } else if (s.startsWith("a")) Algorithm = Integer.parseInt(s.substring(1)); else if (s.startsWith("lc")) Lc = Integer.parseInt(s.substring(2)); else if (s.startsWith("lp")) Lp = Integer.parseInt(s.substring(2)); else if (s.startsWith("pb")) Pb = Integer.parseInt(s.substring(2)); else if (s.startsWith("eos")) Eos = true; else if (s.startsWith("mf")) { String mfs = s.substring(2); if (mfs.equals("bt2")) MatchFinder = 0; else if (mfs.equals("bt4")) MatchFinder = 1; else if (mfs.equals("bt4b")) MatchFinder = 2; else return false; } else return false; return true; } public boolean Parse(String[] args) throws Exception { int pos = 0; boolean switchMode = true; for (int i = 0; i < args.length; i++) { String s = args[i]; if (s.length() == 0) return false; if (switchMode) { if (s.compareTo("--") == 0) { switchMode = false; continue; } if (s.charAt(0) == '-') { String sw = s.substring(1).toLowerCase(); if (sw.length() == 0) return false; try { if (!ParseSwitch(sw)) return false; } catch (NumberFormatException e) { return false; } continue; } } if (pos == 0) { if (s.equalsIgnoreCase("e")) Command = kEncode; else if (s.equalsIgnoreCase("d")) Command = kDecode; else if (s.equalsIgnoreCase("b")) Command = kBenchmak; else return false; } else if(pos == 1) { if (Command == kBenchmak) { try { NumBenchmarkPasses = Integer.parseInt(s); if (NumBenchmarkPasses < 1) return false; } catch (NumberFormatException e) { return false; } } else InFile = s; } else if(pos == 2) OutFile = s; else return false; pos++; continue; } return true; } } static void PrintHelp() { System.out.println( "\nUsage: LZMA [...] inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 2], default: 2 (max)\n" + " -d{N}: set dictionary - [0,28], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt4, bt4b], default: bt4\n" + " -eos: write End Of Stream marker\n" ); } public static void main(String[] args) throws Exception { System.out.println("\nLZMA (Java) 4.32 Copyright (c) 1999-2005 Igor Pavlov 2005-12-09\n"); if (args.length < 1) { PrintHelp(); return; } CommandLine params = new CommandLine(); if (!params.Parse(args)) { System.out.println("\nIncorrect command"); return; } if (params.Command == CommandLine.kBenchmak) { int dictionary = (1 << 21); if (params.DictionarySizeIsDefined) dictionary = params.DictionarySize; if (params.MatchFinder > 1) throw new Exception("Unsupported match finder"); SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary, params.MatchFinder >= 1); } else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode) { java.io.File inFile = new java.io.File(params.InFile); java.io.File outFile = new java.io.File(params.OutFile); java.io.BufferedInputStream inStream = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile)); java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile)); boolean eos = false; if (params.Eos) eos = true; if (params.Command == CommandLine.kEncode) { SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); if (!encoder.SetAlgorithm(params.Algorithm)) throw new Exception("Incorrect compression mode"); if (!encoder.SetDictionarySize(params.DictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SeNumFastBytes(params.Fb)) throw new Exception("Incorrect -fb value"); if (!encoder.SetMatchFinder(params.MatchFinder)) throw new Exception("Incorrect -mf value"); if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb)) throw new Exception("Incorrect -lc or -lp or -pb value"); encoder.SetEndMarkerMode(eos); encoder.WriteCoderProperties(outStream); long fileSize; if (eos) fileSize = -1; else fileSize = inFile.length(); for (int i = 0; i < 8; i++) outStream.write((int)(fileSize >>> (8 * i)) & 0xFF); encoder.Code(inStream, outStream, -1, -1, null); } else { int propertiesSize = 5; byte[] properties = new byte[propertiesSize]; if (inStream.read(properties, 0, propertiesSize) != propertiesSize) throw new Exception("input .lzma file is too short"); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!decoder.SetDecoderProperties(properties)) throw new Exception("Incorrect stream properties"); long outSize = 0; for (int i = 0; i < 8; i++) { int v = inStream.read(); if (v < 0) throw new Exception("Can't read stream size"); outSize |= ((long)v) << (8 * i); } if (!decoder.Code(inStream, outStream, outSize)) throw new Exception("Error in data stream"); } outStream.flush(); outStream.close(); inStream.close(); } else throw new Exception("Incorrect command"); return; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Java/SevenZip/LzmaBench.java ================================================ package SevenZip; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class LzmaBench { static final int kAdditionalSize = (1 << 21); static final int kCompressedAdditionalSize = (1 << 10); static class CRandomGenerator { int A1; int A2; public CRandomGenerator() { Init(); } public void Init() { A1 = 362436069; A2 = 521288629; } public int GetRnd() { return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); } }; static class CBitRandomGenerator { CRandomGenerator RG = new CRandomGenerator(); int Value; int NumBits; public void Init() { Value = 0; NumBits = 0; } public int GetRnd(int numBits) { int result; if (NumBits > numBits) { result = Value & ((1 << numBits) - 1); Value >>>= numBits; NumBits -= numBits; return result; } numBits -= NumBits; result = (Value << numBits); Value = RG.GetRnd(); result |= Value & (((int)1 << numBits) - 1); Value >>>= numBits; NumBits = 32 - numBits; return result; } }; static class CBenchRandomGenerator { CBitRandomGenerator RG = new CBitRandomGenerator(); int Pos; public int BufferSize; public byte[] Buffer = null; public CBenchRandomGenerator() { } public void Init() { RG.Init(); } public void Set(int bufferSize) { Buffer = new byte[bufferSize]; Pos = 0; BufferSize = bufferSize; } int GetRndBit() { return RG.GetRnd(1); } int GetLogRandBits(int numBits) { int len = RG.GetRnd(numBits); return RG.GetRnd((int)len); } int GetOffset() { if (GetRndBit() == 0) return GetLogRandBits(4); return (GetLogRandBits(4) << 10) | RG.GetRnd(10); } int GetLen() { if (GetRndBit() == 0) return RG.GetRnd(2); if (GetRndBit() == 0) return 4 + RG.GetRnd(3); return 12 + RG.GetRnd(4); } public void Generate() { while (Pos < BufferSize) { if (GetRndBit() == 0 || Pos < 1) Buffer[Pos++] = (byte)(RG.GetRnd(8)); else { int offset = GetOffset(); while (offset >= Pos) offset >>>= 1; offset += 1; int len = 2 + GetLen(); for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) Buffer[Pos] = Buffer[Pos - offset]; } } } }; static class CrcOutStream extends java.io.OutputStream { public CRC CRC = new CRC(); public void Init() { CRC.Init(); } public int GetDigest() { return CRC.GetDigest(); } public void write(byte[] b) { CRC.Update(b); } public void write(byte[] b, int off, int len) { CRC.Update(b, off, len); } public void write(int b) { CRC.UpdateByte(b); } }; static class MyOutputStream extends java.io.OutputStream { byte[] _buffer; int _size; int _pos; public MyOutputStream(byte[] buffer) { _buffer = buffer; _size = _buffer.length; } public void reset() { _pos = 0; } public void write(int b) throws IOException { if (_pos >= _size) throw new IOException("Error"); _buffer[_pos++] = (byte)b; } public int size() { return _pos; } }; static class MyInputStream extends java.io.InputStream { byte[] _buffer; int _size; int _pos; public MyInputStream(byte[] buffer, int size) { _buffer = buffer; _size = size; } public void reset() { _pos = 0; } public int read() { if (_pos >= _size) return -1; return _buffer[_pos++] & 0xFF; } }; static class CProgressInfo implements ICodeProgress { public long ApprovedStart; public long InSize; public long Time; public void Init() { InSize = 0; } public void SetProgress(long inSize, long outSize) { if (inSize >= ApprovedStart && InSize == 0) { Time = System.currentTimeMillis(); InSize = inSize; } } } static final int kSubBits = 8; static int GetLogSize(int size) { for (int i = kSubBits; i < 32; i++) for (int j = 0; j < (1 << kSubBits); j++) if (size <= ((1) << i) + (j << (i - kSubBits))) return (i << kSubBits) + j; return (32 << kSubBits); } static long MyMultDiv64(long value, long elapsedTime) { long freq = 1000; // ms long elTime = elapsedTime; while (freq > 1000000) { freq >>>= 1; elTime >>>= 1; } if (elTime == 0) elTime = 1; return value * freq / elTime; } static long GetCompressRating(int dictionarySize, boolean isBT4, long elapsedTime, long size) { long numCommandsForOne; if (isBT4) { long t = GetLogSize(dictionarySize) - (19 << kSubBits); numCommandsForOne = 2000 + ((t * t * 68) >>> (2 * kSubBits)); } else { long t = GetLogSize(dictionarySize) - (15 << kSubBits); numCommandsForOne = 1500 + ((t * t * 41) >>> (2 * kSubBits)); } long numCommands = (long)(size) * numCommandsForOne; return MyMultDiv64(numCommands, elapsedTime); } static long GetDecompressRating(long elapsedTime, long outSize, long inSize) { long numCommands = inSize * 250 + outSize * 21; return MyMultDiv64(numCommands, elapsedTime); } static long GetTotalRating( int dictionarySize, boolean isBT4, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe) { return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; } static void PrintValue(long v) { String s = ""; s += v; for (int i = 0; i + s.length() < 6; i++) System.out.print(" "); System.out.print(s); } static void PrintRating(long rating) { PrintValue(rating / 1000000); System.out.print(" MIPS"); } static void PrintResults( int dictionarySize, boolean isBT4, long elapsedTime, long size, boolean decompressMode, long secondSize) { long speed = MyMultDiv64(size, elapsedTime); PrintValue(speed / 1024); System.out.print(" KB/s "); long rating; if (decompressMode) rating = GetDecompressRating(elapsedTime, size, secondSize); else rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size); PrintRating(rating); } String bt2 = "BT2"; String bt4 = "BT4"; static public int LzmaBenchmark(int numIterations, int dictionarySize, boolean isBT4) throws Exception { if (numIterations <= 0) return 0; if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15)) { System.out.println("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); return 1; } System.out.print("\n Compressing Decompressing\n\n"); SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); if (!encoder.SetDictionarySize(dictionarySize)) throw new Exception("Incorrect dictionary size"); if (!encoder.SetMatchFinder(isBT4 ? SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT4: SevenZip.Compression.LZMA.Encoder.EMatchFinderTypeBT2)) throw new Exception("Incorrect MatchFinder"); int kBufferSize = dictionarySize + kAdditionalSize; int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; ByteArrayOutputStream propStream = new ByteArrayOutputStream(); encoder.WriteCoderProperties(propStream); byte[] propArray = propStream.toByteArray(); decoder.SetDecoderProperties(propArray); CBenchRandomGenerator rg = new CBenchRandomGenerator(); rg.Init(); rg.Set(kBufferSize); rg.Generate(); CRC crc = new CRC(); crc.Init(); crc.Update(rg.Buffer, 0, rg.BufferSize); CProgressInfo progressInfo = new CProgressInfo(); progressInfo.ApprovedStart = dictionarySize; long totalBenchSize = 0; long totalEncodeTime = 0; long totalDecodeTime = 0; long totalCompressedSize = 0; MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); byte[] compressedBuffer = new byte[kCompressedBufferSize]; MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); CrcOutStream crcOutStream = new CrcOutStream(); MyInputStream inputCompressedStream = null; int compressedSize = 0; for (int i = 0; i < numIterations; i++) { progressInfo.Init(); inStream.reset(); compressedStream.reset(); encoder.Code(inStream, compressedStream, -1, -1, progressInfo); long encodeTime = System.currentTimeMillis() - progressInfo.Time; if (i == 0) { compressedSize = compressedStream.size(); inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); } else if (compressedSize != compressedStream.size()) throw (new Exception("Encoding error")); if (progressInfo.InSize == 0) throw (new Exception("Internal ERROR 1282")); long decodeTime = 0; for (int j = 0; j < 2; j++) { inputCompressedStream.reset(); crcOutStream.Init(); long outSize = kBufferSize; long startTime = System.currentTimeMillis(); if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) throw (new Exception("Decoding Error"));; decodeTime = System.currentTimeMillis() - startTime; if (crcOutStream.GetDigest() != crc.GetDigest()) throw (new Exception("CRC Error")); } long benchSize = kBufferSize - (long)progressInfo.InSize; PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize); System.out.println(); totalBenchSize += benchSize; totalEncodeTime += encodeTime; totalDecodeTime += decodeTime; totalCompressedSize += compressedSize; } System.out.println("---------------------------------------------------"); PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0); System.out.print(" "); PrintResults(dictionarySize, isBT4, totalDecodeTime, kBufferSize * (long)numIterations, true, totalCompressedSize); System.out.println(" Average"); return 0; } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/LGPL.txt ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/Methods.txt ================================================ Compression method IDs (4.27) ----------------------------- Each compression method in 7z has unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 15 bytes. List of defined IDs ------------------- 00 - Copy 01 - Reserved 02 - Common 03 Swap - 2 Swap2 - 4 Swap4 04 Delta (subject to change) 03 - 7z 01 - LZMA 01 - Version 03 - Branch 01 - x86 03 - BCJ 1B - BCJ2 02 - PPC 05 - BC_PPC_B (Big Endian) 03 - Alpha 01 - BC_Alpha 04 - IA64 01 - BC_IA64 05 - ARM 01 - BC_ARM 06 - M68 05 - BC_M68_B (Big Endian) 07 - ARM Thumb 01 - BC_ARMThumb 08 - SPARC 05 - BC_SPARC 04 - PPMD 01 - Version 04 - Misc 00 - Reserved 01 - Zip 00 - Copy (not used). Use {00} instead 01 - Shrink 06 - Implode 08 - Deflate 09 - Deflate64 12 - BZip2 (not used). Use {04 02 02} instead 02 - BZip 02 - BZip2 03 - Rar 01 - Rar15 02 - Rar20 03 - Rar29 04 - Arj 01 - Arj (1,2,3) 02 - Arj 4 05 - Z 06 - Lzh 07 - Reserved for 7z 08 - Cab 06 - Crypto 00 - 01 - AES 0x - AES-128 4x - AES-192 8x - AES-256 x0 - ECB x1 - CBC x2 - CFB x3 - OFB 07 - Reserved 0F - Reserved F0 - Misc Ciphers (Real Ciphers without hashing algo) F1 - Misc Ciphers (Combine) 01 - Zip 01 - Main Zip crypto algo 03 - RAR 02 - 03 - Rar29 AES-128 + (modified SHA-1) 07 - 7z 01 - AES-256 + SHA-256 07 - Hash (subject to change) 00 - 01 - CRC 02 - SHA-1 03 - SHA-256 04 - SHA-384 05 - SHA-512 F0 - Misc Hash F1 - Misc 03 - RAR 03 - Rar29 Password Hashing (modified SHA1) 07 - 7z 01 - SHA-256 Password Hashing --- End of document ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/history.txt ================================================ HISTORY of the LZMA SDK ----------------------- Version 4.32 2005-12-09 -------------------------------------- - Java version of LZMA SDK was included Version 4.30 2005-11-20 -------------------------------------- - Compression ratio was improved in -a2 mode - Speed optimizations for compressing in -a2 mode - -fb switch now supports values up to 273 - Bug in 7z_C (7zIn.c) was fixed: It used Alloc/Free functions from different memory pools. So if program used two memory pools, it worked incorrectly. - 7z_C: .7z format supporting was improved - LZMA# SDK (C#.NET version) was included Version 4.27 (Updated) 2005-09-21 -------------------------------------- - Some GUIDs/interfaces in C++ were changed. IStream.h: ISequentialInStream::Read now works as old ReadPart ISequentialOutStream::Write now works as old WritePart Version 4.27 2005-08-07 -------------------------------------- - Bug in LzmaDecodeSize.c was fixed: if _LZMA_IN_CB and _LZMA_OUT_READ were defined, decompressing worked incorrectly. Version 4.26 2005-08-05 -------------------------------------- - Fixes in 7z_C code and LzmaTest.c: previous versions could work incorrectly, if malloc(0) returns 0 Version 4.23 2005-06-29 -------------------------------------- - Small fixes in C++ code Version 4.22 2005-06-10 -------------------------------------- - Small fixes Version 4.21 2005-06-08 -------------------------------------- - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed - New additional version of ANSI-C LZMA Decoder with zlib-like interface: - LzmaStateDecode.h - LzmaStateDecode.c - LzmaStateTest.c - ANSI-C LZMA Decoder now can decompress files larger than 4 GB Version 4.17 2005-04-18 -------------------------------------- - New example for RAM->RAM compressing/decompressing: LZMA + BCJ (filter for x86 code): - LzmaRam.h - LzmaRam.cpp - LzmaRamDecode.h - LzmaRamDecode.c - -f86 switch for lzma.exe Version 4.16 2005-03-29 -------------------------------------- - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, decoder could access memory outside of allocated range. - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). Old version of LZMA Decoder now is in file LzmaDecodeSize.c. LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c - Small speed optimization in LZMA C++ code - filter for SPARC's code was added - Simplified version of .7z ANSI-C Decoder was included Version 4.06 2004-09-05 -------------------------------------- - Bug in v4.05 was fixed: LZMA-Encoder didn't release output stream in some cases. Version 4.05 2004-08-25 -------------------------------------- - Source code of filters for x86, IA-64, ARM, ARM-Thumb and PowerPC code was included to SDK - Some internal minor changes Version 4.04 2004-07-28 -------------------------------------- - More compatibility with some C++ compilers Version 4.03 2004-06-18 -------------------------------------- - "Benchmark" command was added. It measures compressing and decompressing speed and shows rating values. Also it checks hardware errors. Version 4.02 2004-06-10 -------------------------------------- - C++ LZMA Encoder/Decoder code now is more portable and it can be compiled by GCC on Linux. Version 4.01 2004-02-15 -------------------------------------- - Some detection of data corruption was enabled. LzmaDecode.c / RangeDecoderReadByte ..... { rd->ExtraBytes = 1; return 0xFF; } Version 4.00 2004-02-13 -------------------------------------- - Original version of LZMA SDK HISTORY of the LZMA ------------------- 2001-2004: Improvements to LZMA compressing/decompressing code, keeping compatibility with original LZMA format 1996-2001: Development of LZMA compression format Some milestones: 2001-08-30: LZMA compression was added to 7-Zip 1999-01-02: First version of 7-Zip was released End of document ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/lzma/lzma.txt ================================================ LZMA SDK 4.32 ------------- LZMA SDK 4.32 Copyright (C) 1999-2005 Igor Pavlov LZMA SDK provides the documentation, samples, header files, libraries, and tools you need to develop applications that use LZMA compression. LZMA is default and general compression method of 7z format in 7-Zip compression program (www.7-zip.org). LZMA provides high compression ratio and very fast decompression. LZMA is an improved version of famous LZ77 compression algorithm. It was improved in way of maximum increasing of compression ratio, keeping high decompression speed and low memory requirements for decompressing. LICENSE ------- LZMA SDK is available under any of the following licenses: 1) GNU Lesser General Public License (GNU LGPL) 2) Common Public License (CPL) 3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 4) Proprietary license It means that you can select one of these four options and follow rules of that license. 1,2) GNU LGPL and CPL licenses are pretty similar and both these licenses are classified as - "Free software licenses" at http://www.gnu.org/ - "OSI-approved" at http://www.opensource.org/ 3) 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 files from LZMA SDK without subjecting your linked code to the terms of the CPL or GNU LGPL. Any modifications or additions to files from LZMA SDK, however, are subject to the GNU LGPL or CPL terms. SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, while you keep LZMA SDK code unmodified. SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits you to use this code under the same terms and conditions contained in the License Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov. SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version of LZMA SDK as update for previous versions. SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits you to use code of examples (LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, LzmaAlone.cs, LzmaAlone.java) as public domain code. 4) Proprietary license LZMA SDK also can be available under a proprietary license which can include: 1) Right to modify code without subjecting modified code to the terms of the CPL or GNU LGPL 2) Technical support for code To request such proprietary license or any additional consultations, send email message from that page: http://www.7-zip.org/support.html You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You should have received a copy of the Common Public License along with this library. LZMA SDK Contents ----------------- LZMA SDK includes: - C++ source code of LZMA compressing and decompressing - ANSI-C compatible source code for LZMA decompressing - C# source code for LZMA compressing and decompressing - Java source code for LZMA compressing and decompressing - Compiled file->file LZMA compressing/decompressing program for Windows system ANSI-C LZMA decompression code was ported from original C++ sources to C. Also it was simplified and optimized for code size. But it is fully compatible with LZMA from 7-Zip. UNIX/Linux version ------------------ To compile C++ version of file->file LZMA, go to directory C/7zip/Compress/LZMA_Alone and type "make" or "make clean all" to recompile all. In some UNIX/Linux versions you must compile LZMA with static libraries. To compile with static libraries, change string in makefile LIB = -lm to string LIB = -lm -static Files --------------------- C - C / CPP source code CS - C# source code Java - Java source code lzma.txt - LZMA SDK description (this file) 7zFormat.txt - 7z Format description 7zC.txt - 7z ANSI-C Decoder description (this file) methods.txt - Compression method IDs for .7z LGPL.txt - GNU Lesser General Public License CPL.html - Common Public License lzma.exe - Compiled file->file LZMA encoder/decoder for Windows history.txt - history of the LZMA SDK Source code structure --------------------- C - C / CPP files Common - common files for C++ projects Windows - common files for Windows related code 7zip - files related to 7-Zip Project Common - common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm BinTree - Binary Tree Match Finder for LZ algorithm HashChain - Hash Chain Match Finder for LZ algorithm Patricia - Patricia Match Finder for LZ algorithm RangeCoder - Range Coder (special code of compression/decompression) LZMA - LZMA compression/decompression on C++ LZMA_Alone - file->file LZMA compression/decompression LZMA_C - ANSI-C compatible LZMA decompressor LzmaDecode.h - interface for LZMA decoding on ANSI-C LzmaDecode.c - LZMA decoding on ANSI-C (new fastest version) LzmaDecodeSize.c - LZMA decoding on ANSI-C (old size-optimized version) LzmaTest.c - test application that decodes LZMA encoded file LzmaStateDecode.h - interface for LZMA decoding (State version) LzmaStateDecode.c - LZMA decoding on ANSI-C (State version) LzmaStateTest.c - test application (State version) Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code Archive - files related to archiving 7z_C - 7z ANSI-C Decoder CS - C# files 7zip Common - some common files for 7-Zip Compress - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression LzmaAlone - file->file LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) Java - Java files SevenZip Compression - files related to compression/decompression LZ - files related to LZ (Lempel-Ziv) compression algorithm LZMA - LZMA compression/decompression RangeCoder - Range Coder (special code of compression/decompression) C/C++ source code of LZMA SDK is part of 7-Zip project. You can find ANSI-C LZMA decompressing code at folder C/7zip/Compress/LZMA_C 7-Zip doesn't use that ANSI-C LZMA code and that code was developed specially for this SDK. And files from LZMA_C do not need files from other directories of SDK for compiling. 7-Zip source code can be downloaded from 7-Zip's SourceForge page: http://sourceforge.net/projects/sevenzip/ LZMA Decompression features --------------------------- - Variable dictionary size (up to 256 MB) - Estimated compressing speed: about 500 KB/s on 1 GHz CPU - Estimated decompressing speed: - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC - Small memory requirements for decompressing (8-32 KB + DictionarySize) - Small code size for decompressing: 2-8 KB (depending from speed optimizations) LZMA decoder uses only integer operations and can be implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). Some critical operations that affect to speed of LZMA decompression: 1) 32*16 bit integer multiply 2) Misspredicted branches (penalty mostly depends from pipeline length) 3) 32-bit shift and arithmetic operations Speed of LZMA decompressing mostly depends from CPU speed. Memory speed has no big meaning. But if your CPU has small data cache, overall weight of memory speed will slightly increase. How To Use ---------- Using LZMA encoder/decoder executable -------------------------------------- Usage: LZMA inputFile outputFile [...] e: encode file d: decode file b: Benchmark. There are two tests: compressing and decompressing with LZMA method. Benchmark shows rating in MIPS (million instructions per second). Rating value is calculated from measured speed and it is normalized with AMD Athlon XP CPU results. Also Benchmark checks possible hardware errors (RAM errors in most cases). Benchmark uses these settings: (-a1, -d21, -fb32, -mfbt4). You can change only -d. Also you can change number of iterations. Example for 30 iterations: LZMA b 30 Default number of iterations is 10. -a{N}: set compression mode 0 = fast, 1 = normal, 2 = max default: 2 (max) d{N}: Sets Dictionary size - [0, 28], default: 23 (8MB) The maximum value for dictionary size is 256 MB = 2^28 bytes. Dictionary size is calculated as DictionarySize = 2^N bytes. For decompressing file compressed by LZMA method with dictionary size D = 2^N you need about D bytes of memory (RAM). -fb{N}: set number of fast bytes - [5, 273], default: 128 Usually big number gives a little bit better compression ratio and slower compression process. -lc{N}: set number of literal context bits - [0, 8], default: 3 Sometimes lc=4 gives gain for big files. -lp{N}: set number of literal pos bits - [0, 4], default: 0 lp switch is intended for periodical data when period is equal 2^N. For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's better to set lc0, if you change lp switch. -pb{N}: set number of pos bits - [0, 4], default: 2 pb switch is intended for periodical data when period is equal 2^N. -mf{MF_ID}: set Match Finder. Default: bt4. Compression ratio for all bt* and pat* almost the same. Algorithms from hc* group doesn't provide good compression ratio, but they often works pretty fast in combination with fast mode (-a0). Methods from bt* group require less memory than methods from pat* group. Usually bt4 works faster than any pat*, but for some types of files pat* can work faster. Memory requirements depend from dictionary size (parameter "d" in table below). MF_ID Memory Description bt2 d*9.5 + 1MB Binary Tree with 2 bytes hashing. bt3 d*9.5 + 65MB Binary Tree with 2-3(full) bytes hashing. bt4 d*9.5 + 6MB Binary Tree with 2-3-4 bytes hashing. bt4b d*9.5 + 34MB Binary Tree with 2-3-4(big) bytes hashing. pat2r d*26 + 1MB Patricia Tree with 2-bits nodes, removing. pat2 d*38 + 1MB Patricia Tree with 2-bits nodes. pat2h d*38 + 77MB Patricia Tree with 2-bits nodes, 2-3 bytes hashing. pat3h d*62 + 85MB Patricia Tree with 3-bits nodes, 2-3 bytes hashing. pat4h d*110 +101MB Patricia Tree with 4-bits nodes, 2-3 bytes hashing. hc3 d*5.5 + 1MB Hash Chain with 2-3 bytes hashing. hc4 d*5.5 + 6MB Hash Chain with 2-3-4 bytes hashing. -eos: write End Of Stream marker. By default LZMA doesn't write eos marker, since LZMA decoder knows uncompressed size stored in .lzma file header. -si: Read data from stdin (it will write End Of Stream marker). -so: Write data to stdout Examples: 1) LZMA e file.bin file.lzma -d16 -lc0 compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) and 0 literal context bits. -lc0 allows to reduce memory requirements for decompression. 2) LZMA e file.bin file.lzma -lc0 -lp2 compresses file.bin to file.lzma with settings suitable for 32-bit periodical data (for example, ARM or MIPS code). 3) LZMA d file.lzma file.bin decompresses file.lzma to file.bin. Compression ratio hints ----------------------- Recommendations --------------- To increase compression ratio for LZMA compressing it's desirable to have aligned data (if it's possible) and also it's desirable to locate data in such order, where code is grouped in one place and data is grouped in other place (it's better than such mixing: code, data, code, data, ...). Using Filters ------------- You can increase compression ratio for some data types, using special filters before compressing. For example, it's possible to increase compression ratio on 5-10% for code for those CPU ISAs: x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. You can find C/C++ source code of such filters in folder "7zip/Compress/Branch" You can check compression ratio gain of these filters with such 7-Zip commands (example for ARM code): No filter: 7z a a1.7z a.bin -m0=lzma With filter for little-endian ARM code: 7z a a2.7z a.bin -m0=bc_arm -m1=lzma With filter for big-endian ARM code (using additional Swap4 filter): 7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=lzma It works in such manner: Compressing = Filter_encoding + LZMA_encoding Decompressing = LZMA_decoding + Filter_decoding Compressing and decompressing speed of such filters is very high, so it will not increase decompressing time too much. Moreover, it reduces decompression time for LZMA_decoding, since compression ratio with filtering is higher. These filters convert CALL (calling procedure) instructions from relative offsets to absolute addresses, so such data becomes more compressible. Source code of these CALL filters is pretty simple (about 20 lines of C++), so you can convert it from C++ version yourself. For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. LZMA compressed file format --------------------------- Offset Size Description 0 1 Special LZMA properties for compressed data 1 4 Dictionary size (little endian) 5 8 Uncompressed size (little endian). -1 means unknown size 13 Compressed data ANSI-C LZMA Decoder ~~~~~~~~~~~~~~~~~~~ To compile ANSI-C LZMA Decoder you can use one of the following files sets: 1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c (fastest version) 2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c (old size-optimized version) 3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c (zlib-like interface) Memory requirements for LZMA decoding ------------------------------------- LZMA decoder doesn't allocate memory itself, so you must allocate memory and send it to LZMA. Stack usage of LZMA decoding function for local variables is not larger than 200 bytes. How To decompress data ---------------------- LZMA Decoder (ANSI-C version) now supports 5 interfaces: 1) Single-call Decompressing 2) Single-call Decompressing with input stream callback 3) Multi-call Decompressing with output buffer 4) Multi-call Decompressing with input callback and output buffer 5) Multi-call State Decompressing (zlib-like interface) Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions. Decompressing steps ------------------- 1) read LZMA properties (5 bytes): unsigned char properties[LZMA_PROPERTIES_SIZE]; 2) read uncompressed size (8 bytes, little-endian) 3) Decode properties: CLzmaDecoderState state; /* it's 24-140 bytes structure, if int is 32-bit */ if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) return PrintError(rs, "Incorrect stream properties"); 4) Allocate memory block for internal Structures: state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); if (state.Probs == 0) return PrintError(rs, kCantAllocateMessage); LZMA decoder uses array of CProb variables as internal structure. By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make it unsigned_int. It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case. 5) Main Decompressing You must use one of the following interfaces: 5.1 Single-call Decompressing ----------------------------- When to use: RAM->RAM decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: no defines Memory Requirements: - Input buffer: compressed size - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: int res = LzmaDecode(&state, inStream, compressedSize, &inProcessed, outStream, outSize, &outProcessed); 5.2 Single-call Decompressing with input stream callback -------------------------------------------------------- When to use: File->RAM or Flash->RAM decompressing. Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Output buffer: uncompressed size - LZMA Internal Structures (~16 KB for default settings) Interface: typedef struct _CBuffer { ILzmaInCallback InCallback; FILE *File; unsigned char Buffer[kInBufferSize]; } CBuffer; int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) { CBuffer *bo = (CBuffer *)object; *buffer = bo->Buffer; *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize); return LZMA_RESULT_OK; } CBuffer g_InBuffer; g_InBuffer.File = inFile; g_InBuffer.InCallback.Read = LzmaReadCompressed; int res = LzmaDecode(&state, &g_InBuffer.InCallback, outStream, outSize, &outProcessed); 5.3 Multi-call decompressing with output buffer ----------------------------------------------- When to use: RAM->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_OUT_READ Memory Requirements: - Input buffer: compressed size - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaTest.c for more details. 5.4 Multi-call decompressing with input callback and output buffer ------------------------------------------------------------------ When to use: File->File decompressing Compile files: LzmaDecode.h, LzmaDecode.c Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { LzmaDecode(&state, &bo.InCallback, g_OutBuffer, outAvail, &outProcessed); } while you need more bytes see LzmaTest.c for more details: 5.5 Multi-call State Decompressing (zlib-like interface) ------------------------------------------------------------------ When to use: file->file decompressing Compile files: LzmaStateDecode.h, LzmaStateDecode.c Compile defines: Memory Requirements: - Buffer for input stream: any size (for example, 16 KB) - Buffer for output stream: any size (for example, 16 KB) - LZMA Internal Structures (~16 KB for default settings) - LZMA dictionary (dictionary size is encoded in stream properties) Interface: state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); LzmaDecoderInit(&state); do { res = LzmaDecode(&state, inBuffer, inAvail, &inProcessed, g_OutBuffer, outAvail, &outProcessed, finishDecoding); inAvail -= inProcessed; inBuffer += inProcessed; } while you need more bytes see LzmaStateTest.c for more details: 6) Free all allocated blocks Note ---- LzmaDecodeSize.c is size-optimized version of LzmaDecode.c. But compiled code of LzmaDecodeSize.c can be larger than compiled code of LzmaDecode.c. So it's better to use LzmaDecode.c in most cases. EXIT codes ----------- LZMA decoder can return one of the following codes: #define LZMA_RESULT_OK 0 #define LZMA_RESULT_DATA_ERROR 1 If you use callback function for input data and you return some error code, LZMA Decoder also returns that code. LZMA Defines ------------ _LZMA_IN_CB - Use callback for input data _LZMA_OUT_READ - Use read function for output data _LZMA_LOC_OPT - Enable local speed optimizations inside code. _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version). _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version) and LzmaStateDecode.c _LZMA_PROB32 - It can increase speed on some 32-bit CPUs, but memory usage will be doubled in that case _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. _LZMA_SYSTEM_SIZE_T - Define it if you want to use system's size_t. You can use it to enable 64-bit sizes supporting C++ LZMA Encoder/Decoder ~~~~~~~~~~~~~~~~~~~~~~~~ C++ LZMA code use COM-like interfaces. So if you want to use it, you can study basics of COM/OLE. By default, LZMA Encoder contains all Match Finders. But for compressing it's enough to have just one of them. So for reducing size of compressing code you can define: #define COMPRESS_MF_BT #define COMPRESS_MF_BT4 and it will use only bt4 match finder. --- http://www.7-zip.org http://www.7-zip.org/support.html ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/mksquashfs.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 07/10/06 - jc - Added LZMA encoding parameter specification (_LZMA_PARAMS) * contact: jeremy@bitsum.com * * mksquashfs.c */ #define FALSE 0 #define TRUE 1 /* jc: Define to enable LZMA encoding parameters on command line */ #define _LZMA_PARAMS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "mksquashfs.h" #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do {\ if(!silent)\ printf("mksquashfs: "s, ## args);\ } while(0) #define ERROR(s, args...) do {\ fprintf(stderr, s, ## args);\ } while(0) #define EXIT_MKSQUASHFS() do {\ if(restore)\ restorefs();\ if(delete && destination_file && !block_device)\ unlink(destination_file);\ exit(1);\ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0) #ifdef _LZMA_PARAMS #include "./lzma/C/7zip/Compress/LZMA_Lib/lzmaext.h" /* jc: be lame and use some globals.. this app is single threaded*/ int g_fb=-1; int g_lc=1; int g_lp=2; int g_pb=2; #endif int delete = FALSE; long long total_compressed = 0, total_uncompressed = 0; int fd; /* filesystem flags for building */ int duplicate_checking = 1, noF = 0, no_fragments = 0, always_use_fragments = 0; int noI = 0, noD = 0, check_data = 0; int swap, silent = TRUE; long long global_uid = -1, global_gid = -1; /* superblock attributes */ int block_size = SQUASHFS_FILE_SIZE, block_log; unsigned short uid_count = 0, guid_count = 0; squashfs_uid uids[SQUASHFS_UIDS], guids[SQUASHFS_GUIDS]; int block_offset; int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, fifo_count = 0, sock_count = 0; /* write position within data section */ long long bytes = 0, total_bytes = 0; /* in memory directory table - possibly compressed */ char *directory_table = NULL; unsigned int directory_bytes = 0, directory_size = 0, total_directory_bytes = 0; /* cached directory table */ char *directory_data_cache = NULL; unsigned int directory_cache_bytes = 0, directory_cache_size = 0; /* in memory inode table - possibly compressed */ char *inode_table = NULL; unsigned int inode_bytes = 0, inode_size = 0, total_inode_bytes = 0; /* cached inode table */ char *data_cache = NULL; unsigned int cache_bytes = 0, cache_size = 0, inode_count = 0; /* in memory directory data */ #define I_COUNT_SIZE 128 #define DIR_ENTRIES 32 #define INODE_HASH_SIZE 65536 #define INODE_HASH_MASK (INODE_HASH_SIZE - 1) #define INODE_HASH(dev, ino) (ino & INODE_HASH_MASK) struct cached_dir_index { squashfs_dir_index index; char *name; }; struct directory { unsigned int start_block; unsigned int size; unsigned char *buff; unsigned char *p; unsigned int entry_count; unsigned char *entry_count_p; unsigned int i_count; unsigned int i_size; struct cached_dir_index *index; unsigned char *index_count_p; unsigned int inode_number; }; struct inode_info *inode_info[INODE_HASH_SIZE]; /* hash tables used to do fast duplicate searches in duplicate check */ struct file_info *dupl[65536], *frag_dups[65536]; int dup_files = 0; /* list of exclude dirs/files */ struct exclude_info { dev_t st_dev; ino_t st_ino; }; #define EXCLUDE_SIZE 8192 int exclude = 0; struct exclude_info *exclude_paths = NULL; int excluded(char *filename, struct stat *buf); /* fragment block data structures */ int fragments = 0; char fragment_data[SQUASHFS_FILE_MAX_SIZE]; int fragment_size = 0; struct fragment { unsigned int index; int offset; int size; }; #define FRAG_SIZE 32768 squashfs_fragment_entry *fragment_table = NULL; /* current inode number for directories and non directories */ unsigned int dir_inode_no = 1; unsigned int inode_no = 0; unsigned int root_inode_number = 0; /* list of source dirs/files */ int source = 0; char **source_path; /* list of root directory entries read from original filesystem */ int old_root_entries = 0; struct old_root_entry_info { char name[SQUASHFS_NAME_LEN + 1]; squashfs_inode inode; int type; int inode_number; }; struct old_root_entry_info *old_root_entry; /* in memory file info */ struct file_info { long long bytes; unsigned short checksum; long long start; unsigned int *block_list; struct file_info *next; struct fragment *fragment; unsigned short fragment_checksum; }; /* count of how many times SIGINT or SIGQUIT has been sent */ int interrupted = 0; /* restore orignal filesystem state if appending to existing filesystem is cancelled */ jmp_buf env; char *sdata_cache, *sdirectory_data_cache; long long sbytes, stotal_bytes; unsigned int sinode_bytes, scache_bytes, sdirectory_bytes, sdirectory_cache_bytes, suid_count, sguid_count, stotal_inode_bytes, stotal_directory_bytes, sinode_count, sfile_count, ssym_count, sdev_count, sdir_count, sfifo_count, ssock_count, sdup_files; int sfragments; int restore = 0; /* flag whether destination file is a block device */ int block_device = 0; /* flag indicating whether files are sorted using sort list(s) */ int sorted = 0; /* save destination file name for deleting on error */ char *destination_file = NULL; /* structure to used to pass in a pointer or an integer * to duplicate buffer read helper functions. */ struct duplicate_buffer_handle { char *ptr; long long start; }; void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type); extern int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source); extern long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table); int get_sorted_inode(squashfs_inode *inode, struct stat *buf); int read_sort_file(char *filename, int source, char *source_path[]); void sort_files_and_write(struct dir_info *dir); struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes); struct dir_info *dir_scan1(char *, int (_readdir)(char *, char *, struct dir_info *)); #define MKINODE(A) ((squashfs_inode)(((squashfs_inode) inode_bytes << 16) + (((char *)A) - data_cache))) void restorefs() { ERROR("Exiting - restoring original filesystem!\n\n"); bytes = sbytes; memcpy(data_cache, sdata_cache, cache_bytes = scache_bytes); memcpy(directory_data_cache, sdirectory_data_cache, directory_cache_bytes = sdirectory_cache_bytes); inode_bytes = sinode_bytes; directory_bytes = sdirectory_bytes; uid_count = suid_count; guid_count = sguid_count; total_bytes = stotal_bytes; total_inode_bytes = stotal_inode_bytes; total_directory_bytes = stotal_directory_bytes; inode_count = sinode_count; file_count = sfile_count; sym_count = ssym_count; dev_count = sdev_count; dir_count = sdir_count; fifo_count = sfifo_count; sock_count = ssock_count; dup_files = sdup_files; fragments = sfragments; fragment_size = 0; longjmp(env, 1); } void sighandler() { if(interrupted == 1) restorefs(); else { ERROR("Interrupting will restore original filesystem!\n"); ERROR("Interrupt again to quit\n"); interrupted ++; } } void sighandler2() { EXIT_MKSQUASHFS(); } unsigned int mangle(char *d, char *s, int size, int block_size, int uncompressed, int data_block) { unsigned long c_byte = block_size << 1; unsigned int res; #ifdef _LZMA_PARAMS if(!uncompressed && (res = compress2_lzma((unsigned char *) d, &c_byte, (unsigned char *) s, size, 9, g_fb, g_lc, g_lp, g_pb)) != Z_OK) { #else if(!uncompressed && (res = compress2((unsigned char *) d, &c_byte, (unsigned char *) s, size, 9)) != Z_OK) { #endif if(res == Z_MEM_ERROR) BAD_ERROR("zlib::compress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::compress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::compress failed, unknown error %d\n", res); return 0; } if(uncompressed || c_byte >= size) { memcpy(d, s, size); return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT); } return (unsigned int) c_byte; } squashfs_base_inode_header *get_inode(int req_size) { int data_space; unsigned short c_byte; while(cache_bytes >= SQUASHFS_METADATA_SIZE) { if((inode_size - inode_bytes) < ((SQUASHFS_METADATA_SIZE << 1)) + 2) { if((inode_table = (char *) realloc(inode_table, inode_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } c_byte = mangle(inode_table + inode_bytes + block_offset, data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(data_cache, data_cache + SQUASHFS_METADATA_SIZE, cache_bytes - SQUASHFS_METADATA_SIZE); cache_bytes -= SQUASHFS_METADATA_SIZE; } data_space = (cache_size - cache_bytes); if(data_space < req_size) { int realloc_size = cache_size == 0 ? ((req_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : req_size - data_space; if((data_cache = (char *) realloc(data_cache, cache_size + realloc_size)) == NULL) { goto failed; } cache_size += realloc_size; } cache_bytes += req_size; return (squashfs_base_inode_header *)(data_cache + (cache_bytes - req_size)); failed: BAD_ERROR("Out of memory in inode table reallocation!\n"); } void read_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(read(fd, buff, bytes) == -1) { perror("Read on destination failed"); EXIT_MKSQUASHFS(); } } void write_bytes(int fd, long long byte, int bytes, char *buff) { off_t off = byte; if(lseek(fd, off, SEEK_SET) == -1) { perror("Lseek on destination failed"); EXIT_MKSQUASHFS(); } if(write(fd, buff, bytes) == -1) { perror("Write on destination failed"); EXIT_MKSQUASHFS(); } } long long write_inodes() { unsigned short c_byte; int avail_bytes; char *datap = data_cache; long long start_bytes = bytes; while(cache_bytes) { if(inode_size - inode_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((inode_table = (char *) realloc(inode_table, inode_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in inode table reallocation!\n"); } inode_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : cache_bytes; c_byte = mangle(inode_table + inode_bytes + block_offset, datap, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Inode block @ %x, size %d\n", inode_bytes, c_byte); if(!swap) memcpy(inode_table + inode_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (inode_table + inode_bytes), 1); if(check_data) *((unsigned char *)(inode_table + inode_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; inode_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_inode_bytes += avail_bytes + block_offset; datap += avail_bytes; cache_bytes -= avail_bytes; } write_bytes(fd, bytes, inode_bytes, (char *) inode_table); bytes += inode_bytes; return start_bytes; } long long write_directories() { unsigned short c_byte; int avail_bytes; char *directoryp = directory_data_cache; long long start_bytes = bytes; while(directory_cache_bytes) { if(directory_size - directory_bytes < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + ((SQUASHFS_METADATA_SIZE << 1) + 2))) == NULL) { BAD_ERROR("Out of memory in directory table reallocation!\n"); } directory_size += (SQUASHFS_METADATA_SIZE << 1) + 2; } avail_bytes = directory_cache_bytes > SQUASHFS_METADATA_SIZE ? SQUASHFS_METADATA_SIZE : directory_cache_bytes; c_byte = mangle(directory_table + directory_bytes + block_offset, directoryp, avail_bytes, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += avail_bytes + block_offset; directoryp += avail_bytes; directory_cache_bytes -= avail_bytes; } write_bytes(fd, bytes, directory_bytes, (char *) directory_table); bytes += directory_bytes; return start_bytes; } unsigned int get_uid(squashfs_uid uid) { int i; for(i = 0; (i < uid_count) && uids[i] != uid; i++); if(i == uid_count) { if(uid_count == SQUASHFS_UIDS) { ERROR("Out of uids! - using uid 0 - probably not what's wanted!\n"); i = 0; } else uids[uid_count++] = uid; } return i; } unsigned int get_guid(squashfs_uid uid, squashfs_uid guid) { int i; if(uid == guid) return SQUASHFS_GUIDS; for(i = 0; (i < guid_count) && guids[i] != guid; i++); if(i == guid_count) { if(guid_count == SQUASHFS_GUIDS) { ERROR("Out of gids! - using gid 0 - probably not what's wanted!\n"); return SQUASHFS_GUIDS; } else guids[guid_count++] = guid; } return i; } int create_inode(squashfs_inode *i_no, struct dir_ent *dir_ent, int type, long long byte_size, long long start_block, unsigned int offset, unsigned int *block_list, struct fragment *fragment, struct directory *dir_in) { struct stat *buf = &dir_ent->inode->buf; squashfs_inode_header inode_header; squashfs_base_inode_header *inode, *base = &inode_header.base; char *filename = dir_ent->pathname; int nlink = dir_ent->inode->nlink; int inode_number = (type == SQUASHFS_LDIR_TYPE || type == SQUASHFS_DIR_TYPE) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; base->mode = SQUASHFS_MODE(buf->st_mode); base->uid = get_uid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid); base->inode_type = type; base->guid = get_guid((squashfs_uid) global_uid == -1 ? buf->st_uid : global_uid, (squashfs_uid) global_gid == -1 ? buf->st_gid : global_gid); base->mtime = buf->st_mtime; base->inode_number = inode_number; if(type == SQUASHFS_FILE_TYPE) { int i; squashfs_reg_inode_header *reg = &inode_header.reg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_reg_inode_header *) inode; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_REG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("File inode, file_size %d, start_block %llx, blocks %d, fragment %d, offset %d, size %d\n", (int) byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LREG_TYPE) { int i; squashfs_lreg_inode_header *reg = &inode_header.lreg, *inodep; inode = get_inode(sizeof(*reg) + offset * sizeof(unsigned int)); inodep = (squashfs_lreg_inode_header *) inode; reg->nlink = nlink; reg->file_size = byte_size; reg->start_block = start_block; reg->fragment = fragment->index; reg->offset = fragment->offset; if(!swap) { memcpy(inodep, reg, sizeof(*reg)); memcpy(inodep->block_list, block_list, offset * sizeof(unsigned int)); } else { SQUASHFS_SWAP_LREG_INODE_HEADER(reg, inodep); SQUASHFS_SWAP_INTS(block_list, inodep->block_list, offset); } TRACE("Long file inode, file_size %lld, start_block %llx, blocks %d, fragment %d, offset %d, size %d, nlink %d\n", byte_size, start_block, offset, fragment->index, fragment->offset, fragment->size, nlink); for(i = 0; i < offset; i++) TRACE("Block %d, size %d\n", i, block_list[i]); } else if(type == SQUASHFS_LDIR_TYPE) { int i; unsigned char *p; squashfs_ldir_inode_header *dir = &inode_header.ldir, *inodep; struct cached_dir_index *index = dir_in->index; unsigned int i_count = dir_in->i_count; unsigned int i_size = dir_in->i_size; if(byte_size >= 1 << 27) BAD_ERROR("directory greater than 2^27-1 bytes!\n"); inode = get_inode(sizeof(*dir) + i_size); inodep = (squashfs_ldir_inode_header *) inode; dir->inode_type = SQUASHFS_LDIR_TYPE; dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->i_count = i_count; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_LDIR_INODE_HEADER(dir, inode); p = (unsigned char *) inodep->index; for(i = 0; i < i_count; i++) { if(!swap) memcpy(p, &index[i].index, sizeof(squashfs_dir_index)); else SQUASHFS_SWAP_DIR_INDEX(&index[i].index, p); memcpy(((squashfs_dir_index *)p)->name, index[i].name, index[i].index.size + 1); p += sizeof(squashfs_dir_index) + index[i].index.size + 1; } TRACE("Long directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_DIR_TYPE) { squashfs_dir_inode_header *dir = &inode_header.dir; inode = get_inode(sizeof(*dir)); dir->nlink = dir_ent->dir->directory_count + 2; dir->file_size = byte_size; dir->offset = offset; dir->start_block = start_block; dir->parent_inode = dir_ent->our_dir ? dir_ent->our_dir->dir_ent->inode->inode_number : dir_inode_no + inode_no; if(!swap) memcpy(inode, dir, sizeof(*dir)); else SQUASHFS_SWAP_DIR_INODE_HEADER(dir, inode); TRACE("Directory inode, file_size %d, start_block %llx, offset %x, nlink %d\n", (int) byte_size, start_block, offset, dir_ent->dir->directory_count + 2); } else if(type == SQUASHFS_CHRDEV_TYPE || type == SQUASHFS_BLKDEV_TYPE) { squashfs_dev_inode_header *dev = &inode_header.dev; inode = get_inode(sizeof(*dev)); dev->nlink = nlink; dev->rdev = (unsigned short) ((major(buf->st_rdev) << 8) | (minor(buf->st_rdev) & 0xff)); if(!swap) memcpy(inode, dev, sizeof(*dev)); else SQUASHFS_SWAP_DEV_INODE_HEADER(dev, inode); TRACE("Device inode, rdev %x, nlink %d\n", dev->rdev, nlink); } else if(type == SQUASHFS_SYMLINK_TYPE) { squashfs_symlink_inode_header *symlink = &inode_header.symlink, *inodep; int byte; char buff[65536]; if((byte = readlink(filename, buff, 65536)) == -1) { perror("Error in reading symbolic link, skipping..."); return FALSE; } if(byte == 65536) { ERROR("Symlink is greater than 65536 bytes! skipping..."); return FALSE; } inode = get_inode(sizeof(*symlink) + byte); symlink->nlink = nlink; inodep = (squashfs_symlink_inode_header *) inode; symlink->symlink_size = byte; if(!swap) memcpy(inode, symlink, sizeof(*symlink)); else SQUASHFS_SWAP_SYMLINK_INODE_HEADER(symlink, inode); strncpy(inodep->symlink, buff, byte); TRACE("Symbolic link inode, symlink_size %d, nlink %d\n", byte, nlink); } else if(type == SQUASHFS_FIFO_TYPE || type == SQUASHFS_SOCKET_TYPE) { squashfs_ipc_inode_header *ipc = &inode_header.ipc; inode = get_inode(sizeof(*ipc)); ipc->nlink = nlink; if(!swap) memcpy(inode, ipc, sizeof(*ipc)); else SQUASHFS_SWAP_IPC_INODE_HEADER(ipc, inode); TRACE("ipc inode, type %s, nlink %d\n", type == SQUASHFS_FIFO_TYPE ? "fifo" : "socket", nlink); } else return FALSE; *i_no = MKINODE(inode); inode_count ++; TRACE("Created inode 0x%llx, type %d, uid %d, guid %d\n", *i_no, type, base->uid, base->guid); return TRUE; } void scan2_init_dir(struct directory *dir) { if((dir->buff = malloc(SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory allocating directory buffer\n"); } dir->size = SQUASHFS_METADATA_SIZE; dir->p = dir->index_count_p = dir->buff; dir->entry_count = 256; dir->entry_count_p = NULL; dir->index = NULL; dir->i_count = dir->i_size = 0; } void add_dir(squashfs_inode inode, unsigned int inode_number, char *name, int type, struct directory *dir) { unsigned char *buff; squashfs_dir_entry idir, *idirp; unsigned int start_block = inode >> 16; unsigned int offset = inode & 0xffff; unsigned int size; if((size = strlen(name)) > SQUASHFS_NAME_LEN) { size = SQUASHFS_NAME_LEN; ERROR("Filename is greater than %d characters, truncating! ...\n", SQUASHFS_NAME_LEN); } if(dir->p + sizeof(squashfs_dir_entry) + size + sizeof(squashfs_dir_header) >= dir->buff + dir->size) { if((buff = realloc(dir->buff, dir->size += SQUASHFS_METADATA_SIZE)) == NULL) { BAD_ERROR("Out of memory reallocating directory buffer\n"); } dir->p = (dir->p - dir->buff) + buff; if(dir->entry_count_p) dir->entry_count_p = (dir->entry_count_p - dir->buff + buff); dir->index_count_p = dir->index_count_p - dir->buff + buff; dir->buff = buff; } if(dir->entry_count == 256 || start_block != dir->start_block || ((dir->entry_count_p != NULL) && ((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE)) || ((long long) inode_number - dir->inode_number) > 32767 || ((long long) inode_number - dir->inode_number) < - 32768) { if(dir->entry_count_p) { squashfs_dir_header dir_header; if((dir->p + sizeof(squashfs_dir_entry) + size - dir->index_count_p) > SQUASHFS_METADATA_SIZE) { if(dir->i_count % I_COUNT_SIZE == 0) if((dir->index = realloc(dir->index, (dir->i_count + I_COUNT_SIZE) * sizeof(struct cached_dir_index))) == NULL) BAD_ERROR("Out of memory in directory index table reallocation!\n"); dir->index[dir->i_count].index.index = dir->p - dir->buff; dir->index[dir->i_count].index.size = size - 1; dir->index[dir->i_count++].name = name; dir->i_size += sizeof(squashfs_dir_index) + size; dir->index_count_p = dir->p; } dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); } dir->entry_count_p = dir->p; dir->start_block = start_block; dir->entry_count = 0; dir->inode_number = inode_number; dir->p += sizeof(squashfs_dir_header); } idirp = (squashfs_dir_entry *) dir->p; idir.offset = offset; idir.type = type; idir.size = size - 1; idir.inode_number = ((long long) inode_number - dir->inode_number); if(!swap) memcpy(idirp, &idir, sizeof(idir)); else SQUASHFS_SWAP_DIR_ENTRY((&idir), idirp); strncpy(idirp->name, name, size); dir->p += sizeof(squashfs_dir_entry) + size; dir->entry_count ++; } int write_dir(squashfs_inode *inode, struct dir_info *dir_info, struct directory *dir) { unsigned int dir_size = dir->p - dir->buff; int data_space = (directory_cache_size - directory_cache_bytes); unsigned int directory_block, directory_offset, i_count, index; unsigned short c_byte; if(data_space < dir_size) { int realloc_size = directory_cache_size == 0 ? ((dir_size + SQUASHFS_METADATA_SIZE) & ~(SQUASHFS_METADATA_SIZE - 1)) : dir_size - data_space; if((directory_data_cache = (char *) realloc(directory_data_cache, directory_cache_size + realloc_size)) == NULL) { goto failed; } directory_cache_size += realloc_size; } if(dir_size) { squashfs_dir_header dir_header; dir_header.count = dir->entry_count - 1; dir_header.start_block = dir->start_block; dir_header.inode_number = dir->inode_number; if(!swap) memcpy(dir->entry_count_p, &dir_header, sizeof(dir_header)); else SQUASHFS_SWAP_DIR_HEADER((&dir_header), (squashfs_dir_header *) dir->entry_count_p); memcpy(directory_data_cache + directory_cache_bytes, dir->buff, dir_size); } directory_offset = directory_cache_bytes; directory_block = directory_bytes; directory_cache_bytes += dir_size; i_count = 0; index = SQUASHFS_METADATA_SIZE - directory_offset; while(1) { while(i_count < dir->i_count && dir->index[i_count].index.index < index) dir->index[i_count++].index.start_block = directory_bytes; index += SQUASHFS_METADATA_SIZE; if(directory_cache_bytes < SQUASHFS_METADATA_SIZE) break; if((directory_size - directory_bytes) < ((SQUASHFS_METADATA_SIZE << 1) + 2)) { if((directory_table = (char *) realloc(directory_table, directory_size + (SQUASHFS_METADATA_SIZE << 1) + 2)) == NULL) { goto failed; } directory_size += SQUASHFS_METADATA_SIZE << 1; } c_byte = mangle(directory_table + directory_bytes + block_offset, directory_data_cache, SQUASHFS_METADATA_SIZE, SQUASHFS_METADATA_SIZE, noI, 0); TRACE("Directory block @ %x, size %d\n", directory_bytes, c_byte); if(!swap) memcpy(directory_table + directory_bytes, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), (directory_table + directory_bytes), 1); if(check_data) *((unsigned char *)(directory_table + directory_bytes + block_offset - 1)) = SQUASHFS_MARKER_BYTE; directory_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; total_directory_bytes += SQUASHFS_METADATA_SIZE + block_offset; memcpy(directory_data_cache, directory_data_cache + SQUASHFS_METADATA_SIZE, directory_cache_bytes - SQUASHFS_METADATA_SIZE); directory_cache_bytes -= SQUASHFS_METADATA_SIZE; } if(dir_info->dir_is_ldir) { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_LDIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, dir) == FALSE) return FALSE; } else { if(create_inode(inode, dir_info->dir_ent, SQUASHFS_DIR_TYPE, dir_size + 3, directory_block, directory_offset, NULL, NULL, NULL) == FALSE) return FALSE; } #ifdef SQUASHFS_TRACE if(!swap) { unsigned char *dirp; int count; TRACE("Directory contents of inode 0x%llx\n", *inode); dirp = dir->buff; while(dirp < dir->p) { char buffer[SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry idir, *idirp; squashfs_dir_header *dirh = (squashfs_dir_header *) dirp; count = dirh->count + 1; dirp += sizeof(squashfs_dir_header); TRACE("\tStart block 0x%x, count %d\n", dirh->start_block, count); while(count--) { idirp = (squashfs_dir_entry *) dirp; memcpy((char *) &idir, (char *) idirp, sizeof(idir)); strncpy(buffer, idirp->name, idir.size + 1); buffer[idir.size + 1] = '\0'; TRACE("\t\tname %s, inode offset 0x%x, type %d\n", buffer, idir.offset, idir.type); dirp += sizeof(squashfs_dir_entry) + idir.size + 1; } } } #endif dir_count ++; return TRUE; failed: BAD_ERROR("Out of memory in directory table reallocation!\n"); } char *get_fragment(char *buffer, struct fragment *fragment) { squashfs_fragment_entry *disk_fragment = &fragment_table[fragment->index]; int size = SQUASHFS_COMPRESSED_SIZE_BLOCK(disk_fragment->size); if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { int res; unsigned long bytes = block_size; char cbuffer[block_size]; read_bytes(fd, disk_fragment->start_block, size, cbuffer); if((res = uncompress((unsigned char *) buffer, &bytes, (const unsigned char *) cbuffer, size)) != Z_OK) { if(res == Z_MEM_ERROR) BAD_ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) BAD_ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else BAD_ERROR("zlib::uncompress failed, unknown error %d\n", res); } } else read_bytes(fd, disk_fragment->start_block, size, buffer); return buffer + fragment->offset; } void write_fragment() { int compressed_size; char buffer[block_size << 1]; if(fragment_size == 0) return; if(fragments % FRAG_SIZE == 0) if((fragment_table = (squashfs_fragment_entry *) realloc(fragment_table, (fragments + FRAG_SIZE) * sizeof(squashfs_fragment_entry))) == NULL) BAD_ERROR("Out of memory in fragment table\n"); fragment_table[fragments].size = mangle(buffer, fragment_data, fragment_size, block_size, noF, 1); fragment_table[fragments].start_block = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(fragment_table[fragments].size); write_bytes(fd, bytes, compressed_size, buffer); bytes += compressed_size; total_uncompressed += fragment_size; total_compressed += compressed_size; TRACE("Writing fragment %d, uncompressed size %d, compressed size %d\n",fragments, fragment_size, compressed_size); fragments ++; fragment_size = 0; } static struct fragment empty_fragment = {SQUASHFS_INVALID_FRAG, 0, 0}; struct fragment *get_and_fill_fragment(char *buff, int size) { struct fragment *ffrg; if(size == 0) return &empty_fragment; if(fragment_size + size > block_size) write_fragment(); if((ffrg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); ffrg->index = fragments; ffrg->offset = fragment_size; ffrg->size = size; memcpy(fragment_data + fragment_size, buff, size); fragment_size += size; return ffrg; } long long write_fragment_table() { long long start_bytes; unsigned int frag_bytes = SQUASHFS_FRAGMENT_BYTES(fragments), meta_blocks = SQUASHFS_FRAGMENT_INDEXES(fragments); char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2], buffer[frag_bytes]; squashfs_fragment_entry *p = (squashfs_fragment_entry *) buffer; unsigned short c_byte; int i, compressed_size; squashfs_fragment_index list[meta_blocks]; TRACE("write_fragment_table: fragments %d, frag_bytes %d, meta_blocks %d\n", fragments, frag_bytes, meta_blocks); for(i = 0; i < fragments; i++, p++) { TRACE("write_fragment_table: fragment %d, start_block %llx, size %d\n", i, fragment_table[i].start_block, fragment_table[i].size); if(!swap) memcpy(p, &fragment_table[i], sizeof(squashfs_fragment_entry)); else SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_table[i], p); } for(i = 0; i < meta_blocks; i++) { int avail_bytes = i == meta_blocks - 1 ? frag_bytes % SQUASHFS_METADATA_SIZE : SQUASHFS_METADATA_SIZE; c_byte = mangle(cbuffer + block_offset, buffer + i * SQUASHFS_METADATA_SIZE , avail_bytes, SQUASHFS_METADATA_SIZE, noF, 0); if(!swap) memcpy(cbuffer, &c_byte, sizeof(unsigned short)); else SQUASHFS_SWAP_SHORTS((&c_byte), cbuffer, 1); if(check_data) *((unsigned char *)(cbuffer + block_offset - 1)) = SQUASHFS_MARKER_BYTE; list[i] = bytes; compressed_size = SQUASHFS_COMPRESSED_SIZE(c_byte) + block_offset; write_bytes(fd, bytes, compressed_size, cbuffer); bytes += compressed_size; } if(!swap) write_bytes(fd, bytes, sizeof(list), (char *) list); else { squashfs_fragment_index slist[meta_blocks]; SQUASHFS_SWAP_FRAGMENT_INDEXES(list, slist, meta_blocks); write_bytes(fd, bytes, sizeof(list), (char *) slist); } start_bytes = bytes; bytes += sizeof(list); return start_bytes; } char *read_from_buffer(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { char *v = handle->ptr; handle->ptr += avail_bytes; return v; } char read_from_file_buffer[SQUASHFS_FILE_MAX_SIZE]; char *read_from_file(struct duplicate_buffer_handle *handle, unsigned int avail_bytes) { read_bytes(fd, handle->start, avail_bytes, read_from_file_buffer); handle->start += avail_bytes; return read_from_file_buffer; } /* * Compute 16 bit BSD checksum over the data */ unsigned short get_checksum(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *handle, long long l) { unsigned short chksum = 0; unsigned int bytes = 0; unsigned char *b; struct duplicate_buffer_handle position = *handle; while(l) { bytes = l > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : l; l -= bytes; b = (unsigned char *) get_next_file_block(&position, bytes); while(bytes--) { chksum = (chksum & 1) ? (chksum >> 1) | 0x8000 : chksum >> 1; chksum += *b++; } } return chksum; } int cached_frag = -1; void add_file(long long start, long long file_bytes, unsigned int *block_listp, int blocks, unsigned int fragment, int offset, int bytes) { struct fragment *frg; struct file_info *dupl_ptr; char *datap; struct duplicate_buffer_handle handle; unsigned int *block_list = block_listp; if(!duplicate_checking) return; if((frg = (struct fragment *) malloc(sizeof(struct fragment))) == NULL) BAD_ERROR("Out of memory in fragment block allocation!\n"); frg->index = fragment; frg->offset = offset; frg->size = bytes; if(fragment == cached_frag || fragment == SQUASHFS_INVALID_FRAG) datap = fragment_data + offset; else datap = get_fragment(fragment_data, frg); handle.start = start; if((dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &frg, datap, bytes)) != NULL) dupl_ptr->fragment = frg; else free(block_list); cached_frag = fragment; } char cached_fragment[SQUASHFS_FILE_SIZE]; int cached_frag1 = -1; struct file_info *duplicate(char *(get_next_file_block)(struct duplicate_buffer_handle *, unsigned int), struct duplicate_buffer_handle *file_start, long long bytes, unsigned int **block_list, long long *start, int blocks, struct fragment **fragment, char *frag_data, int frag_bytes) { unsigned short checksum = get_checksum(get_next_file_block, file_start, bytes); struct duplicate_buffer_handle handle = { frag_data, 0 }; unsigned short fragment_checksum = get_checksum(read_from_buffer, &handle, frag_bytes); struct file_info *dupl_ptr = bytes ? dupl[checksum] : frag_dups[fragment_checksum]; for(; dupl_ptr; dupl_ptr = dupl_ptr->next) if(bytes == dupl_ptr->bytes && frag_bytes == dupl_ptr->fragment->size && fragment_checksum == dupl_ptr->fragment_checksum) { char buffer1[SQUASHFS_FILE_MAX_SIZE]; long long dup_bytes = dupl_ptr->bytes; long long dup_start = dupl_ptr->start; struct duplicate_buffer_handle position = *file_start; char *buffer; while(dup_bytes) { int avail_bytes = dup_bytes > SQUASHFS_FILE_MAX_SIZE ? SQUASHFS_FILE_MAX_SIZE : dup_bytes; buffer = get_next_file_block(&position, avail_bytes); read_bytes(fd, dup_start, avail_bytes, buffer1); if(memcmp(buffer, buffer1, avail_bytes) != 0) break; dup_bytes -= avail_bytes; dup_start += avail_bytes; } if(dup_bytes == 0) { char *fragment_buffer1; if(dupl_ptr->fragment->index == fragments || dupl_ptr->fragment->index == SQUASHFS_INVALID_FRAG) fragment_buffer1 = fragment_data + dupl_ptr->fragment->offset; else if(dupl_ptr->fragment->index == cached_frag1) fragment_buffer1 = cached_fragment + dupl_ptr->fragment->offset; else { fragment_buffer1 = get_fragment(cached_fragment, dupl_ptr->fragment); cached_frag1 = dupl_ptr->fragment->index; } if(frag_bytes == 0 || memcmp(frag_data, fragment_buffer1, frag_bytes) == 0) { TRACE("Found duplicate file, start 0x%llx, size %lld, checksum 0x%x, fragment %d, size %d, offset %d, checksum 0x%x\n", dupl_ptr->start, dupl_ptr->bytes, dupl_ptr->checksum, dupl_ptr->fragment->index, frag_bytes, dupl_ptr->fragment->offset, fragment_checksum); *block_list = dupl_ptr->block_list; *start = dupl_ptr->start; *fragment = dupl_ptr->fragment; return 0; } } } if((dupl_ptr = (struct file_info *) malloc(sizeof(struct file_info))) == NULL) { BAD_ERROR("Out of memory in dup_files allocation!\n"); } dupl_ptr->bytes = bytes; dupl_ptr->checksum = checksum; dupl_ptr->start = *start; dupl_ptr->fragment_checksum = fragment_checksum; dupl_ptr->block_list = *block_list; dup_files ++; if(bytes) { dupl_ptr->next = dupl[checksum]; dupl[checksum] = dupl_ptr; } else { dupl_ptr->next = frag_dups[fragment_checksum]; frag_dups[fragment_checksum] = dupl_ptr; } return dupl_ptr; } #define MINALLOCBYTES (1024 * 1024) int write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *duplicate_file) { int block = 0, i, file, whole_file = 1, status; unsigned int c_byte, frag_bytes; long long bbytes, file_bytes = 0, start; char *c_buffer = NULL, *filename = dir_ent->pathname; struct fragment *fragment; struct file_info *dupl_ptr = NULL; struct duplicate_buffer_handle handle; long long read_size = (size > SQUASHFS_MAX_FILE_SIZE) ? SQUASHFS_MAX_FILE_SIZE : size; int blocks = (read_size + block_size - 1) >> block_log, allocated_blocks = blocks; unsigned int *block_list, *block_listp; char *buff = (char*)malloc(SQUASHFS_FILE_MAX_SIZE); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) BAD_ERROR("Out of memory allocating block_list\n"); block_listp = block_list; if(!no_fragments && (read_size < block_size || always_use_fragments)) { allocated_blocks = blocks = read_size >> block_log; frag_bytes = read_size % block_size; } else frag_bytes = 0; if(size > read_size) ERROR("file %s truncated to %lld bytes\n", filename, SQUASHFS_MAX_FILE_SIZE); total_bytes += read_size; if((file = open(filename, O_RDONLY)) == -1) goto read_err; do { long long bytes = (((long long) allocated_blocks) + 1) << block_log; if(bytes != ((size_t) bytes) || (c_buffer = (char *) malloc(bytes)) == NULL) { TRACE("Out of memory allocating write_file buffer, allocated_blocks %ld, blocks %d\n", allocated_blocks, blocks); whole_file = 0; if(bytes < MINALLOCBYTES) BAD_ERROR("Out of memory allocating write_file buffer, could not allocate %ld blocks (%d Kbytes)\n", allocated_blocks, allocated_blocks << (block_log - 10)); allocated_blocks >>= 1; } } while(!c_buffer); for(start = bytes; block < blocks; file_bytes += bbytes) { for(i = 0, bbytes = 0; (i < allocated_blocks) && (block < blocks); i++) { int available_bytes = read_size - (block * block_size) > block_size ? block_size : read_size - (block * block_size); if(read(file, buff, available_bytes) == -1) goto read_err; c_byte = mangle(c_buffer + bbytes, buff, available_bytes, block_size, noD, 1); block_list[block ++] = c_byte; bbytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); } if(!whole_file) { write_bytes(fd, bytes, bbytes, c_buffer); bytes += bbytes; } } if(frag_bytes != 0) { if(read(file, buff, frag_bytes) == -1) goto read_err; } close(file); if(whole_file) { handle.ptr = c_buffer; if(duplicate_checking && (dupl_ptr = duplicate(read_from_buffer, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { *duplicate_file = TRUE; goto wr_inode; } write_bytes(fd, bytes, file_bytes, c_buffer); bytes += file_bytes; } else { handle.start = start; if(duplicate_checking && (dupl_ptr = duplicate(read_from_file, &handle, file_bytes, &block_listp, &start, blocks, &fragment, buff, frag_bytes)) == NULL) { bytes = start; if(!block_device) ftruncate(fd, bytes); *duplicate_file = TRUE; goto wr_inode; } } fragment = get_and_fill_fragment(buff, frag_bytes); if(duplicate_checking) dupl_ptr->fragment = fragment; *duplicate_file = FALSE; wr_inode: free(c_buffer); file_count ++; if(dir_ent->inode->nlink == 1 && read_size < ((long long) (1<<30) - 1)) status = create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, start, blocks, block_listp, fragment, NULL); else status = create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, start, blocks, block_listp, fragment, NULL); if(duplicate_checking == FALSE || *duplicate_file == TRUE) free(block_list); return status; read_err: perror("Error in reading file, skipping..."); free(buff); free(c_buffer); free(block_list); return FALSE; } char b_buffer[8192]; char *name; char *basename_r(); char *getbase(char *pathname) { char *result; if(*pathname != '/') { result = getenv("PWD"); strcat(strcat(strcpy(b_buffer, result), "/"), pathname); } else strcpy(b_buffer, pathname); name = b_buffer; if(((result = basename_r()) == NULL) || (strcmp(result, "..") == 0)) return NULL; else return result; } char *basename_r() { char *s; char *p; int n = 1; for(;;) { s = name; if(*name == '\0') return NULL; if(*name != '/') { while(*name != '\0' && *name != '/') name++; n = name - s; } while(*name == '/') name++; if(strncmp(s, ".", n) == 0) continue; if((*name == '\0') || (strncmp(s, "..", n) == 0) || ((p = basename_r()) == NULL)) { s[n] = '\0'; return s; } if(strcmp(p, "..") == 0) continue; return p; } } struct inode_info *lookup_inode(struct stat *buf) { int inode_hash = INODE_HASH(buf->st_dev, buf->st_ino); struct inode_info *inode = inode_info[inode_hash]; while(inode != NULL) { if(memcmp(buf, &inode->buf, sizeof(struct stat)) == 0) { inode->nlink ++; return inode; } inode = inode->next; } if((inode = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in inode hash table entry allocation\n"); memcpy(&inode->buf, buf, sizeof(struct stat)); inode->inode = SQUASHFS_INVALID_BLK; inode->nlink = 1; if((buf->st_mode & S_IFMT) == S_IFDIR) inode->inode_number = dir_inode_no ++; else inode->inode_number = inode_no ++; inode->next = inode_info[inode_hash]; inode_info[inode_hash] = inode; return inode; } inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, struct inode_info *inode_info, void *data, struct dir_info *dir) { if((dir->count % DIR_ENTRIES) == 0) if((dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * sizeof(struct dir_ent *))) == NULL) BAD_ERROR("Out of memory in add_dir_entry\n"); if((dir->list[dir->count] = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in linux_opendir\n"); if(sub_dir) sub_dir->dir_ent = dir->list[dir->count]; dir->list[dir->count]->name = strdup(name); dir->list[dir->count]->pathname = pathname != NULL ? strdup(pathname) : NULL; dir->list[dir->count]->inode = inode_info; dir->list[dir->count]->dir = sub_dir; dir->list[dir->count]->our_dir = dir; dir->list[dir->count++]->data = data; dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); } int compare_name(const void *ent1_ptr, const void *ent2_ptr) { struct dir_ent *ent1 = *((struct dir_ent **) ent1_ptr); struct dir_ent *ent2 = *((struct dir_ent **) ent2_ptr); return strcmp(ent1->name, ent2->name); } void sort_directory(struct dir_info *dir) { qsort(dir->list, dir->count, sizeof(struct dir_ent *), compare_name); if((dir->count < 257 && dir->byte_count < SQUASHFS_METADATA_SIZE)) dir->dir_is_ldir = FALSE; } struct dir_info *scan1_opendir(char *pathname) { DIR *linuxdir; struct dirent *d_name; struct dir_info *dir; if((dir = malloc(sizeof(struct dir_info))) == NULL) return NULL; if(pathname[0] != '\0' && (dir->linuxdir = opendir(pathname)) == NULL) { free(dir); return NULL; } dir->pathname = strdup(pathname); dir->count = dir->directory_count = dir->current_count = dir->byte_count = 0; dir->dir_is_ldir = TRUE; dir->list = NULL; return dir; } int scan1_encomp_readdir(char *pathname, char *dir_name, struct dir_info *dir) { int i, n, pass; char *basename; static int index = 0; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } while(index < source) { if((basename = getbase(source_path[index])) == NULL) { ERROR("Bad source directory %s - skipping ...\n", source_path[index]); index ++; continue; } strcpy(dir_name, basename); pass = 1; for(;;) { for(n = 0; n < dir->count && strcmp(dir->list[n]->name, dir_name) != 0; n++); if(n == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", basename, pass++); ERROR("%s\n", dir_name); } strcpy(pathname, source_path[index ++]); return 1; } return 0; } int scan1_single_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; int i, pass; if(dir->count < old_root_entries) for(i = 0; i < old_root_entries; i++) { if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) dir->directory_count ++; add_dir_entry(old_root_entry[i].name, "", NULL, NULL, &old_root_entry[i], dir); } if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); pass = 1; for(;;) { for(i = 0; i < dir->count && strcmp(dir->list[i]->name, dir_name) != 0; i++); if(i == dir->count) break; ERROR("Source directory entry %s already used! - trying ", dir_name); sprintf(dir_name, "%s_%d", d_name->d_name, pass++); ERROR("%s\n", dir_name); } strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } int scan1_readdir(char *pathname, char *dir_name, struct dir_info *dir) { struct dirent *d_name; if((d_name = readdir(dir->linuxdir)) != NULL) { strcpy(dir_name, d_name->d_name); strcat(strcat(strcpy(pathname, dir->pathname), "/"), d_name->d_name); return 1; } return 0; } struct dir_ent *scan2_readdir(struct directory *dir, struct dir_info *dir_info) { int current_count; while((current_count = dir_info->current_count++) < dir_info->count) if(dir_info->list[current_count]->data) add_dir(dir_info->list[current_count]->data->inode, dir_info->list[current_count]->data->inode_number, dir_info->list[current_count]->name, dir_info->list[current_count]->data->type, dir); else return dir_info->list[current_count]; return FALSE; } void scan1_freedir(struct dir_info *dir) { if(dir->pathname[0] != '\0') closedir(dir->linuxdir); } void scan2_freedir(struct directory *dir) { if(dir->index) free(dir->index); free(dir->buff); } void dir_scan(squashfs_inode *inode, char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir_info = dir_scan1(pathname, _readdir); struct dir_ent *dir_ent; struct inode_info *inode_info; if(dir_info == NULL) return; if((dir_ent = malloc(sizeof(struct dir_ent))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); if((inode_info = malloc(sizeof(struct inode_info))) == NULL) BAD_ERROR("Out of memory in dir_scan\n"); dir_ent->name = dir_ent->pathname = strdup(pathname); dir_ent->dir = dir_info; dir_ent->inode = inode_info; dir_ent->our_dir = NULL; dir_ent->data = NULL; inode_info->nlink = 1; inode_info->inode_number = root_inode_number ? root_inode_number : dir_inode_no++; dir_info->dir_ent = dir_ent; if(pathname[0] == '\0') { /* dummy top level directory, if multiple sources specified on command line */ inode_info->buf.st_mode = S_IRWXU | S_IRWXG | S_IRWXO; inode_info->buf.st_uid = getuid(); inode_info->buf.st_gid = getgid(); inode_info->buf.st_mtime = time(NULL); } else if(lstat(pathname, &inode_info->buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", pathname); perror(buffer); return; } if(sorted) sort_files_and_write(dir_info); dir_scan2(inode, dir_info); } struct dir_info *dir_scan1(char *pathname, int (_readdir)(char *, char *, struct dir_info *)) { struct dir_info *dir, *sub_dir; struct stat buf; char filename[8192], dir_name[8192]; if((dir = scan1_opendir(pathname)) == NULL) { ERROR("Could not open %s, skipping...\n", pathname); goto error; } while(_readdir(filename, dir_name, dir) != FALSE) { if(strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0) continue; if(lstat(filename, &buf) == -1) { char buffer[8192]; sprintf(buffer, "Cannot stat dir/file %s, ignoring", filename); perror(buffer); continue; } if(excluded(filename, &buf)) continue; if((buf.st_mode & S_IFMT) == S_IFDIR) { if((sub_dir = dir_scan1(filename, scan1_readdir)) == NULL) continue; dir->directory_count ++; } else sub_dir = NULL; add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), NULL, dir); } scan1_freedir(dir); sort_directory(dir); error: return dir; } int dir_scan2(squashfs_inode *inode, struct dir_info *dir_info) { int squashfs_type; int result = FALSE; int duplicate_file; char *pathname = dir_info->pathname; struct directory dir; struct dir_ent *dir_ent; scan2_init_dir(&dir); while((dir_ent = scan2_readdir(&dir, dir_info)) != NULL) { struct inode_info *inode_info = dir_ent->inode; struct stat *buf = &inode_info->buf; char *filename = dir_ent->pathname; char *dir_name = dir_ent->name; unsigned int inode_number = ((buf->st_mode & S_IFMT) == S_IFDIR) ? dir_ent->inode->inode_number : dir_ent->inode->inode_number + dir_inode_no; if(dir_ent->inode->inode == SQUASHFS_INVALID_BLK) { switch(buf->st_mode & S_IFMT) { case S_IFREG: squashfs_type = SQUASHFS_FILE_TYPE; result = write_file(inode, dir_ent, buf->st_size, &duplicate_file); INFO("file %s, uncompressed size %lld bytes %s\n", filename, buf->st_size, duplicate_file ? "DUPLICATE" : ""); break; case S_IFDIR: squashfs_type = SQUASHFS_DIR_TYPE; result = dir_scan2(inode, dir_ent->dir); break; case S_IFLNK: squashfs_type = SQUASHFS_SYMLINK_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("symbolic link %s inode 0x%llx\n", dir_name, *inode); sym_count ++; break; case S_IFCHR: squashfs_type = SQUASHFS_CHRDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("character device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFBLK: squashfs_type = SQUASHFS_BLKDEV_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("block device %s inode 0x%llx\n", dir_name, *inode); dev_count ++; break; case S_IFIFO: squashfs_type = SQUASHFS_FIFO_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("fifo %s inode 0x%llx\n", dir_name, *inode); fifo_count ++; break; case S_IFSOCK: squashfs_type = SQUASHFS_SOCKET_TYPE; result = create_inode(inode, dir_ent, squashfs_type, 0, 0, 0, NULL, NULL, NULL); INFO("unix domain socket %s inode 0x%llx\n", dir_name, *inode); sock_count ++; break; default: ERROR("%s unrecognised file type, mode is %x\n", filename, buf->st_mode); result = FALSE; } if(result) dir_ent->inode->inode = *inode; dir_ent->inode->type = squashfs_type; } else { *inode = dir_ent->inode->inode; squashfs_type = dir_ent->inode->type; switch(squashfs_type) { case SQUASHFS_FILE_TYPE: if(!sorted) INFO("file %s, uncompressed size %lld bytes LINK\n", filename, buf->st_size); break; case SQUASHFS_SYMLINK_TYPE: INFO("symbolic link %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_CHRDEV_TYPE: INFO("character device %s inode 0x%llx LINK\n", dir_name, *inode); break; caseSQUASHFS_BLKDEV_TYPE: INFO("block device %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_FIFO_TYPE: INFO("fifo %s inode 0x%llx LINK\n", dir_name, *inode); break; case SQUASHFS_SOCKET_TYPE: INFO("unix domain socket %s inode 0x%llx LINK\n", dir_name, *inode); break; } result = TRUE; } if(result) add_dir(*inode, inode_number, dir_name, squashfs_type, &dir); } result = write_dir(inode, dir_info, &dir); INFO("directory %s inode 0x%llx\n", pathname, *inode); scan2_freedir(&dir); return result; } unsigned int slog(unsigned int block) { int i; for(i = 12; i <= 20; i++) if(block == (1 << i)) return i; return 0; } int excluded(char *filename, struct stat *buf) { int i; for(i = 0; i < exclude; i++) if((exclude_paths[i].st_dev == buf->st_dev) && (exclude_paths[i].st_ino == buf->st_ino)) return TRUE; return FALSE; } #define ADD_ENTRY(buf) \ if(exclude % EXCLUDE_SIZE == 0) {\ if((exclude_paths = (struct exclude_info *) realloc(exclude_paths, (exclude + EXCLUDE_SIZE) * sizeof(struct exclude_info))) == NULL)\ BAD_ERROR("Out of memory in exclude dir/file table\n");\ }\ exclude_paths[exclude].st_dev = buf.st_dev;\ exclude_paths[exclude++].st_ino = buf.st_ino; int add_exclude(char *path) { int i; char buffer[4096], filename[4096]; struct stat buf; if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { if(lstat(path, &buf) == -1) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", path); perror(buffer); return TRUE; } ADD_ENTRY(buf); return TRUE; } for(i = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) { sprintf(buffer, "Cannot stat exclude dir/file %s, ignoring", filename); perror(buffer); } continue; } ADD_ENTRY(buf); } return TRUE; } void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, int type) { if((old_root_entry = (struct old_root_entry_info *) realloc(old_root_entry, sizeof(struct old_root_entry_info) * (old_root_entries + 1))) == NULL) BAD_ERROR("Out of memory in old root directory entries reallocation\n"); strcpy(old_root_entry[old_root_entries].name, name); old_root_entry[old_root_entries].inode = inode; old_root_entry[old_root_entries].inode_number = inode_number; old_root_entry[old_root_entries++].type = type; } #define VERSION() \ printf("mksquashfs version 3.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { struct stat buf, source_buf; int i; squashfs_super_block sBlk; char *b, *root_name = NULL; int be, nopad = FALSE, keep_as_directory = FALSE, orig_be; squashfs_inode inode; #if __BYTE_ORDER == __BIG_ENDIAN be = TRUE; #else be = FALSE; #endif block_log = slog(block_size); if(argc > 1 && strcmp(argv[1], "-version") == 0) { VERSION(); exit(0); } for(i = 1; i < argc && argv[i][0] != '-'; i++); if(i < 3) goto printOptions; source_path = argv + 1; source = i - 2; for(; i < argc; i++) { if(strcmp(argv[i], "-b") == 0) { if((++i == argc) || (block_size = strtol(argv[i], &b, 10), *b !='\0')) { ERROR("%s: -b missing or invalid block size\n", argv[0]); exit(1); } if((block_log = slog(block_size)) == 0) { ERROR("%s: -b block size not power of two or not between 4096 and 64K\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-ef") == 0) { if(++i == argc) { ERROR("%s: -ef missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-no-duplicates") == 0) duplicate_checking = FALSE; #ifdef _LZMA_PARAMS else if(strcmp(argv[i], "-lc") == 0) { if(++i == argc) { ERROR("%s: -lc missing or invalid value\n", argv[0]); exit(1); } g_lc = strtol(argv[i], NULL, 10); if(g_lc<0 || g_lc>8) { ERROR("lc is out of bounds (0-8).\n"); exit(1); } } else if(strcmp(argv[i], "-lp") == 0) { if(++i == argc) { ERROR("%s: -lp missing or invalid value\n", argv[0]); exit(1); } g_lp = strtol(argv[i], NULL, 10); if(g_lp<0 || g_lp>4) { ERROR("lp is out of bounds (0-4).\n"); exit(1); } } else if(strcmp(argv[i], "-pb") == 0) { if(++i == argc) { ERROR("%s: -pb missing or invalid value\n", argv[0]); exit(1); } g_pb = strtol(argv[i], NULL, 10); if(g_pb<0 || g_pb>4) { ERROR("pb is out of bounds (0-4).\n"); exit(1); } } else if(strcmp(argv[i], "-fb") == 0) { if(++i == argc) { ERROR("%s: -fb missing or invalid value\n", argv[0]); exit(1); } g_fb = strtol(argv[i], NULL, 10); if(g_fb<5 || g_fb>273) { ERROR("fb is out of bounds (5-272).\n"); exit(1); } } #endif else if(strcmp(argv[i], "-no-fragments") == 0) no_fragments = TRUE; else if(strcmp(argv[i], "-always-use-fragments") == 0) always_use_fragments = TRUE; else if(strcmp(argv[i], "-sort") == 0) { if(++i == argc) { ERROR("%s: -sort missing filename\n", argv[0]); exit(1); } } else if(strcmp(argv[i], "-all-root") == 0 || strcmp(argv[i], "-root-owned") == 0) global_uid = global_gid = 0; else if(strcmp(argv[i], "-force-uid") == 0) { if(++i == argc) { ERROR("%s: -force-uid missing uid or user\n", argv[0]); exit(1); } if((global_uid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_uid < 0 || global_uid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-uid uid out of range\n", argv[0]); exit(1); } } else { struct passwd *uid = getpwnam(argv[i]); if(uid) global_uid = uid->pw_uid; else { ERROR("%s: -force-uid invalid uid or unknown user\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-force-gid") == 0) { if(++i == argc) { ERROR("%s: -force-gid missing gid or group\n", argv[0]); exit(1); } if((global_gid = strtoll(argv[i], &b, 10)), *b =='\0') { if(global_gid < 0 || global_gid > (((long long) 1 << 32) - 1)) { ERROR("%s: -force-gid gid out of range\n", argv[0]); exit(1); } } else { struct group *gid = getgrnam(argv[i]); if(gid) global_gid = gid->gr_gid; else { ERROR("%s: -force-gid invalid gid or unknown group\n", argv[0]); exit(1); } } } else if(strcmp(argv[i], "-noI") == 0 || strcmp(argv[i], "-noInodeCompression") == 0) noI = TRUE; else if(strcmp(argv[i], "-noD") == 0 || strcmp(argv[i], "-noDataCompression") == 0) noD = TRUE; else if(strcmp(argv[i], "-noF") == 0 || strcmp(argv[i], "-noFragmentCompression") == 0) noF = TRUE; else if(strcmp(argv[i], "-nopad") == 0) nopad = TRUE; else if(strcmp(argv[i], "-check_data") == 0) check_data = TRUE; else if(strcmp(argv[i], "-info") == 0) silent = 0; else if(strcmp(argv[i], "-be") == 0) be = TRUE; else if(strcmp(argv[i], "-le") == 0) be = FALSE; else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-noappend") == 0) delete = TRUE; else if(strcmp(argv[i], "-keep-as-directory") == 0) keep_as_directory = TRUE; else if(strcmp(argv[i], "-root-becomes") == 0) { if(++i == argc) { ERROR("%s: -root-becomes: missing name\n", argv[0]); exit(1); } root_name = argv[i]; } else if(strcmp(argv[i], "-version") == 0) { VERSION(); } else { ERROR("%s: invalid option\n\n", argv[0]); printOptions: ERROR("SYNTAX:%s source1 source2 ... dest [options] [-e list of exclude\ndirs/files]\n", argv[0]); ERROR("\nOptions are\n"); ERROR("-version\t\tprint version, licence and copyright message\n"); ERROR("-info\t\t\tprint files written to filesystem\n"); ERROR("-b \t\tset data block to . Default %d bytes\n", SQUASHFS_FILE_SIZE); ERROR("-noI\t\t\tdo not compress inode table\n"); ERROR("-noD\t\t\tdo not compress data blocks\n"); ERROR("-noF\t\t\tdo not compress fragment blocks\n"); ERROR("-no-fragments\t\tdo not use fragments\n"); ERROR("-always-use-fragments\tuse fragment blocks for files larger than block size\n"); ERROR("-no-duplicates\t\tdo not perform duplicate checking\n"); ERROR("-noappend\t\tdo not append to existing filesystem\n"); ERROR("-keep-as-directory\tif one source directory is specified, create a root\n"); ERROR("\t\t\tdirectory containing that directory, rather than the\n"); ERROR("\t\t\tcontents of the directory\n"); ERROR("-root-becomes \twhen appending source files/directories, make the\n"); ERROR("\t\t\toriginal root become a subdirectory in the new root\n"); ERROR("\t\t\tcalled , rather than adding the new source items\n"); ERROR("\t\t\tto the original root\n"); ERROR("-all-root\t\tmake all files owned by root\n"); ERROR("-force-uid uid\t\tset all file uids to uid\n"); ERROR("-force-gid gid\t\tset all file gids to gid\n"); ERROR("-le\t\t\tcreate a little endian filesystem\n"); ERROR("-be\t\t\tcreate a big endian filesystem\n"); ERROR("-nopad\t\t\tdo not pad filesystem to a multiple of 4K\n"); ERROR("-check_data\t\tadd checkdata for greater filesystem checks\n"); ERROR("-root-owned\t\talternative name for -all-root\n"); ERROR("-noInodeCompression\talternative name for -noI\n"); ERROR("-noDataCompression\talternative name for -noD\n"); ERROR("-noFragmentCompression\talternative name for -noF\n"); ERROR("-sort \tsort files according to priorities in . One\n"); ERROR("\t\t\tfile or dir with priority per line. Priority -32768 to\n"); ERROR("\t\t\t32767, default priority 0\n"); ERROR("-ef \tlist of exclude dirs/files. One per line\n"); #ifdef _LZMA_PARAMS ERROR("-fb x\t\t\tset lzma fast bytes to x (5-272)\n"); ERROR("-lc x\t\t\tset lzma literal context bits to x (0-8)\n"); ERROR("-lp x\t\t\tset lzma literal pos bits to x (0-4)\n"); ERROR("-pb x\t\t\tset lzma pos bits to x (0-4)\n"); #endif exit(1); } } for(i = 0; i < source; i++) if(stat(source_path[i], &source_buf) == -1) { fprintf(stderr, "Cannot stat source directory \"%s\" because %s\n", source_path[i], strerror(errno)); EXIT_MKSQUASHFS(); } destination_file = argv[source + 1]; if(stat(argv[source + 1], &buf) == -1) { if(errno == ENOENT) { /* Does not exist */ if((fd = open(argv[source + 1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) { perror("Could not create destination file"); exit(1); } delete = TRUE; } else { perror("Could not stat destination file"); exit(1); } } else { if(S_ISBLK(buf.st_mode)) { if((fd = open(argv[source + 1], O_RDWR)) == -1) { perror("Could not open block device as destination"); exit(1); } block_device = 1; } else if(S_ISREG(buf.st_mode)) { if((fd = open(argv[source + 1], (delete ? O_TRUNC : 0) | O_RDWR)) == -1) { perror("Could not open regular file for writing as destination"); exit(1); } } else { ERROR("Destination not block device or regular file\n"); exit(1); } } if(!delete) { if(read_super(fd, &sBlk, &orig_be, argv[source + 1]) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } } else { signal(SIGTERM, sighandler2); signal(SIGINT, sighandler2); } /* process the exclude files - must be done afer destination file has been possibly created */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-ef") == 0) { FILE *fd; char filename[16385]; if((fd = fopen(argv[++i], "r")) == NULL) { perror("Could not open exclude file..."); EXIT_MKSQUASHFS(); } while(fscanf(fd, "%16384[^\n]\n", filename) != EOF) add_exclude(filename); fclose(fd); } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-sort") == 0) i++; if(i != argc) { if(++i == argc) { ERROR("%s: -e missing arguments\n", argv[0]); EXIT_MKSQUASHFS(); } while(i < argc && add_exclude(argv[i++])); } /* process the sort files - must be done afer the exclude files */ for(i = source + 2; i < argc; i++) if(strcmp(argv[i], "-sort") == 0) { read_sort_file(argv[++i], source, source_path); sorted ++; } else if(strcmp(argv[i], "-e") == 0) break; else if(strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-root-becomes") == 0 || strcmp(argv[i], "-ef") == 0) i++; if(delete) { printf("Creating %s %d.%d filesystem on %s, block size %d.\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); bytes = sizeof(squashfs_super_block); } else { unsigned int last_directory_block, inode_dir_offset, inode_dir_file_size, root_inode_size, inode_dir_start_block, uncompressed_data, compressed_data, inode_dir_inode_number, inode_dir_parent_inode; unsigned int root_inode_start = SQUASHFS_INODE_BLK(sBlk.root_inode), root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk.root_inode); be = orig_be; block_log = slog(block_size = sBlk.block_size); noI = SQUASHFS_UNCOMPRESSED_INODES(sBlk.flags); noD = SQUASHFS_UNCOMPRESSED_DATA(sBlk.flags); noF = SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk.flags); check_data = SQUASHFS_CHECK_DATA(sBlk.flags); no_fragments = SQUASHFS_NO_FRAGMENTS(sBlk.flags); always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); if((bytes = read_filesystem(root_name, fd, &sBlk, &inode_table, &data_cache, &directory_table, &directory_data_cache, &last_directory_block, &inode_dir_offset, &inode_dir_file_size, &root_inode_size, &inode_dir_start_block, &file_count, &sym_count, &dev_count, &dir_count, &fifo_count, &sock_count, (squashfs_uid *) uids, &uid_count, (squashfs_uid *) guids, &guid_count, &total_bytes, &total_inode_bytes, &total_directory_bytes, &inode_dir_inode_number, &inode_dir_parent_inode, add_old_root_entry, &fragment_table)) == 0) { ERROR("Failed to read existing filesystem - will not overwrite - ABORTING!\n"); EXIT_MKSQUASHFS(); } if((fragments = sBlk.fragments)) fragment_table = (squashfs_fragment_entry *) realloc((char *) fragment_table, ((fragments + FRAG_SIZE - 1) & ~(FRAG_SIZE - 1)) * sizeof(squashfs_fragment_entry)); printf("Appending to existing %s %d.%d filesystem on %s, block size %d\n", be ? "big endian" : "little endian", SQUASHFS_MAJOR, SQUASHFS_MINOR, argv[source + 1], block_size); printf("All -be, -le, -b, -noI, -noD, -noF, -check_data, no-duplicates, no-fragments, -always-use-fragments and -2.0 options ignored\n"); printf("\nIf appending is not wanted, please re-run with -noappend specified!\n\n"); compressed_data = inode_dir_offset + inode_dir_file_size & ~(SQUASHFS_METADATA_SIZE - 1); uncompressed_data = inode_dir_offset + inode_dir_file_size & (SQUASHFS_METADATA_SIZE - 1); /* save original filesystem state for restoring ... */ sfragments = fragments; sbytes = bytes; sinode_count = sBlk.inodes; sdata_cache = (char *)malloc(scache_bytes = root_inode_offset + root_inode_size); sdirectory_data_cache = (char *)malloc(sdirectory_cache_bytes = uncompressed_data); memcpy(sdata_cache, data_cache, scache_bytes); memcpy(sdirectory_data_cache, directory_data_cache + compressed_data, sdirectory_cache_bytes); sinode_bytes = root_inode_start; sdirectory_bytes = last_directory_block; suid_count = uid_count; sguid_count = guid_count; stotal_bytes = total_bytes; stotal_inode_bytes = total_inode_bytes; stotal_directory_bytes = total_directory_bytes + compressed_data; sfile_count = file_count; ssym_count = sym_count; sdev_count = dev_count; sdir_count = dir_count + 1; sfifo_count = fifo_count; ssock_count = sock_count; sdup_files = dup_files; restore = TRUE; if(setjmp(env)) goto restore_filesystem; signal(SIGTERM, sighandler); signal(SIGINT, sighandler); write_bytes(fd, SQUASHFS_START, 4, "\0\0\0\0"); /* set the filesystem state up to be able to append to the original filesystem. The filesystem state * differs depending on whether we're appending to the original root directory, or if the original * root directory becomes a sub-directory (root-becomes specified on command line, here root_name != NULL) */ inode_bytes = inode_size = root_inode_start; directory_size = last_directory_block; cache_size = root_inode_offset + root_inode_size; directory_cache_size = inode_dir_offset + inode_dir_file_size; if(root_name) { root_inode_number = inode_dir_parent_inode; dir_inode_no = sBlk.inodes + 2; directory_bytes = last_directory_block; directory_cache_bytes = uncompressed_data; memmove(directory_data_cache, directory_data_cache + compressed_data, uncompressed_data); cache_bytes = root_inode_offset + root_inode_size; add_old_root_entry(root_name, sBlk.root_inode, inode_dir_inode_number, SQUASHFS_DIR_TYPE); total_directory_bytes += compressed_data; dir_count ++; } else { root_inode_number = inode_dir_inode_number; dir_inode_no = sBlk.inodes + 1; directory_bytes = inode_dir_start_block; directory_cache_bytes = inode_dir_offset; cache_bytes = root_inode_offset; } inode_count = file_count + dir_count + sym_count + dev_count + fifo_count + sock_count; } #if __BYTE_ORDER == __BIG_ENDIAN swap = !be; #else swap = be; #endif block_offset = check_data ? 3 : 2; if(delete && !keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_readdir); else if(!keep_as_directory && source == 1 && S_ISDIR(source_buf.st_mode)) dir_scan(&inode, source_path[0], scan1_single_readdir); else dir_scan(&inode, "", scan1_encomp_readdir); sBlk.root_inode = inode; sBlk.inodes = inode_count; sBlk.s_magic = SQUASHFS_MAGIC; sBlk.s_major = SQUASHFS_MAJOR; sBlk.s_minor = SQUASHFS_MINOR; sBlk.block_size = block_size; sBlk.block_log = block_log; sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, check_data, noF, no_fragments, always_use_fragments, duplicate_checking); sBlk.mkfs_time = time(NULL); restore_filesystem: write_fragment(); sBlk.fragments = fragments; sBlk.inode_table_start = write_inodes(); sBlk.directory_table_start = write_directories(); sBlk.fragment_table_start = write_fragment_table(); TRACE("sBlk->inode_table_start 0x%x\n", sBlk.inode_table_start); TRACE("sBlk->directory_table_start 0x%x\n", sBlk.directory_table_start); TRACE("sBlk->fragment_table_start 0x%x\n", sBlk.fragment_table_start); if(sBlk.no_uids = uid_count) { if(!swap) write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[uid_count]; SQUASHFS_SWAP_DATA(uids, uids_copy, uid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, uid_count * sizeof(squashfs_uid), (char *) uids_copy); } sBlk.uid_start = bytes; bytes += uid_count * sizeof(squashfs_uid); } else sBlk.uid_start = 0; if(sBlk.no_guids = guid_count) { if(!swap) write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[guid_count]; SQUASHFS_SWAP_DATA(guids, guids_copy, guid_count, sizeof(squashfs_uid) * 8); write_bytes(fd, bytes, guid_count * sizeof(squashfs_uid), (char *) guids_copy); } sBlk.guid_start = bytes; bytes += guid_count * sizeof(squashfs_uid); } else sBlk.guid_start = 0; sBlk.bytes_used = bytes; sBlk.unused = SQUASHFS_INVALID_BLK; if(!swap) write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk); else { squashfs_super_block sBlk_copy; SQUASHFS_SWAP_SUPER_BLOCK((&sBlk), &sBlk_copy); write_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) &sBlk_copy); } if(!nopad && (i = bytes & (4096 - 1))) { char temp[4096] = {0}; write_bytes(fd, bytes, 4096 - i, temp); } total_bytes += total_inode_bytes + total_directory_bytes + uid_count * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + sizeof(squashfs_super_block); printf("\n%s filesystem, data block size %d, %s data, %s metadata, %s fragments\n", be ? "Big endian" : "Little endian", block_size, noD ? "uncompressed" : "compressed", noI ? "uncompressed" : "compressed", no_fragments ? "no" : noF ? "uncompressed" : "compressed"); printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", bytes / 1024.0, bytes / (1024.0 * 1024.0)); printf("\t%.2f%% of uncompressed filesystem size (%.2f Kbytes)\n", ((float) bytes / total_bytes) * 100.0, total_bytes / 1024.0); printf("Inode table size %d bytes (%.2f Kbytes)\n", inode_bytes, inode_bytes / 1024.0); printf("\t%.2f%% of uncompressed inode table size (%d bytes)\n", ((float) inode_bytes / total_inode_bytes) * 100.0, total_inode_bytes); printf("Directory table size %d bytes (%.2f Kbytes)\n", directory_bytes, directory_bytes / 1024.0); printf("\t%.2f%% of uncompressed directory table size (%d bytes)\n", ((float) directory_bytes / total_directory_bytes) * 100.0, total_directory_bytes); if(duplicate_checking) printf("Number of duplicate files found %d\n", file_count - dup_files); else printf("No duplicate files removed\n"); printf("Number of inodes %d\n", inode_count); printf("Number of files %d\n", file_count); if(!no_fragments) printf("Number of fragments %d\n", fragments); printf("Number of symbolic links %d\n", sym_count); printf("Number of device nodes %d\n", dev_count); printf("Number of fifo nodes %d\n", fifo_count); printf("Number of socket nodes %d\n", sock_count); printf("Number of directories %d\n", dir_count); printf("Number of uids %d\n", uid_count); for(i = 0; i < uid_count; i++) { struct passwd *user = getpwuid(uids[i]); printf("\t%s (%d)\n", user == NULL ? "unknown" : user->pw_name, uids[i]); } printf("Number of gids %d\n", guid_count); for(i = 0; i < guid_count; i++) { struct group *group = getgrgid(guids[i]); printf("\t%s (%d)\n", group == NULL ? "unknown" : group->gr_name, guids[i]); } close(fd); return 0; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/mksquashfs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = (long long) value << (SHIFT);\ unsigned char *s = ((unsigned char *) &val) + 7;\ unsigned char *d = ((unsigned char *)p) + (pos / 8);\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d++ |= *s--;\ } #define SQUASHFS_MEMSET(s, d, n) memset(d, 0, n); ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/read_fs.c ================================================ /* * Read a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * read_fs.c */ extern void read_bytes(int, long long, int, char *); extern int add_file(long long, long long, unsigned int *, int, unsigned int, int, int); #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) int swap; int read_block(int fd, long long start, long long *next, unsigned char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { read_bytes(fd, start, 2, (char *) block); ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else read_bytes(fd, start, 2, (char *)&c_byte); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, buffer); if((res = uncompress(block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_bytes(fd, start + offset, c_byte, (char *) block); if(next) *next = start + offset + c_byte; return c_byte; } } int scan_inode_table(int fd, long long start, long long end, long long root_inode_start, int root_inode_offset, squashfs_super_block *sBlk, squashfs_inode_header *dir_inode, unsigned char **inode_table, unsigned int *root_inode_block, unsigned int *root_inode_size, long long *uncompressed_file, unsigned int *uncompressed_directory, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count) { unsigned char *cur_ptr; int byte, bytes = 0, size = 0, files = 0; squashfs_reg_inode_header inode; unsigned int directory_start_block; TRACE("scan_inode_table: start 0x%llx, end 0x%llx, root_inode_start 0x%llx\n", start, end, root_inode_start); while(start < end) { if(start == root_inode_start) { TRACE("scan_inode_table: read compressed block 0x%llx containing root inode\n", start); *root_inode_block = bytes; } if((size - bytes < SQUASHFS_METADATA_SIZE) && ((*inode_table = realloc(*inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) return FALSE; TRACE("scan_inode_table: reading block 0x%llx\n", start); if((byte = read_block(fd, start, &start, *inode_table + bytes, sBlk)) == 0) { free(*inode_table); return FALSE; } bytes += byte; } /* * Read last inode entry which is the root directory inode, and obtain the last * directory start block index. This is used when calculating the total uncompressed * directory size. The directory bytes in the last block will be counted as normal. * * The root inode is ignored in the inode scan. This ensures there is * always enough bytes left to read a regular file inode entry */ *root_inode_size = bytes - (*root_inode_block + root_inode_offset); bytes = *root_inode_block + root_inode_offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&dir_inode->base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&dir_inode->base, *inode_table + bytes, sizeof(dir_inode->base)); if(dir_inode->base.inode_type == SQUASHFS_DIR_TYPE) { if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode->dir, &sinode); } else memcpy(&dir_inode->dir, *inode_table + bytes, sizeof(dir_inode->dir)); directory_start_block = dir_inode->dir.start_block; } else { if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, *inode_table + bytes, sizeof(dir_inode->ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode->ldir, &sinode); } else memcpy(&dir_inode->ldir, *inode_table + bytes, sizeof(dir_inode->ldir)); directory_start_block = dir_inode->ldir.start_block; } for(cur_ptr = *inode_table; cur_ptr < *inode_table + bytes; files ++) { if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(inode)); SQUASHFS_SWAP_REG_INODE_HEADER(&inode, &sinode); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: processing inode @ byte position 0x%x, type 0x%x\n", cur_ptr - *inode_table, inode.inode_type); switch(inode.inode_type) { case SQUASHFS_FILE_TYPE: { int frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; int blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; long long file_bytes = 0; int i, start = inode.start_block; unsigned int *block_list; TRACE("scan_inode_table: regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } cur_ptr += sizeof(inode); if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_LREG_TYPE: { squashfs_lreg_inode_header inode; int frag_bytes; int blocks; long long file_bytes = 0; int i, start; unsigned int *block_list; if(swap) { squashfs_lreg_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_LREG_INODE_HEADER(&inode, &sinodep); } else memcpy(&inode, cur_ptr, sizeof(inode)); TRACE("scan_inode_table: extended regular file, file_size %lld, blocks %d\n", inode.file_size, blocks); cur_ptr += sizeof(inode); frag_bytes = inode.fragment == SQUASHFS_INVALID_FRAG ? 0 : inode.file_size % sBlk->block_size; blocks = inode.fragment == SQUASHFS_INVALID_FRAG ? (inode.file_size + sBlk->block_size - 1) >> sBlk->block_log : inode.file_size >> sBlk->block_log; start = inode.start_block; if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("Out of memory in block list malloc\n"); goto failed; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, cur_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, cur_ptr, blocks * sizeof(unsigned int)); *uncompressed_file += inode.file_size; (*file_count) ++; for(i = 0; i < blocks; i++) file_bytes += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); add_file(start, file_bytes, block_list, blocks, inode.fragment, inode.offset, frag_bytes); cur_ptr += blocks * sizeof(unsigned int); break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header inodep; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, cur_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep); } else memcpy(&inodep, cur_ptr, sizeof(inodep)); (*sym_count) ++; cur_ptr += sizeof(inodep) + inodep.symlink_size; break; } case SQUASHFS_DIR_TYPE: { squashfs_dir_inode_header dir_inode; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_DIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_dir_inode_header); break; } case SQUASHFS_LDIR_TYPE: { squashfs_ldir_inode_header dir_inode; int i; if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, cur_ptr, sizeof(dir_inode)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&dir_inode, &sinode); } else memcpy(&dir_inode, cur_ptr, sizeof(dir_inode)); if(dir_inode.start_block < directory_start_block) *uncompressed_directory += dir_inode.file_size; (*dir_count) ++; cur_ptr += sizeof(squashfs_ldir_inode_header); for(i = 0; i < dir_inode.i_count; i++) { squashfs_dir_index index; if(swap) { squashfs_dir_index sindex; memcpy(&sindex, cur_ptr, sizeof(squashfs_dir_index)); SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); } else memcpy(&index, cur_ptr, sizeof(squashfs_dir_index)); cur_ptr += sizeof(squashfs_dir_index) + index.size + 1; } break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: (*dev_count) ++; cur_ptr += sizeof(squashfs_dev_inode_header); break; case SQUASHFS_FIFO_TYPE: (*fifo_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; case SQUASHFS_SOCKET_TYPE: (*sock_count) ++; cur_ptr += sizeof(squashfs_ipc_inode_header); break; default: ERROR("Unknown inode type %d in scan_inode_table!\n", inode.inode_type); goto failed; } } return files; failed: free(*inode_table); return FALSE; } int read_super(int fd, squashfs_super_block *sBlk, int *be, char *source) { read_bytes(fd, SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s - ignoring -le/-be options\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { if(sBlk->s_major < 3) ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem. Appending\nto SQUASHFS %d.%d filesystems is not supported. Please convert it to a SQUASHFS 3.0 filesystem\n", source, sBlk->s_major, sBlk->s_minor, sBlk->s_major, sBlk->s_minor); else ERROR("Major/Minor mismatch, filesystem on %s is %d.%d, I support 3.0\n", source, sBlk->s_major, sBlk->s_minor); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN *be = !swap; #else *be = swap; #endif printf("Found a valid SQUASHFS superblock on %s.\n", source); printf("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); printf("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); printf("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); printf("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); printf("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); printf("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); printf("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); printf("\tBlock size %d\n", sBlk->block_size); printf("\tNumber of fragments %d\n", sBlk->fragments); printf("\tNumber of inodes %d\n", sBlk->inodes); printf("\tNumber of uids %d\n", sBlk->no_uids); printf("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start %llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start %llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start); printf("\n"); return TRUE; failed_mount: return FALSE; } unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size, unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int)) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; unsigned char *directory_table = NULL; int byte, bytes = 0, dir_count; long long start = sBlk->directory_table_start + directory_start_block, last_start_block; size += offset; if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL) return NULL; while(bytes < size) { TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes); last_start_block = start; if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) { free(directory_table); return NULL; } bytes += byte; } if(!root_entries) goto all_done; bytes = offset; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type); push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dire->inode_number, dire->type); bytes += dire->size + 1; } } all_done: *last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start; return directory_table; } int read_fragment_table(int fd, squashfs_super_block *sBlk, squashfs_fragment_entry **fragment_table) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return 1; if((*fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) { ERROR("Failed to allocate fragment table\n"); return 0; } if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(fd, sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fd, fragment_table_index[i], NULL, ((unsigned char *) *fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&(*fragment_table)[i])); memcpy((char *) &(*fragment_table)[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } return 1; } long long read_filesystem(char *root_name, int fd, squashfs_super_block *sBlk, char **cinode_table, char **data_cache, char **cdirectory_table, char **directory_data_cache, unsigned int *last_directory_block, unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size, unsigned int *root_inode_size, unsigned int *inode_dir_start_block, int *file_count, int *sym_count, int *dev_count, int *dir_count, int *fifo_count, int *sock_count, squashfs_uid *uids, unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_count, long long *uncompressed_file, unsigned int *uncompressed_inode, unsigned int *uncompressed_directory, unsigned int *inode_dir_inode_number, unsigned int *inode_dir_parent_inode, void (push_directory_entry)(char *, squashfs_inode, int, int), squashfs_fragment_entry **fragment_table) { unsigned char *inode_table = NULL, *directory_table; long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start + SQUASHFS_INODE_BLK(sBlk->root_inode); unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files; squashfs_inode_header inode; printf("Scanning existing filesystem...\n"); if(read_fragment_table(fd, sBlk, fragment_table) == 0) goto error; if((files = scan_inode_table(fd, start, end, root_inode_start, root_inode_offset, sBlk, &inode, &inode_table, &root_inode_block, root_inode_size, uncompressed_file, uncompressed_directory, file_count, sym_count, dev_count, dir_count, fifo_count, sock_count)) == 0) { ERROR("read_filesystem: inode table read failed\n"); goto error; } *uncompressed_inode = root_inode_block; printf("Read existing filesystem, %d inodes scanned\n", files); if(inode.base.inode_type == SQUASHFS_DIR_TYPE || inode.base.inode_type == SQUASHFS_LDIR_TYPE) { if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { *inode_dir_start_block = inode.dir.start_block; *inode_dir_offset = inode.dir.offset; *inode_dir_file_size = inode.dir.file_size - 3; *inode_dir_inode_number = inode.dir.inode_number; *inode_dir_parent_inode = inode.dir.parent_inode; } else { *inode_dir_start_block = inode.ldir.start_block; *inode_dir_offset = inode.ldir.offset; *inode_dir_file_size = inode.ldir.file_size - 3; *inode_dir_inode_number = inode.ldir.inode_number; *inode_dir_parent_inode = inode.ldir.parent_inode; } if((directory_table = squashfs_readdir(fd, !root_name, *inode_dir_start_block, *inode_dir_offset, *inode_dir_file_size, last_directory_block, sBlk, push_directory_entry)) == NULL) { ERROR("read_filesystem: Could not read root directory\n"); goto error; } root_inode_start -= start; if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n"); goto error; } read_bytes(fd, start, root_inode_start, *cinode_table); if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) { ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n"); goto error; } read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table); if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) { ERROR("read_filesystem: failed to alloc inode cache\n"); goto error; } memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size); if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) { ERROR("read_filesystem: failed to alloc directory cache\n"); goto error; } memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size); if(!swap) read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids); else { squashfs_uid uids_copy[sBlk->no_uids]; read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy); SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8); } if(!swap) read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids); else { squashfs_uid guids_copy[sBlk->no_guids]; read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy); SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8); } *uid_count = sBlk->no_uids; *guid_count = sBlk->no_guids; free(inode_table); free(directory_table); return sBlk->inode_table_start; } error: return 0; } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/read_fs.h ================================================ /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating a filesystem on a * machine with different byte ordering to the target architecture. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * mksquashfs.h * */ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing architectures */ #if __BYTE_ORDER == __BIG_ENDIAN /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos) #else /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ int bits;\ int b_pos = pos % 8;\ unsigned long long val = 0;\ unsigned char *s = (unsigned char *)p + (pos / 8);\ unsigned char *d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/sort.c ================================================ /* * Create a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "sort.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define INFO(s, args...) do { \ if(!silent) printf("mksquashfs: "s, ## args); \ } while(0) #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_MKSQUASHFS() do { \ exit(1); \ } while(0) #define BAD_ERROR(s, args...) do {\ fprintf(stderr, "FATAL ERROR:" s, ##args);\ EXIT_MKSQUASHFS();\ } while(0); int mkisofs_style = -1; struct sort_info { dev_t st_dev; ino_t st_ino; int priority; struct sort_info *next; }; struct sort_info *sort_info_list[65536]; struct priority_entry { struct dir_ent *dir; struct priority_entry *next; }; struct priority_entry *priority_list[65536]; extern int silent; extern squashfs_inode write_file(squashfs_inode *inode, struct dir_ent *dir_ent, long long size, int *c_size); int add_priority_list(struct dir_ent *dir, int priority) { struct priority_entry *new_priority_entry; priority += 32768; if((new_priority_entry = malloc(sizeof(struct priority_entry))) == NULL) { ERROR("Out of memory allocating priority entry\n"); return FALSE; } new_priority_entry->dir = dir;; new_priority_entry->next = priority_list[priority]; priority_list[priority] = new_priority_entry; return TRUE; } int get_priority(char *filename, struct stat *buf, int priority) { int hash = buf->st_ino & 0xffff; struct sort_info *s; for(s = sort_info_list[hash]; s; s = s->next) if((s->st_dev == buf->st_dev) && (s->st_ino == buf->st_ino)) { TRACE("returning priority %d (%s)\n", s->priority, filename); return s->priority; } TRACE("returning priority %d (%s)\n", priority, filename); return priority; } #define ADD_ENTRY(buf, priority) {\ int hash = buf.st_ino & 0xffff;\ struct sort_info *s;\ if((s = malloc(sizeof(struct sort_info))) == NULL) {\ ERROR("Out of memory allocating sort list entry\n");\ return FALSE;\ }\ s->st_dev = buf.st_dev;\ s->st_ino = buf.st_ino;\ s->priority = priority;\ s->next = sort_info_list[hash];\ sort_info_list[hash] = s;\ } int add_sort_list(char *path, int priority, int source, char *source_path[]) { int i, n; char filename[4096]; struct stat buf; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); if(strlen(path) > 1 && strcmp(path + strlen(path) - 2, "/*") == 0) path[strlen(path) - 2] = '\0'; TRACE("add_sort_list: filename %s, priority %d\n", path, priority); re_read: if(path[0] == '/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0 || mkisofs_style == 1) { if(lstat(path, &buf) == -1) goto error; TRACE("adding filename %s, priority %d, st_dev %llx, st_ino %llx\n", path, priority, buf.st_dev, buf.st_ino); ADD_ENTRY(buf, priority); return TRUE; } for(i = 0, n = 0; i < source; i++) { strcat(strcat(strcpy(filename, source_path[i]), "/"), path); if(lstat(filename, &buf) == -1) { if(!(errno == ENOENT || errno == ENOTDIR)) goto error; continue; } ADD_ENTRY(buf, priority); n ++; } if(n == 0 && mkisofs_style == -1 && lstat(path, &buf) != -1) { ERROR("WARNING: Mkisofs style sortlist detected! This is supported but please\n"); ERROR("convert to mksquashfs style sortlist! A sortlist entry "); ERROR("should be\neither absolute (starting with "); ERROR("'/') start with './' or '../' (taken to be\nrelative to $PWD), otherwise it "); ERROR("is assumed the entry is relative to one\nof the source directories, i.e. with "); ERROR("\"mksquashfs test test.sqsh\",\nthe sortlist "); ERROR("entry \"file\" is assumed to be inside the directory test.\n\n"); mkisofs_style = 1; goto re_read; } mkisofs_style = 0; if(n == 1) return TRUE; if(n > 1) BAD_ERROR(" Ambiguous sortlist entry \"%s\"\n\nIt maps to more than one source entry! Please use an absolute path.\n", path); error: fprintf(stderr, "Cannot stat sortlist entry \"%s\"\n", path); fprintf(stderr, "This is probably because you're using the wrong file\n"); fprintf(stderr, "path relative to the source directories\n"); return FALSE; } void generate_file_priorities(struct dir_info *dir, int priority, struct stat *buf) { priority = get_priority(dir->pathname, buf, priority); while(dir->current_count < dir->count) { struct dir_ent *dir_ent = dir->list[dir->current_count++]; struct stat *buf = &dir_ent->inode->buf; if(dir_ent->data) continue; switch(buf->st_mode & S_IFMT) { case S_IFREG: add_priority_list(dir_ent, get_priority(dir_ent->pathname, buf, priority)); break; case S_IFDIR: generate_file_priorities(dir_ent->dir, priority, buf); break; } } dir->current_count = 0; } int read_sort_file(char *filename, int source, char *source_path[]) { FILE *fd; char sort_filename[16385]; int priority; if((fd = fopen(filename, "r")) == NULL) { perror("Could not open sort_list file..."); return FALSE; } while(fscanf(fd, "%s %d", sort_filename, &priority) != EOF) if(priority >= -32768 && priority <= 32767) add_sort_list(sort_filename, priority, source, source_path); else ERROR("Sort file %s, priority %d outside range of -32767:32768 - skipping...\n", sort_filename, priority); fclose(fd); return TRUE; } void sort_files_and_write(struct dir_info *dir) { int i; struct priority_entry *entry; squashfs_inode inode; int duplicate_file; generate_file_priorities(dir, 0, &dir->dir_ent->inode->buf); for(i = 65535; i >= 0; i--) for(entry = priority_list[i]; entry; entry = entry->next) { TRACE("%d: %s\n", i - 32768, entry->dir->pathname); if(entry->dir->inode->inode == SQUASHFS_INVALID_BLK) { if(write_file(&inode, entry->dir, entry->dir->inode->buf.st_size, &duplicate_file)) { INFO("file %s, uncompressed size %lld bytes %s\n", entry->dir->pathname, entry->dir->inode->buf.st_size, duplicate_file ? "DUPLICATE" : ""); entry->dir->inode->inode = inode; entry->dir->inode->type = SQUASHFS_FILE_TYPE; } } else INFO("file %s, uncompressed size %lld bytes LINK\n", entry->dir->pathname, entry->dir->inode->buf.st_size); } } ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/sort.h ================================================ #ifndef SORT_H #define SORT_H /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * sort.h */ struct dir_info { char *pathname; unsigned int count; unsigned int directory_count; unsigned int current_count; unsigned int byte_count; char dir_is_ldir; struct dir_ent *dir_ent; struct dir_ent **list; DIR *linuxdir; }; struct dir_ent { char *name; char *pathname; struct inode_info *inode; struct dir_info *dir; struct dir_info *our_dir; struct old_root_entry_info *data; }; struct inode_info { unsigned int nlink; struct stat buf; squashfs_inode inode; unsigned int type; unsigned int inode_number; struct inode_info *next; }; #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/squashfs_fs.h ================================================ #ifndef SQUASHFS_FS #define SQUASHFS_FS /* * Squashfs * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * squashfs_fs.h */ #define SQUASHFS_MAJOR 3 #define SQUASHFS_MINOR 0 #define SQUASHFS_MAGIC 0x74717368 #define SQUASHFS_MAGIC_SWAP 0x68737174 #define SQUASHFS_START 0 /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 #define SQUASHFS_METADATA_LOG 13 /* default size of data blocks */ #define SQUASHFS_FILE_SIZE 131072 #define SQUASHFS_FILE_LOG 17 #define SQUASHFS_FILE_MAX_SIZE 1048576 /*#define SQUASHFS_FILE_SIZE 65536 #define SQUASHFS_FILE_LOG 16 #define SQUASHFS_FILE_MAX_SIZE 65536 */ /* Max number of uids and gids */ #define SQUASHFS_UIDS 256 #define SQUASHFS_GUIDS 255 /* Max length of filename (not 255) */ #define SQUASHFS_NAME_LEN 256 #define SQUASHFS_INVALID ((long long) 0xffffffffffff) #define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) #define SQUASHFS_INVALID_BLK ((long long) -1) #define SQUASHFS_USED_BLK ((long long) -2) /* Filesystem flags */ #define SQUASHFS_NOI 0 #define SQUASHFS_NOD 1 #define SQUASHFS_CHECK 2 #define SQUASHFS_NOF 3 #define SQUASHFS_NO_FRAG 4 #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) #define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOI) #define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOD) #define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NOF) #define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_NO_FRAG) #define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ SQUASHFS_ALWAYS_FRAG) #define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ SQUASHFS_DUPLICATE) #define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ SQUASHFS_CHECK) #define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ (duplicate_checking << 6)) /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_FILE_TYPE 2 #define SQUASHFS_SYMLINK_TYPE 3 #define SQUASHFS_BLKDEV_TYPE 4 #define SQUASHFS_CHRDEV_TYPE 5 #define SQUASHFS_FIFO_TYPE 6 #define SQUASHFS_SOCKET_TYPE 7 #define SQUASHFS_LDIR_TYPE 8 #define SQUASHFS_LREG_TYPE 9 /* 1.0 filesystem type definitions */ #define SQUASHFS_TYPES 5 #define SQUASHFS_IPC_TYPE 0 /* Flag whether block is compressed or uncompressed, bit is set if block is * uncompressed */ #define SQUASHFS_COMPRESSED_BIT (1 << 15) #define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) #define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) #define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) #define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) ((B) & \ ~SQUASHFS_COMPRESSED_BIT_BLOCK) //#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ // ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ // ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block */ #define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) #define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) #define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ << 16) + (B))) /* Compute 32 bit VFS inode number from squashfs inode number */ #define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ ((b) >> 2) + 1)) /* XXX */ /* Translate between VFS mode and squashfs mode */ #define SQUASHFS_MODE(a) ((a) & 0xfff) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) #define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ sizeof(long long)) #define SQUASHFS_CACHED_FRAGMENTS 3 /* cached data constants for filesystem */ #define SQUASHFS_CACHED_BLKS 8 #define SQUASHFS_MAX_FILE_SIZE_LOG 64 #define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) #define SQUASHFS_MARKER_BYTE 0xff /* * definitions for structures on disk */ typedef long long squashfs_block_t; typedef long long squashfs_inode_t; struct squashfs_super_block { unsigned int s_magic; unsigned int inodes; unsigned int bytes_used_2; unsigned int uid_start_2; unsigned int guid_start_2; unsigned int inode_table_start_2; unsigned int directory_table_start_2; unsigned int s_major:16; unsigned int s_minor:16; unsigned int block_size_1:16; unsigned int block_log:16; unsigned int flags:8; unsigned int no_uids:8; unsigned int no_guids:8; unsigned int mkfs_time /* time of filesystem creation */; squashfs_inode_t root_inode; unsigned int block_size; unsigned int fragments; unsigned int fragment_table_start_2; long long bytes_used; long long uid_start; long long guid_start; long long inode_table_start; long long directory_table_start; long long fragment_table_start; long long unused; } __attribute__ ((packed)); struct squashfs_dir_index { unsigned int index; unsigned int start_block; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); #define SQUASHFS_BASE_INODE_HEADER \ unsigned int inode_type:4; \ unsigned int mode:12; \ unsigned int uid:8; \ unsigned int guid:8; \ unsigned int mtime; \ unsigned int inode_number; struct squashfs_base_inode_header { SQUASHFS_BASE_INODE_HEADER; } __attribute__ ((packed)); struct squashfs_ipc_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; } __attribute__ ((packed)); struct squashfs_dev_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header { SQUASHFS_BASE_INODE_HEADER; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; unsigned int file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_lreg_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; squashfs_block_t start_block; unsigned int fragment; unsigned int offset; long long file_size; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:19; unsigned int offset:13; unsigned int start_block; unsigned int parent_inode; } __attribute__ ((packed)); struct squashfs_ldir_inode_header { SQUASHFS_BASE_INODE_HEADER; unsigned int nlink; unsigned int file_size:27; unsigned int offset:13; unsigned int start_block; unsigned int i_count:16; unsigned int parent_inode; struct squashfs_dir_index index[0]; } __attribute__ ((packed)); union squashfs_inode_header { struct squashfs_base_inode_header base; struct squashfs_dev_inode_header dev; struct squashfs_symlink_inode_header symlink; struct squashfs_reg_inode_header reg; struct squashfs_lreg_inode_header lreg; struct squashfs_dir_inode_header dir; struct squashfs_ldir_inode_header ldir; struct squashfs_ipc_inode_header ipc; }; struct squashfs_dir_entry { unsigned int offset:13; unsigned int type:3; unsigned int size:8; int inode_number:16; char name[0]; } __attribute__ ((packed)); struct squashfs_dir_header { unsigned int count:8; unsigned int start_block; unsigned int inode_number; } __attribute__ ((packed)); struct squashfs_fragment_entry { long long start_block; unsigned int size; unsigned int unused; } __attribute__ ((packed)); extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); extern int squashfs_uncompress_init(void); extern int squashfs_uncompress_exit(void); /* * macros to convert each packed bitfield structure from little endian to big * endian and vice versa. These are needed when creating or using a filesystem * on a machine with different byte ordering to the target architecture. * */ #define SQUASHFS_SWAP_START \ int bits;\ int b_pos;\ unsigned long long val;\ unsigned char *s;\ unsigned char *d; #define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ SQUASHFS_SWAP((s)->unused, d, 888, 64);\ } #define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); #define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ipc_inode_header))\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dev_inode_header)); \ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_symlink_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_reg_inode_header));\ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ } #define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_lreg_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_dir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ sizeof(struct squashfs_ldir_inode_header));\ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ } #define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ SQUASHFS_SWAP((s)->index, d, 0, 32);\ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ SQUASHFS_SWAP((s)->size, d, 64, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ } #define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ SQUASHFS_SWAP((s)->size, d, 64, 32);\ } #define SQUASHFS_SWAP_SHORTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 2);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 16)\ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ } #define SQUASHFS_SWAP_INTS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 4);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 32)\ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ } #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ 64)\ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ } #define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ int entry;\ int bit_position;\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, n * bits / 8);\ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ bits)\ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY struct squashfs_base_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int type:4; unsigned int offset:4; } __attribute__ ((packed)); struct squashfs_dev_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_1 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:4; /* index into uid table */ unsigned int guid:4; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ SQUASHFS_SWAP((s)->guid, d, 20, 4); #define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_ipc_inode_header_1));\ SQUASHFS_SWAP((s)->type, d, 24, 4);\ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ } #define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dev_inode_header_1));\ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_symlink_inode_header_1));\ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_reg_inode_header_1));\ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ sizeof(struct squashfs_dir_inode_header_1));\ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ } #endif #ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY struct squashfs_dir_index_2 { unsigned int index:27; unsigned int start_block:29; unsigned char size; unsigned char name[0]; } __attribute__ ((packed)); struct squashfs_base_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_ipc_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ } __attribute__ ((packed)); struct squashfs_dev_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short rdev; } __attribute__ ((packed)); struct squashfs_symlink_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned short symlink_size; char symlink[0]; } __attribute__ ((packed)); struct squashfs_reg_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int mtime; unsigned int start_block; unsigned int fragment; unsigned int offset; unsigned int file_size:32; unsigned short block_list[0]; } __attribute__ ((packed)); struct squashfs_dir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:19; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_ldir_inode_header_2 { unsigned int inode_type:4; unsigned int mode:12; /* protection */ unsigned int uid:8; /* index into uid table */ unsigned int guid:8; /* index into guid table */ unsigned int file_size:27; unsigned int offset:13; unsigned int mtime; unsigned int start_block:24; unsigned int i_count:16; struct squashfs_dir_index_2 index[0]; } __attribute__ ((packed)); union squashfs_inode_header_2 { struct squashfs_base_inode_header_2 base; struct squashfs_dev_inode_header_2 dev; struct squashfs_symlink_inode_header_2 symlink; struct squashfs_reg_inode_header_2 reg; struct squashfs_dir_inode_header_2 dir; struct squashfs_ldir_inode_header_2 ldir; struct squashfs_ipc_inode_header_2 ipc; }; struct squashfs_dir_header_2 { unsigned int count:8; unsigned int start_block:24; } __attribute__ ((packed)); struct squashfs_dir_entry_2 { unsigned int offset:13; unsigned int type:3; unsigned int size:8; char name[0]; } __attribute__ ((packed)); struct squashfs_fragment_entry_2 { unsigned int start_block; unsigned int size; } __attribute__ ((packed)); #define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ SQUASHFS_MEMSET(s, d, n);\ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ #define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ } #define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) #define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dev_inode_header_2)); \ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ } #define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_symlink_inode_header_2));\ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ } #define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_reg_inode_header_2));\ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\ } #define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_dir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ } #define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ sizeof(struct squashfs_ldir_inode_header_2));\ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ } #define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ SQUASHFS_SWAP((s)->index, d, 0, 27);\ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ SQUASHFS_SWAP((s)->size, d, 56, 8);\ } #define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ SQUASHFS_SWAP((s)->count, d, 0, 8);\ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ } #define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ SQUASHFS_SWAP((s)->type, d, 13, 3);\ SQUASHFS_SWAP((s)->size, d, 16, 8);\ } #define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ SQUASHFS_SWAP_START\ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ SQUASHFS_SWAP((s)->size, d, 32, 32);\ } #define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) /* fragment and fragment table defines */ #define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) #define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ SQUASHFS_METADATA_SIZE - 1) / \ SQUASHFS_METADATA_SIZE) #define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ sizeof(int)) #endif #ifdef __KERNEL__ /* * macros used to swap each structure entry, taking into account * bitfields and different bitfield placing conventions on differing * architectures */ #include #ifdef __BIG_ENDIAN /* convert from little endian to big endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, b_pos) #else /* convert from big endian to little endian */ #define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ tbits, 64 - tbits - b_pos) #endif #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ b_pos = pos % 8;\ val = 0;\ s = (unsigned char *)p + (pos / 8);\ d = ((unsigned char *) &val) + 7;\ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ *d-- = *s++;\ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ } #define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); #endif #endif ================================================ FILE: src/squashfs-3.0-lzma-damn-small-variant/unsquashfs.c ================================================ /* * Unsquash a squashfs filesystem. This is a highly compressed read only filesystem. * * Copyright (c) 2002, 2003, 2004, 2005, 2006 * Phillip Lougher * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * unsquash.c */ #define TRUE 1 #define FALSE 0 #include #include #include #include #include #include #include #include #include #ifndef linux #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #else #include #endif #include #include "read_fs.h" #include "global.h" #include #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ printf("mksquashfs: "s, ## args); \ } while(0) #else #define TRACE(s, args...) #endif #define ERROR(s, args...) do { \ fprintf(stderr, s, ## args); \ } while(0) #define EXIT_UNSQUASH(s, args...) do { \ fprintf(stderr, "FATAL ERROR aborting: "s, ## args); \ } while(0) struct hash_table_entry { int start; int bytes; struct hash_table_entry *next; }; int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, dev_count = 0, fifo_count = 0; char *inode_table = NULL, *directory_table = NULL; struct hash_table_entry *inode_table_hash[65536], *directory_table_hash[65536]; int fd; squashfs_fragment_entry *fragment_table; unsigned int *uid_table, *guid_table; unsigned int cached_frag = SQUASHFS_INVALID_FRAG; char *fragment_data; char *file_data; char *data; unsigned int block_size; int lsonly = FALSE, info = FALSE; char **created_inode; #define CALCULATE_HASH(start) (start & 0xffff) int add_entry(struct hash_table_entry *hash_table[], int start, int bytes) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; if((hash_table_entry = malloc(sizeof(struct hash_table_entry))) == NULL) { ERROR("add_hash: out of memory in malloc\n"); return FALSE; } hash_table_entry->start = start; hash_table_entry->bytes = bytes; hash_table_entry->next = hash_table[hash]; hash_table[hash] = hash_table_entry; return TRUE; } int lookup_entry(struct hash_table_entry *hash_table[], int start) { int hash = CALCULATE_HASH(start); struct hash_table_entry *hash_table_entry; for(hash_table_entry = hash_table[hash]; hash_table_entry; hash_table_entry = hash_table_entry->next) if(hash_table_entry->start == start) return hash_table_entry->bytes; return -1; } int read_bytes(long long byte, int bytes, char *buff) { off_t off = byte; TRACE("read_bytes: reading from position 0x%llx, bytes %d\n", byte, bytes); if(lseek(fd, off, SEEK_SET) == -1) { ERROR("Lseek failed because %s\b", strerror(errno)); return FALSE; } if(read(fd, buff, bytes) == -1) { ERROR("Read on destination failed because %s\n", strerror(errno)); return FALSE; } return TRUE; } int read_block(long long start, long long *next, char *block, squashfs_super_block *sBlk) { unsigned short c_byte; int offset = 2; if(swap) { if(read_bytes(start, 2, block) == FALSE) goto failed; ((unsigned char *) &c_byte)[1] = block[0]; ((unsigned char *) &c_byte)[0] = block[1]; } else if(read_bytes(start, 2, (char *)&c_byte) == FALSE) goto failed; TRACE("read_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE(c_byte), SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_CHECK_DATA(sBlk->flags)) offset = 3; if(SQUASHFS_COMPRESSED(c_byte)) { char buffer[SQUASHFS_METADATA_SIZE]; int res; unsigned long bytes = SQUASHFS_METADATA_SIZE; c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) buffer, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); goto failed; } if(next) *next = start + offset + c_byte; return bytes; } else { c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, block) == FALSE) goto failed; if(next) *next = start + offset + c_byte; return c_byte; } failed: return FALSE; } int read_data_block(long long start, unsigned int size, char *block) { int res; unsigned long bytes = block_size; int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : "uncompressed"); if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) return 0; if((res = uncompress((unsigned char *) block, &bytes, (const unsigned char *) data, c_byte)) != Z_OK) { if(res == Z_MEM_ERROR) ERROR("zlib::uncompress failed, not enough memory\n"); else if(res == Z_BUF_ERROR) ERROR("zlib::uncompress failed, not enough room in output buffer\n"); else ERROR("zlib::uncompress failed, unknown error %d\n", res); return 0; } return bytes; } else { if(read_bytes(start, c_byte, block) == FALSE) return 0; return c_byte; } } void uncompress_inode_table(long long start, long long end, squashfs_super_block *sBlk) { int size = 0, bytes = 0, res; while(start < end) { if((size - bytes < SQUASHFS_METADATA_SIZE) && ((inode_table = realloc(inode_table, size += SQUASHFS_METADATA_SIZE)) == NULL)) EXIT_UNSQUASH("uncompress_inode_table: out of memory in realloc\n"); TRACE("uncompress_inode_table: reading block 0x%llx\n", start); add_entry(inode_table_hash, start, bytes); if((res = read_block(start, &start, inode_table + bytes, sBlk)) == 0) { free(inode_table); EXIT_UNSQUASH("uncompress_inode_table: failed to read block\n"); } bytes += res; } } int set_attributes(char *pathname, unsigned int mode, unsigned int uid, unsigned int guid, unsigned int mtime, unsigned int set_mode) { struct utimbuf times = { (time_t) mtime, (time_t) mtime }; if(utime(pathname, ×) == -1) { ERROR("set_attributes: failed to set time on %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(set_mode && chmod(pathname, (mode_t) mode) == -1) { ERROR("set_attributes: failed to change mode %s, because %s\n", pathname, strerror(errno)); return FALSE; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[uid]; uid_t guid_value = guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[guid]; if(chown(pathname, uid_value, guid_value) == -1) { ERROR("set_attributes: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); return FALSE; } } return TRUE; } void read_uids_guids(squashfs_super_block *sBlk) { if((uid_table = malloc((sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int))) == NULL) EXIT_UNSQUASH("read_uids_guids: failed to allocate uid/gid table\n"); guid_table = uid_table + sBlk->no_uids; if(read_bytes(sBlk->uid_start, (sBlk->no_uids + sBlk->no_guids) * sizeof(unsigned int), (char *) uid_table) == FALSE) EXIT_UNSQUASH("read_uids_guids: failed to read uid/gid table\n"); } void read_fragment_table(squashfs_super_block *sBlk) { int i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); squashfs_fragment_index fragment_table_index[indexes]; TRACE("read_fragment_table: %d fragments, reading %d fragment indexes from 0x%llx\n", sBlk->fragments, indexes, sBlk->fragment_table_start); if(sBlk->fragments == 0) return; if((fragment_table = (squashfs_fragment_entry *) malloc(sBlk->fragments * sizeof(squashfs_fragment_entry))) == NULL) EXIT_UNSQUASH("read_fragment_table: failed to allocate fragment table\n"); if(swap) { squashfs_fragment_index sfragment_table_index[indexes]; read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) sfragment_table_index); SQUASHFS_SWAP_FRAGMENT_INDEXES(fragment_table_index, sfragment_table_index, indexes); } else read_bytes(sBlk->fragment_table_start, SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), (char *) fragment_table_index); for(i = 0; i < indexes; i++) { int length = read_block(fragment_table_index[i], NULL, ((char *) fragment_table) + (i * SQUASHFS_METADATA_SIZE), sBlk); TRACE("Read fragment table block %d, from 0x%llx, length %d\n", i, fragment_table_index[i], length); } if(swap) { squashfs_fragment_entry sfragment; for(i = 0; i < sBlk->fragments; i++) { SQUASHFS_SWAP_FRAGMENT_ENTRY((&sfragment), (&fragment_table[i])); memcpy((char *) &fragment_table[i], (char *) &sfragment, sizeof(squashfs_fragment_entry)); } } } char *read_fragment(unsigned int fragment) { TRACE("read_fragment: reading fragment %d\n", fragment); if(cached_frag == SQUASHFS_INVALID_FRAG || fragment != cached_frag) { squashfs_fragment_entry *fragment_entry = &fragment_table[fragment]; if(read_data_block(fragment_entry->start_block, fragment_entry->size, fragment_data) == 0) { ERROR("read_fragment: failed to read fragment %d\n", fragment); cached_frag = SQUASHFS_INVALID_FRAG; return NULL; } cached_frag = fragment; } return fragment_data; } int write_file(char *pathname, unsigned int fragment, unsigned int frag_bytes, unsigned int offset, unsigned int blocks, long long start, char *block_ptr, unsigned int mode) { unsigned int file_fd, bytes, i; unsigned int *block_list; TRACE("write_file: regular file, blocks %d\n", blocks); if((block_list = malloc(blocks * sizeof(unsigned int))) == NULL) { ERROR("write_file: unable to malloc block list\n"); return FALSE; } if(swap) { unsigned int sblock_list[blocks]; memcpy(sblock_list, block_ptr, blocks * sizeof(unsigned int)); SQUASHFS_SWAP_INTS(block_list, sblock_list, blocks); } else memcpy(block_list, block_ptr, blocks * sizeof(unsigned int)); if((file_fd = open(pathname, O_CREAT | O_WRONLY, (mode_t) mode)) == -1) { ERROR("write_file: failed to create file %s, because %s\n", pathname, strerror(errno)); free(block_list); return FALSE; } for(i = 0; i < blocks; i++) { if((bytes = read_data_block(start, block_list[i], file_data)) == 0) { ERROR("write_file: failed to read data block 0x%llx\n", start); goto failure; } if(write(file_fd, file_data, bytes) < bytes) { ERROR("write_file: failed to write data block 0x%llx\n", start); goto failure; } start += SQUASHFS_COMPRESSED_SIZE_BLOCK(block_list[i]); } if(frag_bytes != 0) { char *fragment_data = read_fragment(fragment); if(fragment_data == NULL) goto failure; if(write(file_fd, fragment_data + offset, frag_bytes) < frag_bytes) { ERROR("write_file: failed to write fragment %d\n", fragment); goto failure; } } close(file_fd); return TRUE; failure: close(file_fd); free(block_list); return FALSE; } int create_inode(char *pathname, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { long long start = sBlk->inode_table_start + start_block; squashfs_inode_header header; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start), file_fd; TRACE("create_inode: pathname %s, start 0x%llx, offset %d\n", pathname, start, offset); if(bytes == -1) { ERROR("create_inode: inode block 0x%llx out of range!\n", start); return FALSE; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_base_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.base)); SQUASHFS_SWAP_BASE_INODE_HEADER(&header.base, &sinode, sizeof(squashfs_base_inode_header)); } else memcpy(&header.base, block_ptr, sizeof(header.base)); if(created_inode[header.base.inode_number - 1]) { TRACE("create_inode: hard link\n"); if(link(created_inode[header.base.inode_number - 1], pathname) == -1) { ERROR("create_inode: failed to create hardlink, because %s\n", strerror(errno)); return FALSE; } return TRUE; } switch(header.base.inode_type) { case SQUASHFS_FILE_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_reg_inode_header *inode = &header.reg; if(swap) { squashfs_reg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_REG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_LREG_TYPE: { unsigned int frag_bytes; unsigned int blocks; unsigned int offset; long long start; squashfs_lreg_inode_header *inode = &header.lreg; if(swap) { squashfs_lreg_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(sinode)); SQUASHFS_SWAP_LREG_INODE_HEADER(inode, &sinode); } else memcpy(inode, block_ptr, sizeof(*inode)); frag_bytes = inode->fragment == SQUASHFS_INVALID_FRAG ? 0 : inode->file_size % sBlk->block_size; offset = inode->offset; blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? (inode->file_size + sBlk->block_size - 1) >> sBlk->block_log : inode->file_size >> sBlk->block_log; start = inode->start_block; TRACE("create_inode: regular file, file_size %lld, blocks %d\n", inode->file_size, blocks); if(write_file(pathname, inode->fragment, frag_bytes, offset, blocks, start, block_ptr + sizeof(*inode), inode->mode)) { set_attributes(pathname, inode->mode, inode->uid, inode->guid, inode->mtime, FALSE); file_count ++; } break; } case SQUASHFS_SYMLINK_TYPE: { squashfs_symlink_inode_header *inodep = &header.symlink; char name[65536]; if(swap) { squashfs_symlink_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: symlink, symlink_size %d\n", inodep->symlink_size); strncpy(name, block_ptr + sizeof(squashfs_symlink_inode_header), inodep->symlink_size); name[inodep->symlink_size] = '\0'; if(symlink(name, pathname) == -1) { ERROR("create_inode: failed to create symlink %s, because %s\n", pathname, strerror(errno)); break; } if(geteuid() == 0) { uid_t uid_value = (uid_t) uid_table[inodep->uid]; uid_t guid_value = inodep->guid == SQUASHFS_GUIDS ? uid_value : (uid_t) guid_table[inodep->guid]; if(lchown(pathname, uid_value, guid_value) == -1) ERROR("create_inode: failed to change uid and gids on %s, because %s\n", pathname, strerror(errno)); } sym_count ++; break; } case SQUASHFS_BLKDEV_TYPE: case SQUASHFS_CHRDEV_TYPE: { squashfs_dev_inode_header *inodep = &header.dev; if(swap) { squashfs_dev_inode_header sinodep; memcpy(&sinodep, block_ptr, sizeof(sinodep)); SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, &sinodep); } else memcpy(inodep, block_ptr, sizeof(*inodep)); TRACE("create_inode: dev, rdev 0x%x\n", inodep->rdev); if(geteuid() == 0) { if(mknod(pathname, inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? S_IFCHR : S_IFBLK, makedev((inodep->rdev >> 8) & 0xff, inodep->rdev & 0xff)) == -1) { ERROR("create_inode: failed to create %s device %s, because %s\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } set_attributes(pathname, inodep->mode, inodep->uid, inodep->guid, inodep->mtime, TRUE); dev_count ++; } else ERROR("create_inode: could not create %s device %s, because you're not superuser!\n", inodep->inode_type == SQUASHFS_CHRDEV_TYPE ? "character" : "block", pathname, strerror(errno)); break; } case SQUASHFS_FIFO_TYPE: TRACE("create_inode: fifo\n"); if(mknod(pathname, S_IFIFO, 0) == -1) { ERROR("create_inode: failed to create fifo %s, because %s\n", pathname, strerror(errno)); break; } set_attributes(pathname, header.base.mode, header.base.uid, header.base.guid, header.base.mtime, TRUE); fifo_count ++; break; case SQUASHFS_SOCKET_TYPE: TRACE("create_inode: socket\n"); ERROR("create_inode: socket %s ignored\n", pathname); break; default: ERROR("Unknown inode type %d in create_inode_table!\n", header.base.inode_type); return FALSE; } created_inode[header.base.inode_number - 1] = strdup(pathname); return TRUE; } void uncompress_directory_table(long long start, long long end, squashfs_super_block *sBlk) { int bytes = 0, size = 0, res; while(start < end) { if(size - bytes < SQUASHFS_METADATA_SIZE && (directory_table = realloc(directory_table, size += SQUASHFS_METADATA_SIZE)) == NULL) EXIT_UNSQUASH("uncompress_directory_table: out of memory in realloc\n"); TRACE("uncompress_directory_table: reading block 0x%llx\n", start); add_entry(directory_table_hash, start, bytes); if((res = read_block(start, &start, directory_table + bytes, sBlk)) == 0) EXIT_UNSQUASH("uncompress_directory_table: failed to read block\n"); bytes += res; } } #define DIR_ENT_SIZE 16 struct dir_ent { char name[SQUASHFS_NAME_LEN + 1]; unsigned int start_block; unsigned int offset; unsigned int type; }; struct dir { int dir_count; int cur_entry; unsigned int mode; unsigned int uid; unsigned int guid; unsigned int mtime; struct dir_ent *dirs; }; struct dir *squashfs_openddir(unsigned int block_start, unsigned int offset, squashfs_super_block *sBlk) { squashfs_dir_header dirh; char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer; long long start = sBlk->inode_table_start + block_start; char *block_ptr; int bytes = lookup_entry(inode_table_hash, start); squashfs_inode_header header; int dir_count, size; struct dir_ent *new_dir; struct dir *dir; TRACE("squashfs_opendir: inode start block %d, offset %d\n", block_start, offset); if(bytes == -1) { ERROR("squashfs_opendir: inode block %d not found!\n", block_start); return NULL; } block_ptr = inode_table + bytes + offset; if(swap) { squashfs_dir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.dir)); SQUASHFS_SWAP_DIR_INODE_HEADER(&header.dir, &sinode); } else memcpy(&header.dir, block_ptr, sizeof(header.dir)); switch(header.dir.inode_type) { case SQUASHFS_DIR_TYPE: block_start = header.dir.start_block; offset = header.dir.offset; size = header.dir.file_size; break; case SQUASHFS_LDIR_TYPE: if(swap) { squashfs_ldir_inode_header sinode; memcpy(&sinode, block_ptr, sizeof(header.ldir)); SQUASHFS_SWAP_LDIR_INODE_HEADER(&header.ldir, &sinode); } else memcpy(&header.ldir, block_ptr, sizeof(header.ldir)); block_start = header.ldir.start_block; offset = header.ldir.offset; size = header.ldir.file_size; break; default: ERROR("squashfs_opendir: inode not a directory\n"); return NULL; } start = sBlk->directory_table_start + block_start; bytes = lookup_entry(directory_table_hash, start); if(bytes == -1) { ERROR("squashfs_opendir: directory block %d not found!\n", block_start); return NULL; } bytes += offset; size += bytes - 3; if((dir = malloc(sizeof(struct dir))) == NULL) { ERROR("squashfs_opendir: malloc failed!\n"); return NULL; } dir->dir_count = 0; dir->cur_entry = 0; dir->mode = header.dir.mode; dir->uid = header.dir.uid; dir->guid = header.dir.guid; dir->mtime = header.dir.mtime; dir->dirs = NULL; while(bytes < size) { if(swap) { squashfs_dir_header sdirh; memcpy(&sdirh, directory_table + bytes, sizeof(sdirh)); SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); } else memcpy(&dirh, directory_table + bytes, sizeof(dirh)); dir_count = dirh.count + 1; TRACE("squashfs_opendir: Read directory header @ byte position %d, %d directory entries\n", bytes, dir_count); bytes += sizeof(dirh); while(dir_count--) { if(swap) { squashfs_dir_entry sdire; memcpy(&sdire, directory_table + bytes, sizeof(sdire)); SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); } else memcpy(dire, directory_table + bytes, sizeof(dire)); bytes += sizeof(*dire); memcpy(dire->name, directory_table + bytes, dire->size + 1); dire->name[dire->size + 1] = '\0'; TRACE("squashfs_opendir: directory entry %s, inode %d:%d, type %d\n", dire->name, dirh.start_block, dire->offset, dire->type); if((dir->dir_count % DIR_ENT_SIZE) == 0) { if((new_dir = realloc(dir->dirs, (dir->dir_count + DIR_ENT_SIZE) * sizeof(struct dir_ent))) == NULL) { ERROR("squashfs_opendir: realloc failed!\n"); free(dir->dirs); free(dir); return NULL; } dir->dirs = new_dir; } strcpy(dir->dirs[dir->dir_count].name, dire->name); dir->dirs[dir->dir_count].start_block = dirh.start_block; dir->dirs[dir->dir_count].offset = dire->offset; dir->dirs[dir->dir_count].type = dire->type; dir->dir_count ++; bytes += dire->size + 1; } } return dir; } int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block, unsigned int *offset, unsigned int *type) { if(dir->cur_entry == dir->dir_count) return FALSE; *name = dir->dirs[dir->cur_entry].name; *start_block = dir->dirs[dir->cur_entry].start_block; *offset = dir->dirs[dir->cur_entry].offset; *type = dir->dirs[dir->cur_entry].type; dir->cur_entry ++; return TRUE; } void squashfs_closedir(struct dir *dir) { free(dir->dirs); free(dir); } int dir_scan(char *parent_name, unsigned int start_block, unsigned int offset, squashfs_super_block *sBlk) { struct dir *dir = squashfs_openddir(start_block, offset, sBlk); unsigned int type; char *name, pathname[1024]; if(dir == NULL) { ERROR("dir_scan: Failed to read directory %s (%x:%x)\n", parent_name, start_block, offset); return FALSE; } if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1) { ERROR("dir_scan: failed to open directory %s, because %s\n", parent_name, strerror(errno)); return FALSE; } while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", name, start_block, offset, type); strcat(strcat(strcpy(pathname, parent_name), "/"), name); if(lsonly || info) printf("%s\n", pathname); if(type == SQUASHFS_DIR_TYPE) dir_scan(pathname, start_block, offset, sBlk); else if(!lsonly) create_inode(pathname, start_block, offset, sBlk); } !lsonly && set_attributes(parent_name, dir->mode, dir->uid, dir->guid, dir->mtime, TRUE); squashfs_closedir(dir); dir_count ++; return TRUE; } int read_super(squashfs_super_block *sBlk, char *source) { read_bytes(SQUASHFS_START, sizeof(squashfs_super_block), (char *) sBlk); /* Check it is a SQUASHFS superblock */ swap = 0; if(sBlk->s_magic != SQUASHFS_MAGIC) { if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) { squashfs_super_block sblk; ERROR("Reading a different endian SQUASHFS filesystem on %s\n", source); SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk); memcpy(sBlk, &sblk, sizeof(squashfs_super_block)); swap = 1; } else { ERROR("Can't find a SQUASHFS superblock on %s\n", source); goto failed_mount; } } /* Check the MAJOR & MINOR versions */ if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) { ERROR("Major/Minor mismatch, filesystem on %s is (%d:%d)\n", source, sBlk->s_major, sBlk->s_minor); ERROR("I only support Squashfs 3.0 filesystems! Later releases will support older Squashfs filesystems\n"); goto failed_mount; } #if __BYTE_ORDER == __BIG_ENDIAN TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "little" : "big", source); #else TRACE("Found a valid %s endian SQUASHFS superblock on %s.\n", swap ? "big" : "little", source); #endif TRACE("\tInodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); TRACE("\tData is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : ""); TRACE("\tFragments are %scompressed\n", SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : ""); TRACE("\tCheck data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not"); TRACE("\tFragments are %s present in the filesystem\n", SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not" : ""); TRACE("\tAlways_use_fragments option is %s specified\n", SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not"); TRACE("\tDuplicates are %s removed\n", SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not"); TRACE("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n", sBlk->bytes_used / 1024.0, sBlk->bytes_used / (1024.0 * 1024.0)); TRACE("\tBlock size %d\n", sBlk->block_size); TRACE("\tNumber of fragments %d\n", sBlk->fragments); TRACE("\tNumber of inodes %d\n", sBlk->inodes); TRACE("\tNumber of uids %d\n", sBlk->no_uids); TRACE("\tNumber of gids %d\n", sBlk->no_guids); TRACE("sBlk->inode_table_start 0x%llx\n", sBlk->inode_table_start); TRACE("sBlk->directory_table_start 0x%llx\n", sBlk->directory_table_start); TRACE("sBlk->uid_start 0x%llx\n", sBlk->uid_start); TRACE("sBlk->fragment_table_start 0x%llx\n", sBlk->fragment_table_start); TRACE("\n"); return TRUE; failed_mount: return FALSE; } #define VERSION() \ printf("unsquashfs version 1.0 (2006/03/15)\n");\ printf("copyright (C) 2006 Phillip Lougher \n\n"); \ printf("This program is free software; you can redistribute it and/or\n");\ printf("modify it under the terms of the GNU General Public License\n");\ printf("as published by the Free Software Foundation; either version 2,\n");\ printf("or (at your option) any later version.\n\n");\ printf("This program is distributed in the hope that it will be useful,\n");\ printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");\ printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");\ printf("GNU General Public License for more details.\n"); int main(int argc, char *argv[]) { squashfs_super_block sBlk; char *dest = "squashfs-root"; int i, version = FALSE; for(i = 1; i < argc; i++) { if(*argv[i] != '-') break; if(strcmp(argv[i], "-version") == 0) { VERSION(); version = TRUE; } else if(strcmp(argv[i], "-info") == 0) info = TRUE; else if(strcmp(argv[i], "-ls") == 0) lsonly = TRUE; else if(strcmp(argv[i], "-dest") == 0) { if(++i == argc) goto options; dest = argv[i]; } } if(i == argc) { if(!version) { options: ERROR("SYNTAX: %s [-ls | -dest] filesystem\n", argv[0]); ERROR("\t-version\t\tprint version, licence and copyright information\n"); ERROR("\t-info\t\t\tprint files as they are unsquashed\n"); ERROR("\t-ls\t\t\tlist filesystem only\n"); ERROR("\t-dest \tunsquash to , default \"squashfs-root\"\n"); } exit(1); } if((fd = open(argv[i], O_RDONLY)) == -1) { ERROR("Could not open %s, because %s\n", argv[i], strerror(errno)); exit(1); } if(read_super(&sBlk, argv[i]) == FALSE) exit(1); block_size = sBlk.block_size; if((fragment_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate fragment_data\n"); if((file_data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate file_data"); if((data = malloc(block_size)) == NULL) EXIT_UNSQUASH("failed to allocate datan\n"); if((created_inode = malloc(sBlk.inodes * sizeof(char *))) == NULL) EXIT_UNSQUASH("failed to allocate created_inode\n"); memset(created_inode, 0, sBlk.inodes * sizeof(char *)); read_uids_guids(&sBlk); read_fragment_table(&sBlk); uncompress_inode_table(sBlk.inode_table_start, sBlk.directory_table_start, &sBlk); uncompress_directory_table(sBlk.directory_table_start, sBlk.fragment_table_start, &sBlk); dir_scan(dest, SQUASHFS_INODE_BLK(sBlk.root_inode), SQUASHFS_INODE_OFFSET(sBlk.root_inode), &sBlk); if(!lsonly) { printf("\n"); printf("created %d files\n", file_count); printf("created %d directories\n", dir_count); printf("created %d symlinks\n", sym_count); printf("created %d devices\n", dev_count); printf("created %d fifos\n", fifo_count); } } ================================================ FILE: src/tpl-tool/doc/Image_layout ================================================ Standard TP-Link firmware images for their router products consist of a header, kernel and a root filesystem in the format shown below. ------------------ | | | | | h | k | r | | e | e | o | | a | r | o | | d | n | t | | r | e | f | | | l | s | | | | | ------------------ The header is 0x200 bytes in length. The kernel is padded to 0x100000 and rootfs to either 0x3C0000 or 0x7C0000 depending on the device. Firmware images which include a bootloader have an 'image within image' structure consisting of a 'standard' kernel/rootfs image within a larger image as shown below. ----------------------------------------- | | | | | | | ------------------- | | | | | | | | | | h | b | | h | k | r | | | e | o | | e | e | o | | | a | o | | a | r | o | | | d | t | | d | n | t | | | r | l | | e | e | f | | | | d | | r | l | s | | | | r | | | | | | | | | ------------------- | | | | | ----------------------------------------- The header layout for both types of image is the same with the exception of the bootloader length and the MD5Key used to salt the image checksum. The layout shown below is for a 'standard' image which does not include a bootloader. Header version 00000000 01000000 Image vendor 00000004 TP-LINK Technologies Image version 0000001C ver. 1.0 Product Id 00000040 25430001 Product Version 00000044 00000001 00000048 00 00 00 00 Image checksum 0000004C df 9b c7 3f 89 d6 13 da 7f c3 c9 40 ea bc c2 0d (salted MD5) 0000005C 00 00 00 00 Kernel checksum 00000060 a3 88 3e 97 46 17 a3 45 54 b6 75 6e 53 6b fa 03 (salted MD5 ?) 00000070 00 00 00 00 Kernel load address 00000074 80002000 Kernel entrypoint 00000078 801a0910 Image length 0000007C 007c0000 Kernel offset 00000080 00000200 Kernel length 00000084 000be024 Rootfs offset 00000088 00100000 Rootfs length 0000008C 006c0000 Bootloader offset 00000090 00000000 Bootloader length 00000094 00000000 Firmware version 00000098 0003 (3.13.6) 0000009A 000d 0000009C 0006 0000009E 00 00 00 00 * 000001FC 00 00 00 00 Notes: I was unable to determine precisely how the kernel checksum is calculated nor the MD5Key used as this is not referred to anywhere in the TP-Link router program (/usr/bin/httpd). However I am certain that this is the kernel checksum as I have two pairs of images with the same checksum in this position, from two different devices. Extracting and decompressing the kernel from these images gave me four files with the same MD5 hash. It seems obvious to me that the difference between the pairs is due to the different product ids in the header. License: Copyright (c) 2012 Jonathan McGowan This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 or later as published by the Free Software Foundation. ================================================ FILE: src/tpl-tool/doc/Readme ================================================ Description: tpl-tool is a tool for extracting and rebuilding official TP-Link firmware images for their router products. It has been successfully tested with twenty four different images from seven different products. This is only a very small selection of the hundred and something available from the TP-Link website. However it should work with any official or third-party firmware image which uses the same format with the exception of OpenWrt images. OpenWrt images do NOT have a 'standard' TP-Link image layout despite having a valid header and do NOT extract correctly. Usage: tpl-tool